diff --git a/AUTHORS b/AUTHORS index de9f1625..c60abf4 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -448,6 +448,7 @@ Henrique de Carvalho <decarv.henrique@gmail.com> Henrique Limas <henrique.ramos.limas@gmail.com> Himanshu Joshi <h.joshi@samsung.com> +Himanshu Nayak <himanshu.nayak@amd.corp-partner.google.com> Hiroki Oshima <hiroki.oshima@gmail.com> Hiroyuki Matsuda <gsittyz@gmail.com> Ho Cheung <uioptt24@gmail.com>
diff --git a/BUILD.gn b/BUILD.gn index e8b687f..7cfadb4 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1398,7 +1398,6 @@ "//third_party/blink/web_tests/view-transition/", "//third_party/blink/web_tests/virtual/", "//third_party/blink/web_tests/virtualkeyboard/", - "//third_party/blink/web_tests/wake-lock/", "//third_party/blink/web_tests/wasm/", "//third_party/blink/web_tests/webaudio/", "//third_party/blink/web_tests/webexposed/",
diff --git a/DEPS b/DEPS index ce55f7e..2784929 100644 --- a/DEPS +++ b/DEPS
@@ -229,7 +229,7 @@ # # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab - 'lacros_sdk_version': '15324.0.0', + 'lacros_sdk_version': '15326.0.0', # Generate location tag metadata to include in tests result data uploaded # to ResultDB. This isn't needed on some configs and the tool that generates @@ -241,7 +241,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:36cf4b54527c49aca7ed3023995a081e14f1852a', + 'luci_go': 'git_revision:221383f749a2c5b8587449d3d2e4982857daa9e7', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -304,15 +304,15 @@ # 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': 'c4b171fe5668a522c222b0777afefcb3cbd8a2ac', + 'skia_revision': 'd178e7d7a2049743f1cea2671dce32d7332061b5', # 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': '7256aca77c6c1a7b4b9007dabd5fd74e8dac1b47', + 'v8_revision': 'c77793a2ee5bfa7c5226dd8f622bf331b97a5a25', # 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': 'f26cfec911f775949a9179a4f1b65da021340945', + 'angle_revision': 'c9094ca6b3e31454056432b6ab4f9bec06665c9b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -320,7 +320,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'ddc5f79a33a19c09cc9bc855e5a34b67417dcd3d', + 'pdfium_revision': 'd087df316170b2d8757487b1015244384624478e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -331,7 +331,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:11.20230125.1.1', + 'fuchsia_version': 'version:11.20230126.1.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -375,7 +375,7 @@ # 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': '45986b07facfe4cde512b52897ae413617896cc0', + 'catapult_revision': 'abaad53f0c4e104ab630b314af2902ad83b82c8c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -383,7 +383,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '9f3432a40c557b3faa3da01fc2ef84e4cf60e66a', + 'devtools_frontend_revision': 'ea96b9128f40d4612b2e031799c5bd2bc7868db5', # 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. @@ -419,11 +419,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '58dd079e466579f5c4c5fe35d41aff9bd16cd555', + 'dawn_revision': '42c5b2f6755317073866ec00dd59396ee9175f8b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'ba1faf0cdc7ae5aed79f907d16eacaeac22b98f2', + 'quiche_revision': '566b33c9fa5b1723db04be3d40dcaf102344c323', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -443,7 +443,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '7f34968b7850b2bd575601bcab8f745220cab8ff', + 'nearby_revision': 'f4d85f9b9012fda464c06d7dc9881c02af7a6055', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -483,7 +483,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '1dfd0022c4d7aa370a8572d4710558ff8684d7a3', + 'libcxx_revision': '1127c78cf90cf253be614a1e1d3645da57edbeb4', # GN CIPD package version. 'gn_version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8', @@ -770,12 +770,12 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - '2684540a00a1b31d6bc5a5d9e55021562cd10ce3', + '63cff6b5da0dff096aa44123a227bc85f12b4250', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '03e9daab0fdba4143e91afb7d8b7ee6c881c3f73', + 'url': Var('chromium_git') + '/website.git' + '@' + '7e351332addd1fca691bb524c976a56f17e3eb95', }, 'src/ios/third_party/earl_grey2/src': { @@ -869,7 +869,7 @@ 'packages': [ { 'package': 'chromium/rts/model/linux-amd64', - 'version': 'xnGS3ACHEm1h2Whq5EIE2zA5Mxq4brKQF70sob2KMFMC', + 'version': 'bCwganuATTWjTe2ahjxynn8rnTuSw900jtLOYmi3kV4C', }, ], 'dep_type': 'cipd', @@ -880,7 +880,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'e5OQW3J7UrdhSg0Fm7i9obiy2o_AEUL_ReMt-UgADdkC', + 'version': 'ms15aJhiLzrF61zOZxq2jcESbsF3FFYtCS8R290t8JsC', }, ], 'dep_type': 'cipd', @@ -891,7 +891,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'T7VgmL-oMb4fpemJKLZ7Jia4M0K7i6U8cTnqMEcLBDYC', + 'version': 'xILgcx3FOZDE8fCy3EXmw76GOIrdmlVb3aQ5dUSq8x8C', }, ], 'dep_type': 'cipd', @@ -959,7 +959,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '3nXDIlFQ-oAo4egDVeC0GbueTl4mOfPrEDzT5jgDEK8C', + 'version': '8KUWsjmvRQJlzdaro14SgP8nok3-kHY2h00BEjXLJqQC', }, ], 'condition': 'checkout_android', @@ -1030,7 +1030,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': '0X1mSg1M9Q3Dv6pcOnX0mK0YR_LyTxyT3oRbYk5uxQ8C', + 'version': 'EPj7vnLteKz9kMQ6x4ZPaM5E20Bt4I0wTdrxdBpruZMC', }, ], 'condition': 'checkout_android', @@ -1176,7 +1176,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '252fb8286918ed6ccbf157c424b4cb97c7dd23cd', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd60807b98527df86e516532b8e2a62a1cb44c128', 'condition': 'checkout_chromeos', }, @@ -1204,13 +1204,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c710e2d56a813d27d2368eb0e7e292bd2f59519f', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '44e9bee34fcc7e8dedc2a988750c9d7cc7f73eba', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'ac4f163294daa437967536cd83b3ede02f39a619', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '396e9c2fca31c3af72fab3653c774f9a6da15ba8', 'condition': 'checkout_src_internal', }, @@ -1243,7 +1243,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + Var('ffmpeg_revision'), 'src/third_party/flac': - Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596', + Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '689da3a7ed50af7448c3f1961d1791c7c1d9c85c', 'src/third_party/flatbuffers/src': Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'b47ba1d5ffae3bd4d5eaad615e33d7cc5c1e3d4a', @@ -1403,7 +1403,7 @@ 'packages': [ { 'package': 'chromium/third_party/jdk', - 'version': 'egbcSHbmF1XZQbKxp_PQiGLFWlQK65krTGqQE-Bj4j8C', + 'version': '-FR8HTNcMfxy7J2HUaWVa0QmEE4f68iotzvFbqOj2LEC', }, ], # Needed on Linux for use on chromium_presubmit (for checkstyle). @@ -1411,6 +1411,19 @@ 'dep_type': 'cipd', }, + # Deprecated - only use for tools which are broken our real JDK. + 'src/third_party/jdk11': { + 'packages': [ + { + 'package': 'chromium/third_party/jdk', + # Do not update this hash - any newer hash will point to JDK17+. + 'version': 'egbcSHbmF1XZQbKxp_PQiGLFWlQK65krTGqQE-Bj4j8C', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/jsoncpp/source': Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + '42e892d96e47b1f6e29844cc705e148ec4856448', # release 1.9.4 @@ -1638,7 +1651,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'db956674bbdfbaab5acdd3fdb4117c2fef5527e9', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + 'bcee0c4761291983173e390885193aa3c3ea7148', + Var('chromium_git') + '/openscreen' + '@' + 'eca304d29cee3f9d045fd0dd36f147a91a367c75', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245', @@ -1655,7 +1668,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ee03e391a1003e8cdc7ce7e07f14b6872883fd1c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '7706133c5b028b83ce0cf64ce340ebbf757305e4', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1695,7 +1708,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'SCuPfdKTpEJfVbWzckpmWx125Zf3pO-4RitqcfXX-RQC', + 'version': 'lhnuNLpWpWBVM6efX0iIg5i9ztfW8VKpMvkyfWCxfr0C', }, ], 'condition': 'checkout_android', @@ -1800,7 +1813,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@71bd1907ea2f4e3d03f9fee926bb6cab5b8a6a2b', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@243deb3abd84f442957dc5394745d25482ff791b', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1840,7 +1853,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ad8abf400d8d23fb04bdcf1f654bccb6625db7b4', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '5671c6410395d6bc3f6041cc15d16ca256688c8e', + Var('webrtc_git') + '/src.git' + '@' + '94d5f6af62a70cb500d43730d0870ed860ac79b6', # 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. @@ -1867,7 +1880,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'bOyplOZW_1JEVFUYAKgbKGWaIlUNmN1YWkzd5HXMjbMC', + 'version': 'PZOpm-VdLUuaVE8seo910YRCnqv7Y2BkPcrmUs13RMAC', }, ], 'dep_type': 'cipd', @@ -1877,7 +1890,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'eBpAa_OebMnB2kWt7jt2enLuznrQvGveRaHpV1a3y1AC', + 'version': 'qp3u_bn43vFlG3HHG61Co9eOeo52m6SWIw099mHqt9EC', }, ], 'dep_type': 'cipd', @@ -1888,7 +1901,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': '8qZDLAMyGda5EhgtPxm1HRsnplhGtP0Mny-vLqo--TcC', + 'version': 'aZ8KYJUPYrRq4f7-Td3nt0et_16S06A0vovOn2c85tIC', }, ], 'dep_type': 'cipd', @@ -1899,7 +1912,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'BUfxeGjbFbRJh3xW3sHUYhB0CNMviWBhCtud4vytIrEC', + 'version': 'JtcfJFsvsUuaaIajqvwETn8j5hxOSC_YLDszV96Ukn8C', }, ], 'dep_type': 'cipd', @@ -1910,7 +1923,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6d740d36bf274cefca0698dab445cdf541d50f7c', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@00a9a866febc29790d835f3bef908e97757a1e93', 'condition': 'checkout_src_internal', }, @@ -1940,7 +1953,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'lhhymPxLgpNiHKsHFh4rUwx4vPVqpd_QMBZGIhHePusC', + 'version': 'J19Uq07iO__IsduQFotOfHNdiRWoyIQc4UgK1HpMFU8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1951,7 +1964,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'OTdFSWASxeY5gUcGB3Xi-MB8o3Q_zgeteL7p_dLSc_cC', + 'version': 'CHpgn1-7IChFiK96I1-giMbXe-Cl9XQiwH3aHwCGzYwC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1962,7 +1975,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'mOGkd2s46jvj37CK6ZuCIX2LSetf3yzXCPiX09K5XE8C', + 'version': 'ufJ9DwqTBE76l81FUQQ2JOIG1ely5QRDFuwz3ccJIRIC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS index 5d6eef9e..0e1c0147 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -833,6 +833,10 @@ 'clang_update': { 'filepath': 'tools/clang/scripts/update.py' }, + 'client_hints': { + 'filepath': 'client_hints|user_agent_utils|content/common/user_agent.cc|' + 'content/public/common/user_agent.h', + }, 'clipboard': { 'filepath': 'clipboard|dnd|drag|drop', }, @@ -2578,6 +2582,8 @@ 'thakis@chromium.org', 'thestig@chromium.org', 'ukai+watch@chromium.org'], + 'client_hints': ['victortan@chromium.org', + 'miketaylr@chromium.org'], 'clipboard': ['dcheng@chromium.org'], 'components_deps': ['droger+watchlist@chromium.org'], 'compositor_animator': ['mdjones+watch@chromium.org'],
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 0c8c5189..be1e242 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -13,6 +13,7 @@ import("//build/config/locales.gni") import("//chrome/android/chrome_common_shared_library.gni") import("//chrome/android/chrome_public_apk_tmpl.gni") +import("//chrome/android/expectations/expectations.gni") import("//chrome/android/trichrome.gni") import("//components/safe_browsing/buildflags.gni") import("//components/spellcheck/spellcheck_build_features.gni") @@ -33,13 +34,6 @@ "$target_gen_dir/system_webview_pak_allowlist.txt" } -# Having //clank present causes different flags because of how play services -# is wired up. -# The channel is required because manifest entries vary based on channel. -_verify_android_configuration = - !is_java_debug && !enable_chrome_android_internal && - android_channel == "stable" - template("standalone_system_webview_apk_tmpl") { system_webview_apk_or_module_tmpl(target_name) { forward_variables_from(invoker, "*") @@ -107,7 +101,7 @@ is_base_module = true bundle_target = ":system_webview_bundle" - if (_verify_android_configuration) { + if (enable_manifest_verification) { expected_android_manifest = "expectations/system_webview_bundle.AndroidManifest.expected" } @@ -248,7 +242,7 @@ android_manifest_dep = "//android_webview/nonembedded:trichrome_webview_manifest" - if (_verify_android_configuration) { + if (enable_manifest_verification) { expected_android_manifest = "expectations/trichrome_webview_bundle.AndroidManifest.expected" } @@ -261,6 +255,10 @@ uncompress_dex = true min_sdk_version = 29 static_library_provider = "//chrome/android:trichrome_library_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } } @@ -271,6 +269,10 @@ uncompress_dex = true min_sdk_version = 29 static_library_provider = "//chrome/android:trichrome_library_64_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } trichrome_webview_tmpl("trichrome_webview_64_base_bundle_module") { @@ -337,6 +339,10 @@ uncompress_dex = true min_sdk_version = 29 static_library_provider = "//chrome/android:trichrome_library_64_32_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } } @@ -375,6 +381,10 @@ uncompress_dex = true min_sdk_version = 29 static_library_provider = "//chrome/android:trichrome_library_32_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } } }
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index c61a698..f0cfc55 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -200,8 +200,9 @@ // If accept languages do not contain en-US, add in en-US which will be // used with a lower q-value. - if (locales_string.find("en-US") == std::string::npos) + if (locales_string.find("en-US") == std::string::npos) { locales_string += ",en-US"; + } return locales_string; } @@ -331,8 +332,9 @@ return !IsAndroidSpecialFileUrl(url); } for (const char* supported_protocol : kProtocolList) { - if (scheme == supported_protocol) + if (scheme == supported_protocol) { return true; + } } return false; } @@ -424,8 +426,9 @@ std::unique_ptr<content::ClientCertificateDelegate> delegate) { AwContentsClientBridge* client = AwContentsClientBridge::FromWebContents(web_contents); - if (client) + if (client) { client->SelectClientCertificate(cert_request_info, std::move(delegate)); + } return base::OnceClosure(); } @@ -557,8 +560,9 @@ navigation_interception::InterceptNavigationDelegate:: MaybeCreateThrottleFor(navigation_handle, navigation_interception::SynchronyMode::kSync); - if (intercept_navigation_throttle) + if (intercept_navigation_throttle) { throttles.push_back(std::move(intercept_navigation_throttle)); + } throttles.push_back(std::make_unique<PolicyBlocklistNavigationThrottle>( navigation_handle, @@ -567,8 +571,9 @@ std::unique_ptr<AwSafeBrowsingNavigationThrottle> safe_browsing_throttle = AwSafeBrowsingNavigationThrottle::MaybeCreateThrottleFor( navigation_handle); - if (safe_browsing_throttle) + if (safe_browsing_throttle) { throttles.push_back(std::move(safe_browsing_throttle)); + } return throttles; } @@ -607,7 +612,8 @@ // TODO(crbug.com/1033760): rt_lookup_service is // used to perform real time URL check, which is gated by UKM opted-in. // Since AW currently doesn't support UKM, this feature is not enabled. - /* rt_lookup_service */ nullptr)); + /* rt_lookup_service */ nullptr, + /* hash_realtime_service */ nullptr)); if (request.destination == network::mojom::RequestDestination::kDocument) { const bool is_load_url = @@ -654,15 +660,17 @@ *ignore_navigation = false; // Only GETs can be overridden. - if (request_method != "GET") + if (request_method != "GET") { return true; + } bool application_initiated = browser_initiated || transition & ui::PAGE_TRANSITION_FORWARD_BACK; // Don't offer application-initiated navigations unless it's a redirect. - if (application_initiated && !is_redirect) + if (application_initiated && !is_redirect) { return true; + } // For HTTP schemes, only top-level navigations can be overridden. Similarly, // WebView Classic lets app override only top level about:blank navigations. @@ -678,17 +686,20 @@ if (!is_outermost_main_frame && (gurl.SchemeIs(url::kHttpScheme) || gurl.SchemeIs(url::kHttpsScheme) || gurl.SchemeIs(url::kAboutScheme) || - gurl.SchemeIs(url::kUuidInPackageScheme))) + gurl.SchemeIs(url::kUuidInPackageScheme))) { return true; + } WebContents* web_contents = WebContents::FromFrameTreeNodeId(frame_tree_node_id); - if (web_contents == nullptr) + if (web_contents == nullptr) { return true; + } AwContentsClientBridge* client_bridge = AwContentsClientBridge::FromWebContents(web_contents); - if (client_bridge == nullptr) + if (client_bridge == nullptr) { return true; + } std::u16string url = base::UTF8ToUTF16(gurl.possibly_invalid_spec()); @@ -771,7 +782,7 @@ new android_webview::AwProxyingURLLoaderFactory( frame_tree_node_id, std::move(receiver), mojo::NullRemote(), true /* intercept_only */, absl::nullopt /* security_options */, - nullptr /* xrw_allowlist_matcher */); + nullptr /* xrw_allowlist_matcher */, url::Origin()); } else { content::GetIOThreadTaskRunner({})->PostTask( FROM_HERE, @@ -783,7 +794,7 @@ frame_tree_node_id, std::move(receiver), mojo::NullRemote(), true /* intercept_only */, absl::nullopt /* security_options */, - nullptr /* xrw_allowlist_matcher */); + nullptr /* xrw_allowlist_matcher */, url::Origin()); }, std::move(receiver), frame_tree_node_id)); } @@ -930,16 +941,21 @@ auto xrw_allowlist_matcher = AwSettings::FromWebContents(web_contents)->xrw_allowlist_matcher(); + url::Origin top_frame_origin = + frame->GetOutermostMainFrame()->GetLastCommittedOrigin(); + content::GetIOThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&AwProxyingURLLoaderFactory::CreateProxy, frame->GetFrameTreeNodeId(), std::move(proxied_receiver), std::move(target_factory_remote), security_options, - std::move(xrw_allowlist_matcher))); + std::move(xrw_allowlist_matcher), + std::move(top_frame_origin))); } else { // A service worker and worker subresources set nullptr to |frame|, and // work without seeing the AllowUniversalAccessFromFileURLs setting. So, // we don't pass a valid |security_options| here. + // At the same time, we also don't have a valid |top_frame_origin|. AwBrowserContext* aw_browser_context = static_cast<AwBrowserContext*>(browser_context); content::GetIOThreadTaskRunner({})->PostTask( @@ -949,7 +965,8 @@ content::RenderFrameHost::kNoFrameTreeNodeId, std::move(proxied_receiver), std::move(target_factory_remote), absl::nullopt /* security_options */, - aw_browser_context->service_worker_xrw_allowlist_matcher())); + aw_browser_context->service_worker_xrw_allowlist_matcher(), + url::Origin() /* top_level_origin */)); } return true; } @@ -1008,8 +1025,9 @@ content::ContentBrowserClient::WideColorGamutHeuristic AwContentBrowserClient::GetWideColorGamutHeuristic() { - if (base::FeatureList::IsEnabled(features::kWebViewWideColorGamutSupport)) + if (base::FeatureList::IsEnabled(features::kWebViewWideColorGamutSupport)) { return WideColorGamutHeuristic::kUseWindow; + } if (display::HasForceDisplayColorProfile() && display::GetForcedDisplayColorProfile() ==
diff --git a/android_webview/browser/aw_contents_client_bridge.h b/android_webview/browser/aw_contents_client_bridge.h index 10b7c075..a7700b2 100644 --- a/android_webview/browser/aw_contents_client_bridge.h +++ b/android_webview/browser/aw_contents_client_bridge.h
@@ -13,7 +13,6 @@ #include "base/android/scoped_java_ref.h" #include "base/containers/id_map.h" #include "base/functional/callback.h" -#include "base/supports_user_data.h" #include "components/security_interstitials/core/unsafe_resource.h" #include "content/public/browser/certificate_request_result_type.h" #include "content/public/browser/javascript_dialog_manager.h"
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc index f8561a42..96f8a2d 100644 --- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc +++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -47,7 +47,9 @@ #include "services/network/public/mojom/early_hints.mojom.h" #include "services/network/public/mojom/fetch_api.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" #include "url/gurl.h" +#include "url/origin.h" namespace android_webview { @@ -83,7 +85,8 @@ bool intercept_only, absl::optional<AwProxyingURLLoaderFactory::SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher); + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin); InterceptedRequest(const InterceptedRequest&) = delete; InterceptedRequest& operator=(const InterceptedRequest&) = delete; @@ -195,6 +198,7 @@ mojo::Remote<network::mojom::URLLoader> target_loader_; mojo::Remote<network::mojom::URLLoaderFactory> target_factory_; scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_; + url::Origin top_frame_origin_; base::WeakPtrFactory<InterceptedRequest> weak_factory_{this}; }; @@ -290,7 +294,8 @@ bool intercept_only, absl::optional<AwProxyingURLLoaderFactory::SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher) + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin) : frame_tree_node_id_(frame_tree_node_id), request_id_(request_id), options_(options), @@ -303,7 +308,8 @@ proxied_loader_receiver_(this, std::move(loader_receiver)), target_client_(std::move(client)), target_factory_(std::move(target_factory)), - xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)) { + xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)), + top_frame_origin_(std::move(top_frame_origin)) { // If there is a client error, clean up the request. target_client_.set_disconnect_handler(base::BindOnce( &InterceptedRequest::OnURLLoaderClientError, base::Unretained(this))); @@ -321,6 +327,7 @@ // Persistent Origin Trials can only be checked on the UI thread. // |result_args| is owned by a BarrierClosure that executes after this call. void CheckXrwOriginTrialOnUiThread(GURL request_url, + url::Origin partition_origin, InterceptResponseReceivedArgs* result_args) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::OriginTrialsControllerDelegate* delegate = @@ -329,8 +336,8 @@ return; result_args->xrw_origin_trial_enabled = delegate->IsTrialPersistedForOrigin( - url::Origin::Create(request_url), "WebViewXRequestedWithDeprecation", - base::Time::Now()); + url::Origin::Create(request_url), partition_origin, + "WebViewXRequestedWithDeprecation", base::Time::Now()); base::UmaHistogramBoolean( "Android.WebView.RequestedWithHeader.OriginTrialEnabled", result_args->xrw_origin_trial_enabled); @@ -347,11 +354,13 @@ // for |request_url|, saving the result in |result_args|. // |result_args| is owned by the |done_callback|. void CheckXrwOriginTrialAsync(GURL request_url, + url::Origin partition_origin, InterceptResponseReceivedArgs* result_args, base::OnceClosure done_callback) { content::GetUIThreadTaskRunner({})->PostTaskAndReply( FROM_HERE, base::BindOnce(&CheckXrwOriginTrialOnUiThread, request_url, + std::move(partition_origin), base::Unretained(result_args)), std::move(done_callback)); } @@ -388,13 +397,22 @@ request_.load_flags = UpdateLoadFlags(request_.load_flags, io_thread_client.get()); + + url::Origin partition_origin = top_frame_origin_; + // Main frame navigation request should partition by the request URL. + if (static_cast<blink::mojom::ResourceType>(request_.resource_type) == + blink::mojom::ResourceType::kMainFrame) { + partition_origin = url::Origin::Create(request_.url); + } if (!io_thread_client || ShouldNotInterceptRequest()) { // equivalent to no interception std::unique_ptr<InterceptResponseReceivedArgs> intercept_response_received_args = std::make_unique<InterceptResponseReceivedArgs>(); + CheckXrwOriginTrialAsync( - request_.url, intercept_response_received_args.get(), + request_.url, std::move(partition_origin), + intercept_response_received_args.get(), base::BindOnce(&InterceptedRequest::InterceptResponseReceived, weak_factory_.GetWeakPtr(), std::move(intercept_response_received_args))); @@ -419,7 +437,8 @@ weak_factory_.GetWeakPtr(), std::move(call_args))); } - CheckXrwOriginTrialAsync(request_.url, intercept_response_received_args, + CheckXrwOriginTrialAsync(request_.url, std::move(partition_origin), + intercept_response_received_args, arg_ready_closure); // TODO: verify the case when WebContents::RenderFrameDeleted is called @@ -866,11 +885,13 @@ mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote, bool intercept_only, absl::optional<SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher) + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin) : frame_tree_node_id_(frame_tree_node_id), intercept_only_(intercept_only), security_options_(security_options), - xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)) { + xrw_allowlist_matcher_(std::move(xrw_allowlist_matcher)), + top_frame_origin_(std::move(top_frame_origin)) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(!(intercept_only_ && target_factory_remote)); if (target_factory_remote) { @@ -885,7 +906,7 @@ base::Unretained(this))); } -AwProxyingURLLoaderFactory::~AwProxyingURLLoaderFactory() {} +AwProxyingURLLoaderFactory::~AwProxyingURLLoaderFactory() = default; // static void AwProxyingURLLoaderFactory::CreateProxy( @@ -893,14 +914,15 @@ mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader_receiver, mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote, absl::optional<SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher) { + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // will manage its own lifetime - new AwProxyingURLLoaderFactory(frame_tree_node_id, std::move(loader_receiver), - std::move(target_factory_remote), false, - security_options, - std::move(xrw_allowlist_matcher)); + new AwProxyingURLLoaderFactory( + frame_tree_node_id, std::move(loader_receiver), + std::move(target_factory_remote), false, security_options, + std::move(xrw_allowlist_matcher), std::move(top_frame_origin)); } void AwProxyingURLLoaderFactory::CreateLoaderAndStart( @@ -938,7 +960,8 @@ InterceptedRequest* req = new InterceptedRequest( frame_tree_node_id_, request_id, options, request, traffic_annotation, std::move(loader), std::move(client), std::move(target_factory_clone), - intercept_only_, security_options_, xrw_allowlist_matcher_); + intercept_only_, security_options_, xrw_allowlist_matcher_, + top_frame_origin_); req->Restart(); }
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h index 798bb7f..022540a 100644 --- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h +++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -15,6 +15,7 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/origin.h" namespace net { struct MutableNetworkTrafficAnnotationTag; @@ -71,7 +72,8 @@ target_factory_remote, bool intercept_only, absl::optional<SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher); + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin); AwProxyingURLLoaderFactory(const AwProxyingURLLoaderFactory&) = delete; AwProxyingURLLoaderFactory& operator=(const AwProxyingURLLoaderFactory&) = @@ -86,7 +88,8 @@ mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote, absl::optional<SecurityOptions> security_options, - scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher); + scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher, + url::Origin top_frame_origin); void CreateLoaderAndStart( mojo::PendingReceiver<network::mojom::URLLoader> loader, @@ -117,6 +120,8 @@ scoped_refptr<AwContentsOriginMatcher> xrw_allowlist_matcher_; + url::Origin top_frame_origin_; + base::WeakPtrFactory<AwProxyingURLLoaderFactory> weak_factory_{this}; };
diff --git a/android_webview/expectations/trichrome_webview_32_bundle.arm64.libs_and_assets.expected b/android_webview/expectations/trichrome_webview_32_bundle.arm64.libs_and_assets.expected new file mode 100644 index 0000000..508a001d --- /dev/null +++ b/android_webview/expectations/trichrome_webview_32_bundle.arm64.libs_and_assets.expected
@@ -0,0 +1,168 @@ +apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 +apk_path=assets/locales/af.pak, compress=False, alignment=4 +apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/locales/ar.pak, compress=False, alignment=4 +apk_path=assets/locales/as.pak, compress=False, alignment=4 +apk_path=assets/locales/az.pak, compress=False, alignment=4 +apk_path=assets/locales/be.pak, compress=False, alignment=4 +apk_path=assets/locales/bg.pak, compress=False, alignment=4 +apk_path=assets/locales/bn.pak, compress=False, alignment=4 +apk_path=assets/locales/bs.pak, compress=False, alignment=4 +apk_path=assets/locales/ca.pak, compress=False, alignment=4 +apk_path=assets/locales/cs.pak, compress=False, alignment=4 +apk_path=assets/locales/da.pak, compress=False, alignment=4 +apk_path=assets/locales/de.pak, compress=False, alignment=4 +apk_path=assets/locales/el.pak, compress=False, alignment=4 +apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/locales/es.pak, compress=False, alignment=4 +apk_path=assets/locales/et.pak, compress=False, alignment=4 +apk_path=assets/locales/eu.pak, compress=False, alignment=4 +apk_path=assets/locales/fa.pak, compress=False, alignment=4 +apk_path=assets/locales/fi.pak, compress=False, alignment=4 +apk_path=assets/locales/fil.pak, compress=False, alignment=4 +apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/locales/fr.pak, compress=False, alignment=4 +apk_path=assets/locales/gl.pak, compress=False, alignment=4 +apk_path=assets/locales/gu.pak, compress=False, alignment=4 +apk_path=assets/locales/he.pak, compress=False, alignment=4 +apk_path=assets/locales/hi.pak, compress=False, alignment=4 +apk_path=assets/locales/hr.pak, compress=False, alignment=4 +apk_path=assets/locales/hu.pak, compress=False, alignment=4 +apk_path=assets/locales/hy.pak, compress=False, alignment=4 +apk_path=assets/locales/id.pak, compress=False, alignment=4 +apk_path=assets/locales/is.pak, compress=False, alignment=4 +apk_path=assets/locales/it.pak, compress=False, alignment=4 +apk_path=assets/locales/ja.pak, compress=False, alignment=4 +apk_path=assets/locales/ka.pak, compress=False, alignment=4 +apk_path=assets/locales/kk.pak, compress=False, alignment=4 +apk_path=assets/locales/km.pak, compress=False, alignment=4 +apk_path=assets/locales/kn.pak, compress=False, alignment=4 +apk_path=assets/locales/ko.pak, compress=False, alignment=4 +apk_path=assets/locales/ky.pak, compress=False, alignment=4 +apk_path=assets/locales/lo.pak, compress=False, alignment=4 +apk_path=assets/locales/lt.pak, compress=False, alignment=4 +apk_path=assets/locales/lv.pak, compress=False, alignment=4 +apk_path=assets/locales/mk.pak, compress=False, alignment=4 +apk_path=assets/locales/ml.pak, compress=False, alignment=4 +apk_path=assets/locales/mn.pak, compress=False, alignment=4 +apk_path=assets/locales/mr.pak, compress=False, alignment=4 +apk_path=assets/locales/ms.pak, compress=False, alignment=4 +apk_path=assets/locales/my.pak, compress=False, alignment=4 +apk_path=assets/locales/nb.pak, compress=False, alignment=4 +apk_path=assets/locales/ne.pak, compress=False, alignment=4 +apk_path=assets/locales/nl.pak, compress=False, alignment=4 +apk_path=assets/locales/or.pak, compress=False, alignment=4 +apk_path=assets/locales/pa.pak, compress=False, alignment=4 +apk_path=assets/locales/pl.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/locales/ro.pak, compress=False, alignment=4 +apk_path=assets/locales/ru.pak, compress=False, alignment=4 +apk_path=assets/locales/si.pak, compress=False, alignment=4 +apk_path=assets/locales/sk.pak, compress=False, alignment=4 +apk_path=assets/locales/sl.pak, compress=False, alignment=4 +apk_path=assets/locales/sq.pak, compress=False, alignment=4 +apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/locales/sr.pak, compress=False, alignment=4 +apk_path=assets/locales/sv.pak, compress=False, alignment=4 +apk_path=assets/locales/sw.pak, compress=False, alignment=4 +apk_path=assets/locales/ta.pak, compress=False, alignment=4 +apk_path=assets/locales/te.pak, compress=False, alignment=4 +apk_path=assets/locales/th.pak, compress=False, alignment=4 +apk_path=assets/locales/tr.pak, compress=False, alignment=4 +apk_path=assets/locales/uk.pak, compress=False, alignment=4 +apk_path=assets/locales/ur.pak, compress=False, alignment=4 +apk_path=assets/locales/uz.pak, compress=False, alignment=4 +apk_path=assets/locales/vi.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/locales/zu.pak, compress=False, alignment=4 +apk_path=assets/resources.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/af.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/am.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/as.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/az.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/be.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bg.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ca.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/cs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/da.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/de.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/el.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/et.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/eu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fil.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/he.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hy.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/id.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/is.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/it.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ja.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ka.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/km.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ko.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ky.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lo.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lt.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ml.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ms.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/my.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nb.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ne.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/or.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ro.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ru.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/si.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sq.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sw.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ta.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/te.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/th.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/tr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ur.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uz.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/vi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zu.pak, compress=False, alignment=4
diff --git a/android_webview/expectations/trichrome_webview_64_32_bundle.arm64.libs_and_assets.expected b/android_webview/expectations/trichrome_webview_64_32_bundle.arm64.libs_and_assets.expected new file mode 100644 index 0000000..877ba5a --- /dev/null +++ b/android_webview/expectations/trichrome_webview_64_32_bundle.arm64.libs_and_assets.expected
@@ -0,0 +1,173 @@ +apk_path=lib/armeabi-v7a/libarcore_sdk_c.so, compress=False, alignment=4096 +apk_path=lib/armeabi-v7a/libchromium_android_linker.so, compress=False, alignment=4096 +apk_path=lib/armeabi-v7a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096 +apk_path=lib/armeabi-v7a/libmonochrome_64.so, compress=False, alignment=4096 +apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 +apk_path=assets/locales/af.pak, compress=False, alignment=4 +apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/locales/ar.pak, compress=False, alignment=4 +apk_path=assets/locales/as.pak, compress=False, alignment=4 +apk_path=assets/locales/az.pak, compress=False, alignment=4 +apk_path=assets/locales/be.pak, compress=False, alignment=4 +apk_path=assets/locales/bg.pak, compress=False, alignment=4 +apk_path=assets/locales/bn.pak, compress=False, alignment=4 +apk_path=assets/locales/bs.pak, compress=False, alignment=4 +apk_path=assets/locales/ca.pak, compress=False, alignment=4 +apk_path=assets/locales/cs.pak, compress=False, alignment=4 +apk_path=assets/locales/da.pak, compress=False, alignment=4 +apk_path=assets/locales/de.pak, compress=False, alignment=4 +apk_path=assets/locales/el.pak, compress=False, alignment=4 +apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/locales/es.pak, compress=False, alignment=4 +apk_path=assets/locales/et.pak, compress=False, alignment=4 +apk_path=assets/locales/eu.pak, compress=False, alignment=4 +apk_path=assets/locales/fa.pak, compress=False, alignment=4 +apk_path=assets/locales/fi.pak, compress=False, alignment=4 +apk_path=assets/locales/fil.pak, compress=False, alignment=4 +apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/locales/fr.pak, compress=False, alignment=4 +apk_path=assets/locales/gl.pak, compress=False, alignment=4 +apk_path=assets/locales/gu.pak, compress=False, alignment=4 +apk_path=assets/locales/he.pak, compress=False, alignment=4 +apk_path=assets/locales/hi.pak, compress=False, alignment=4 +apk_path=assets/locales/hr.pak, compress=False, alignment=4 +apk_path=assets/locales/hu.pak, compress=False, alignment=4 +apk_path=assets/locales/hy.pak, compress=False, alignment=4 +apk_path=assets/locales/id.pak, compress=False, alignment=4 +apk_path=assets/locales/is.pak, compress=False, alignment=4 +apk_path=assets/locales/it.pak, compress=False, alignment=4 +apk_path=assets/locales/ja.pak, compress=False, alignment=4 +apk_path=assets/locales/ka.pak, compress=False, alignment=4 +apk_path=assets/locales/kk.pak, compress=False, alignment=4 +apk_path=assets/locales/km.pak, compress=False, alignment=4 +apk_path=assets/locales/kn.pak, compress=False, alignment=4 +apk_path=assets/locales/ko.pak, compress=False, alignment=4 +apk_path=assets/locales/ky.pak, compress=False, alignment=4 +apk_path=assets/locales/lo.pak, compress=False, alignment=4 +apk_path=assets/locales/lt.pak, compress=False, alignment=4 +apk_path=assets/locales/lv.pak, compress=False, alignment=4 +apk_path=assets/locales/mk.pak, compress=False, alignment=4 +apk_path=assets/locales/ml.pak, compress=False, alignment=4 +apk_path=assets/locales/mn.pak, compress=False, alignment=4 +apk_path=assets/locales/mr.pak, compress=False, alignment=4 +apk_path=assets/locales/ms.pak, compress=False, alignment=4 +apk_path=assets/locales/my.pak, compress=False, alignment=4 +apk_path=assets/locales/nb.pak, compress=False, alignment=4 +apk_path=assets/locales/ne.pak, compress=False, alignment=4 +apk_path=assets/locales/nl.pak, compress=False, alignment=4 +apk_path=assets/locales/or.pak, compress=False, alignment=4 +apk_path=assets/locales/pa.pak, compress=False, alignment=4 +apk_path=assets/locales/pl.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/locales/ro.pak, compress=False, alignment=4 +apk_path=assets/locales/ru.pak, compress=False, alignment=4 +apk_path=assets/locales/si.pak, compress=False, alignment=4 +apk_path=assets/locales/sk.pak, compress=False, alignment=4 +apk_path=assets/locales/sl.pak, compress=False, alignment=4 +apk_path=assets/locales/sq.pak, compress=False, alignment=4 +apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/locales/sr.pak, compress=False, alignment=4 +apk_path=assets/locales/sv.pak, compress=False, alignment=4 +apk_path=assets/locales/sw.pak, compress=False, alignment=4 +apk_path=assets/locales/ta.pak, compress=False, alignment=4 +apk_path=assets/locales/te.pak, compress=False, alignment=4 +apk_path=assets/locales/th.pak, compress=False, alignment=4 +apk_path=assets/locales/tr.pak, compress=False, alignment=4 +apk_path=assets/locales/uk.pak, compress=False, alignment=4 +apk_path=assets/locales/ur.pak, compress=False, alignment=4 +apk_path=assets/locales/uz.pak, compress=False, alignment=4 +apk_path=assets/locales/vi.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/locales/zu.pak, compress=False, alignment=4 +apk_path=assets/resources.pak, compress=False, alignment=4 +apk_path=assets/snapshot_blob_32.bin, compress=False, alignment=4 +apk_path=assets/stored-locales/af.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/am.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/as.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/az.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/be.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bg.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ca.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/cs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/da.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/de.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/el.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/et.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/eu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fil.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/he.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hy.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/id.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/is.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/it.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ja.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ka.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/km.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ko.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ky.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lo.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lt.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ml.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ms.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/my.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nb.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ne.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/or.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ro.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ru.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/si.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sq.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sw.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ta.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/te.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/th.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/tr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ur.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uz.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/vi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zu.pak, compress=False, alignment=4
diff --git a/android_webview/expectations/trichrome_webview_64_bundle.arm64.libs_and_assets.expected b/android_webview/expectations/trichrome_webview_64_bundle.arm64.libs_and_assets.expected new file mode 100644 index 0000000..508a001d --- /dev/null +++ b/android_webview/expectations/trichrome_webview_64_bundle.arm64.libs_and_assets.expected
@@ -0,0 +1,168 @@ +apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 +apk_path=assets/locales/af.pak, compress=False, alignment=4 +apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/locales/ar.pak, compress=False, alignment=4 +apk_path=assets/locales/as.pak, compress=False, alignment=4 +apk_path=assets/locales/az.pak, compress=False, alignment=4 +apk_path=assets/locales/be.pak, compress=False, alignment=4 +apk_path=assets/locales/bg.pak, compress=False, alignment=4 +apk_path=assets/locales/bn.pak, compress=False, alignment=4 +apk_path=assets/locales/bs.pak, compress=False, alignment=4 +apk_path=assets/locales/ca.pak, compress=False, alignment=4 +apk_path=assets/locales/cs.pak, compress=False, alignment=4 +apk_path=assets/locales/da.pak, compress=False, alignment=4 +apk_path=assets/locales/de.pak, compress=False, alignment=4 +apk_path=assets/locales/el.pak, compress=False, alignment=4 +apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/locales/es.pak, compress=False, alignment=4 +apk_path=assets/locales/et.pak, compress=False, alignment=4 +apk_path=assets/locales/eu.pak, compress=False, alignment=4 +apk_path=assets/locales/fa.pak, compress=False, alignment=4 +apk_path=assets/locales/fi.pak, compress=False, alignment=4 +apk_path=assets/locales/fil.pak, compress=False, alignment=4 +apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/locales/fr.pak, compress=False, alignment=4 +apk_path=assets/locales/gl.pak, compress=False, alignment=4 +apk_path=assets/locales/gu.pak, compress=False, alignment=4 +apk_path=assets/locales/he.pak, compress=False, alignment=4 +apk_path=assets/locales/hi.pak, compress=False, alignment=4 +apk_path=assets/locales/hr.pak, compress=False, alignment=4 +apk_path=assets/locales/hu.pak, compress=False, alignment=4 +apk_path=assets/locales/hy.pak, compress=False, alignment=4 +apk_path=assets/locales/id.pak, compress=False, alignment=4 +apk_path=assets/locales/is.pak, compress=False, alignment=4 +apk_path=assets/locales/it.pak, compress=False, alignment=4 +apk_path=assets/locales/ja.pak, compress=False, alignment=4 +apk_path=assets/locales/ka.pak, compress=False, alignment=4 +apk_path=assets/locales/kk.pak, compress=False, alignment=4 +apk_path=assets/locales/km.pak, compress=False, alignment=4 +apk_path=assets/locales/kn.pak, compress=False, alignment=4 +apk_path=assets/locales/ko.pak, compress=False, alignment=4 +apk_path=assets/locales/ky.pak, compress=False, alignment=4 +apk_path=assets/locales/lo.pak, compress=False, alignment=4 +apk_path=assets/locales/lt.pak, compress=False, alignment=4 +apk_path=assets/locales/lv.pak, compress=False, alignment=4 +apk_path=assets/locales/mk.pak, compress=False, alignment=4 +apk_path=assets/locales/ml.pak, compress=False, alignment=4 +apk_path=assets/locales/mn.pak, compress=False, alignment=4 +apk_path=assets/locales/mr.pak, compress=False, alignment=4 +apk_path=assets/locales/ms.pak, compress=False, alignment=4 +apk_path=assets/locales/my.pak, compress=False, alignment=4 +apk_path=assets/locales/nb.pak, compress=False, alignment=4 +apk_path=assets/locales/ne.pak, compress=False, alignment=4 +apk_path=assets/locales/nl.pak, compress=False, alignment=4 +apk_path=assets/locales/or.pak, compress=False, alignment=4 +apk_path=assets/locales/pa.pak, compress=False, alignment=4 +apk_path=assets/locales/pl.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/locales/ro.pak, compress=False, alignment=4 +apk_path=assets/locales/ru.pak, compress=False, alignment=4 +apk_path=assets/locales/si.pak, compress=False, alignment=4 +apk_path=assets/locales/sk.pak, compress=False, alignment=4 +apk_path=assets/locales/sl.pak, compress=False, alignment=4 +apk_path=assets/locales/sq.pak, compress=False, alignment=4 +apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/locales/sr.pak, compress=False, alignment=4 +apk_path=assets/locales/sv.pak, compress=False, alignment=4 +apk_path=assets/locales/sw.pak, compress=False, alignment=4 +apk_path=assets/locales/ta.pak, compress=False, alignment=4 +apk_path=assets/locales/te.pak, compress=False, alignment=4 +apk_path=assets/locales/th.pak, compress=False, alignment=4 +apk_path=assets/locales/tr.pak, compress=False, alignment=4 +apk_path=assets/locales/uk.pak, compress=False, alignment=4 +apk_path=assets/locales/ur.pak, compress=False, alignment=4 +apk_path=assets/locales/uz.pak, compress=False, alignment=4 +apk_path=assets/locales/vi.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/locales/zu.pak, compress=False, alignment=4 +apk_path=assets/resources.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/af.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/am.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/as.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/az.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/be.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bg.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ca.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/cs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/da.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/de.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/el.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/et.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/eu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fil.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/he.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hy.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/id.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/is.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/it.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ja.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ka.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/km.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ko.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ky.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lo.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lt.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ml.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ms.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/my.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nb.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ne.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/or.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ro.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ru.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/si.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sq.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sw.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ta.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/te.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/th.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/tr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ur.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uz.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/vi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zu.pak, compress=False, alignment=4
diff --git a/android_webview/expectations/trichrome_webview_bundle.arm.libs_and_assets.expected b/android_webview/expectations/trichrome_webview_bundle.arm.libs_and_assets.expected new file mode 100644 index 0000000..0b72da8c --- /dev/null +++ b/android_webview/expectations/trichrome_webview_bundle.arm.libs_and_assets.expected
@@ -0,0 +1,164 @@ +apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 +apk_path=assets/locales/af.pak, compress=False, alignment=4 +apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar.pak, compress=False, alignment=4 +apk_path=assets/locales/as.pak, compress=False, alignment=4 +apk_path=assets/locales/az.pak, compress=False, alignment=4 +apk_path=assets/locales/be.pak, compress=False, alignment=4 +apk_path=assets/locales/bg.pak, compress=False, alignment=4 +apk_path=assets/locales/bn.pak, compress=False, alignment=4 +apk_path=assets/locales/bs.pak, compress=False, alignment=4 +apk_path=assets/locales/ca.pak, compress=False, alignment=4 +apk_path=assets/locales/cs.pak, compress=False, alignment=4 +apk_path=assets/locales/da.pak, compress=False, alignment=4 +apk_path=assets/locales/de.pak, compress=False, alignment=4 +apk_path=assets/locales/el.pak, compress=False, alignment=4 +apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/locales/es.pak, compress=False, alignment=4 +apk_path=assets/locales/et.pak, compress=False, alignment=4 +apk_path=assets/locales/eu.pak, compress=False, alignment=4 +apk_path=assets/locales/fa.pak, compress=False, alignment=4 +apk_path=assets/locales/fi.pak, compress=False, alignment=4 +apk_path=assets/locales/fil.pak, compress=False, alignment=4 +apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/locales/fr.pak, compress=False, alignment=4 +apk_path=assets/locales/gl.pak, compress=False, alignment=4 +apk_path=assets/locales/gu.pak, compress=False, alignment=4 +apk_path=assets/locales/he.pak, compress=False, alignment=4 +apk_path=assets/locales/hi.pak, compress=False, alignment=4 +apk_path=assets/locales/hr.pak, compress=False, alignment=4 +apk_path=assets/locales/hu.pak, compress=False, alignment=4 +apk_path=assets/locales/hy.pak, compress=False, alignment=4 +apk_path=assets/locales/id.pak, compress=False, alignment=4 +apk_path=assets/locales/is.pak, compress=False, alignment=4 +apk_path=assets/locales/it.pak, compress=False, alignment=4 +apk_path=assets/locales/ja.pak, compress=False, alignment=4 +apk_path=assets/locales/ka.pak, compress=False, alignment=4 +apk_path=assets/locales/kk.pak, compress=False, alignment=4 +apk_path=assets/locales/km.pak, compress=False, alignment=4 +apk_path=assets/locales/kn.pak, compress=False, alignment=4 +apk_path=assets/locales/ko.pak, compress=False, alignment=4 +apk_path=assets/locales/ky.pak, compress=False, alignment=4 +apk_path=assets/locales/lo.pak, compress=False, alignment=4 +apk_path=assets/locales/lt.pak, compress=False, alignment=4 +apk_path=assets/locales/lv.pak, compress=False, alignment=4 +apk_path=assets/locales/mk.pak, compress=False, alignment=4 +apk_path=assets/locales/ml.pak, compress=False, alignment=4 +apk_path=assets/locales/mn.pak, compress=False, alignment=4 +apk_path=assets/locales/mr.pak, compress=False, alignment=4 +apk_path=assets/locales/ms.pak, compress=False, alignment=4 +apk_path=assets/locales/my.pak, compress=False, alignment=4 +apk_path=assets/locales/nb.pak, compress=False, alignment=4 +apk_path=assets/locales/ne.pak, compress=False, alignment=4 +apk_path=assets/locales/nl.pak, compress=False, alignment=4 +apk_path=assets/locales/or.pak, compress=False, alignment=4 +apk_path=assets/locales/pa.pak, compress=False, alignment=4 +apk_path=assets/locales/pl.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/locales/ro.pak, compress=False, alignment=4 +apk_path=assets/locales/ru.pak, compress=False, alignment=4 +apk_path=assets/locales/si.pak, compress=False, alignment=4 +apk_path=assets/locales/sk.pak, compress=False, alignment=4 +apk_path=assets/locales/sl.pak, compress=False, alignment=4 +apk_path=assets/locales/sq.pak, compress=False, alignment=4 +apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/locales/sr.pak, compress=False, alignment=4 +apk_path=assets/locales/sv.pak, compress=False, alignment=4 +apk_path=assets/locales/sw.pak, compress=False, alignment=4 +apk_path=assets/locales/ta.pak, compress=False, alignment=4 +apk_path=assets/locales/te.pak, compress=False, alignment=4 +apk_path=assets/locales/th.pak, compress=False, alignment=4 +apk_path=assets/locales/tr.pak, compress=False, alignment=4 +apk_path=assets/locales/uk.pak, compress=False, alignment=4 +apk_path=assets/locales/ur.pak, compress=False, alignment=4 +apk_path=assets/locales/uz.pak, compress=False, alignment=4 +apk_path=assets/locales/vi.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/locales/zu.pak, compress=False, alignment=4 +apk_path=assets/resources.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/af.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/am.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/as.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/az.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/be.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bg.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ca.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/cs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/da.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/de.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/el.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/et.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/eu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fil.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/he.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hy.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/id.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/is.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/it.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ja.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ka.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/km.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ko.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ky.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lo.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lt.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ml.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ms.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/my.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nb.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ne.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/or.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ro.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ru.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/si.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sq.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sw.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ta.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/te.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/th.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/tr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ur.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uz.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/vi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zu.pak, compress=False, alignment=4
diff --git a/android_webview/expectations/trichrome_webview_bundle.arm64.libs_and_assets.expected b/android_webview/expectations/trichrome_webview_bundle.arm64.libs_and_assets.expected new file mode 100644 index 0000000..53efb3e --- /dev/null +++ b/android_webview/expectations/trichrome_webview_bundle.arm64.libs_and_assets.expected
@@ -0,0 +1,173 @@ +apk_path=lib/arm64-v8a/libarcore_sdk_c.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libchromium_android_linker.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libmonochrome.so, compress=False, alignment=4096 +apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 +apk_path=assets/locales/af.pak, compress=False, alignment=4 +apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/locales/ar.pak, compress=False, alignment=4 +apk_path=assets/locales/as.pak, compress=False, alignment=4 +apk_path=assets/locales/az.pak, compress=False, alignment=4 +apk_path=assets/locales/be.pak, compress=False, alignment=4 +apk_path=assets/locales/bg.pak, compress=False, alignment=4 +apk_path=assets/locales/bn.pak, compress=False, alignment=4 +apk_path=assets/locales/bs.pak, compress=False, alignment=4 +apk_path=assets/locales/ca.pak, compress=False, alignment=4 +apk_path=assets/locales/cs.pak, compress=False, alignment=4 +apk_path=assets/locales/da.pak, compress=False, alignment=4 +apk_path=assets/locales/de.pak, compress=False, alignment=4 +apk_path=assets/locales/el.pak, compress=False, alignment=4 +apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/locales/es.pak, compress=False, alignment=4 +apk_path=assets/locales/et.pak, compress=False, alignment=4 +apk_path=assets/locales/eu.pak, compress=False, alignment=4 +apk_path=assets/locales/fa.pak, compress=False, alignment=4 +apk_path=assets/locales/fi.pak, compress=False, alignment=4 +apk_path=assets/locales/fil.pak, compress=False, alignment=4 +apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/locales/fr.pak, compress=False, alignment=4 +apk_path=assets/locales/gl.pak, compress=False, alignment=4 +apk_path=assets/locales/gu.pak, compress=False, alignment=4 +apk_path=assets/locales/he.pak, compress=False, alignment=4 +apk_path=assets/locales/hi.pak, compress=False, alignment=4 +apk_path=assets/locales/hr.pak, compress=False, alignment=4 +apk_path=assets/locales/hu.pak, compress=False, alignment=4 +apk_path=assets/locales/hy.pak, compress=False, alignment=4 +apk_path=assets/locales/id.pak, compress=False, alignment=4 +apk_path=assets/locales/is.pak, compress=False, alignment=4 +apk_path=assets/locales/it.pak, compress=False, alignment=4 +apk_path=assets/locales/ja.pak, compress=False, alignment=4 +apk_path=assets/locales/ka.pak, compress=False, alignment=4 +apk_path=assets/locales/kk.pak, compress=False, alignment=4 +apk_path=assets/locales/km.pak, compress=False, alignment=4 +apk_path=assets/locales/kn.pak, compress=False, alignment=4 +apk_path=assets/locales/ko.pak, compress=False, alignment=4 +apk_path=assets/locales/ky.pak, compress=False, alignment=4 +apk_path=assets/locales/lo.pak, compress=False, alignment=4 +apk_path=assets/locales/lt.pak, compress=False, alignment=4 +apk_path=assets/locales/lv.pak, compress=False, alignment=4 +apk_path=assets/locales/mk.pak, compress=False, alignment=4 +apk_path=assets/locales/ml.pak, compress=False, alignment=4 +apk_path=assets/locales/mn.pak, compress=False, alignment=4 +apk_path=assets/locales/mr.pak, compress=False, alignment=4 +apk_path=assets/locales/ms.pak, compress=False, alignment=4 +apk_path=assets/locales/my.pak, compress=False, alignment=4 +apk_path=assets/locales/nb.pak, compress=False, alignment=4 +apk_path=assets/locales/ne.pak, compress=False, alignment=4 +apk_path=assets/locales/nl.pak, compress=False, alignment=4 +apk_path=assets/locales/or.pak, compress=False, alignment=4 +apk_path=assets/locales/pa.pak, compress=False, alignment=4 +apk_path=assets/locales/pl.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/locales/ro.pak, compress=False, alignment=4 +apk_path=assets/locales/ru.pak, compress=False, alignment=4 +apk_path=assets/locales/si.pak, compress=False, alignment=4 +apk_path=assets/locales/sk.pak, compress=False, alignment=4 +apk_path=assets/locales/sl.pak, compress=False, alignment=4 +apk_path=assets/locales/sq.pak, compress=False, alignment=4 +apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/locales/sr.pak, compress=False, alignment=4 +apk_path=assets/locales/sv.pak, compress=False, alignment=4 +apk_path=assets/locales/sw.pak, compress=False, alignment=4 +apk_path=assets/locales/ta.pak, compress=False, alignment=4 +apk_path=assets/locales/te.pak, compress=False, alignment=4 +apk_path=assets/locales/th.pak, compress=False, alignment=4 +apk_path=assets/locales/tr.pak, compress=False, alignment=4 +apk_path=assets/locales/uk.pak, compress=False, alignment=4 +apk_path=assets/locales/ur.pak, compress=False, alignment=4 +apk_path=assets/locales/uz.pak, compress=False, alignment=4 +apk_path=assets/locales/vi.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/locales/zu.pak, compress=False, alignment=4 +apk_path=assets/resources.pak, compress=False, alignment=4 +apk_path=assets/snapshot_blob_64.bin, compress=False, alignment=4 +apk_path=assets/stored-locales/af.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/am.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar-XB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ar.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/as.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/az.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/be.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bg.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/bs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ca.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/cs.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/da.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/de.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/el.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-GB.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/en-XA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es-419.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/es.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/et.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/eu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fil.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr-CA.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/fr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/gu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/he.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hu.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/hy.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/id.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/is.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/it.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ja.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ka.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/km.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/kn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ko.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ky.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lo.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lt.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/lv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ml.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/mr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ms.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/my.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nb.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ne.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/nl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/or.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pa.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-BR.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/pt-PT.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ro.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ru.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/si.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sl.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sq.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr-Latn.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sv.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/sw.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ta.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/te.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/th.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/tr.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uk.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/ur.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/uz.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/vi.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-CN.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-HK.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zh-TW.pak, compress=False, alignment=4 +apk_path=assets/stored-locales/zu.pak, compress=False, alignment=4
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java index 6487c9a3..b842bcc 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -301,97 +301,183 @@ private String mTitle; private String mDefaultFilename; private boolean mCapture; - private static final Map<String, String> sAcceptTypesMapping = new HashMap<String, - String>() { - { - put("application/*", "application/*"); - put("audio/*", "audio/*"); - put("font/*", "font/*"); - put("image/*", "image/*"); - put("text/*", "text/*"); - put("video/*", "video/*"); - put(".aac", "audio/aac"); - put(".abw", "application/x-abiword"); - put(".arc", "application/x-freearc"); - put(".avif", "image/avif"); - put(".avi", "video/x-msvideo"); - put(".azw", "application/vnd.amazon.ebook"); - put(".bin", "application/octet-stream"); - put(".bmp", "image/bmp"); - put(".bz", "application/x-bzip"); - put(".bz2", "application/x-bzip2"); - put(".cda", "application/x-cdf"); - put(".csh", "application/x-csh"); - put(".css", "text/css"); - put(".csv", "text/csv"); - put(".doc", "application/msword"); - put(".docx", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); - put(".eot", "application/vnd.ms-fontobject"); - put(".epub", "application/epub+zip"); - put(".gz", "application/gzip"); - put(".gif", "image/gif"); - put(".htm", "text/html"); - put(".html", "text/html"); - put(".ico", "image/vnd.microsoft.icon"); - put(".ics", "text/calendar"); - put(".jar", "application/java-archive"); - put(".jpeg", "image/jpeg"); - put(".jpg", "image/jpeg"); - put(".js", "text/javascript"); - put(".json", "application/json"); - put(".jsonld", "application/ld+json"); - put(".mid", "audio/midi"); - put(".midi", "audio/midi"); - put(".mjs", "text/javascript"); - put(".mp3", "audio/mpeg"); - put(".mp4", "video/mp4"); - put(".mpeg", "video/mpeg"); - put(".mpkg", "application/vnd.apple.installer+xml"); - put(".odp", "application/vnd.oasis.opendocument.presentation"); - put(".ods", "application/vnd.oasis.opendocument.spreadsheet"); - put(".odt", "application/vnd.oasis.opendocument.text"); - put(".oga", "audio/ogg"); - put(".ogv", "video/ogg"); - put(".ogx", "application/ogg"); - put(".opus", "audio/opus"); - put(".otf", "font/otf"); - put(".png", "image/png"); - put(".pdf", "application/pdf"); - put(".php", "application/x-httpd-php"); - put(".ppt", "application/vnd.ms-powerpoint"); - put(".pptx", - "application/vnd.openxmlformats-officedocument" - + ".presentationml.presentation"); - put(".rar", "application/vnd.rar"); - put(".rtf", "application/rtf"); - put(".sh", "application/x-sh"); - put(".svg", "image/svg+xml"); - put(".swf", "application/x-shockwave-flash"); - put(".tar", "application/x-tar"); - put(".tif", "image/tiff"); - put(".tiff", "image/tiff"); - put(".ts", "video/mp2t"); - put(".ttf", "font/ttf"); - put(".txt", "text/plain"); - put(".vsd", "application/vnd.visio"); - put(".wav", "audio/wav"); - put(".weba", "audio/webm"); - put(".webm", "video/webm"); - put(".webp", "image/webp"); - put(".woff", "font/woff"); - put(".woff2", "font/woff2"); - put(".xhtml", "application/xhtml+xml"); - put(".xls", "application/vnd.ms-excel"); - put(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - put(".xml", "application/xml"); - put(".xul", "application/vnd.mozilla.xul+xml"); - put(".zip", "application/zip"); - put(".3gp", "video/3gpp"); - put(".3g2", "video/3gpp2"); - put(".7z", "application/x-7z-compressed"); + private static final Map<String, String> sAcceptTypesMapping; + static { + // It takes less code to loop over an array than to call put() N times. + String[] tuples = new String[] { + "application/*", + "application/*", + "audio/*", + "audio/*", + "font/*", + "font/*", + "image/*", + "image/*", + "text/*", + "text/*", + "video/*", + "video/*", + ".aac", + "audio/aac", + ".abw", + "application/x-abiword", + ".arc", + "application/x-freearc", + ".avif", + "image/avif", + ".avi", + "video/x-msvideo", + ".azw", + "application/vnd.amazon.ebook", + ".bin", + "application/octet-stream", + ".bmp", + "image/bmp", + ".bz", + "application/x-bzip", + ".bz2", + "application/x-bzip2", + ".cda", + "application/x-cdf", + ".csh", + "application/x-csh", + ".css", + "text/css", + ".csv", + "text/csv", + ".doc", + "application/msword", + ".docx", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ".eot", + "application/vnd.ms-fontobject", + ".epub", + "application/epub+zip", + ".gz", + "application/gzip", + ".gif", + "image/gif", + ".htm", + "text/html", + ".html", + "text/html", + ".ico", + "image/vnd.microsoft.icon", + ".ics", + "text/calendar", + ".jar", + "application/java-archive", + ".jpeg", + "image/jpeg", + ".jpg", + "image/jpeg", + ".js", + "text/javascript", + ".json", + "application/json", + ".jsonld", + "application/ld+json", + ".mid", + "audio/midi", + ".midi", + "audio/midi", + ".mjs", + "text/javascript", + ".mp3", + "audio/mpeg", + ".mp4", + "video/mp4", + ".mpeg", + "video/mpeg", + ".mpkg", + "application/vnd.apple.installer+xml", + ".odp", + "application/vnd.oasis.opendocument.presentation", + ".ods", + "application/vnd.oasis.opendocument.spreadsheet", + ".odt", + "application/vnd.oasis.opendocument.text", + ".oga", + "audio/ogg", + ".ogv", + "video/ogg", + ".ogx", + "application/ogg", + ".opus", + "audio/opus", + ".otf", + "font/otf", + ".png", + "image/png", + ".pdf", + "application/pdf", + ".php", + "application/x-httpd-php", + ".ppt", + "application/vnd.ms-powerpoint", + ".pptx", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + ".rar", + "application/vnd.rar", + ".rtf", + "application/rtf", + ".sh", + "application/x-sh", + ".svg", + "image/svg+xml", + ".swf", + "application/x-shockwave-flash", + ".tar", + "application/x-tar", + ".tif", + "image/tiff", + ".tiff", + "image/tiff", + ".ts", + "video/mp2t", + ".ttf", + "font/ttf", + ".txt", + "text/plain", + ".vsd", + "application/vnd.visio", + ".wav", + "audio/wav", + ".weba", + "audio/webm", + ".webm", + "video/webm", + ".webp", + "image/webp", + ".woff", + "font/woff", + ".woff2", + "font/woff2", + ".xhtml", + "application/xhtml+xml", + ".xls", + "application/vnd.ms-excel", + ".xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ".xml", + "application/xml", + ".xul", + "application/vnd.mozilla.xul+xml", + ".zip", + "application/zip", + ".3gp", + "video/3gpp", + ".3g2", + "video/3gpp2", + ".7z", + "application/x-7z-compressed", + }; + Map<String, String> map = new HashMap<String, String>(tuples.length / 2); + for (int i = 0; i < tuples.length; i += 2) { + map.put(tuples[i], tuples[i + 1]); } - }; + sAcceptTypesMapping = map; + } public FileChooserParamsImpl(int mode, String acceptTypes, String title, String defaultFilename, boolean capture) {
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 d0a1213..2e49efc 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
@@ -315,8 +315,6 @@ "Switches skia to use DMSAA instead of MSAA for tile raster"), Flag.baseFeature( CcFeatures.AVOID_RASTER_DURING_ELASTIC_OVERSCROLL, "No effect on webview"), - Flag.baseFeature(BlinkFeatures.DOCUMENT_EVENT_NODE_PATH_CACHING, - "Enables a performance optimization that caches event paths."), Flag.baseFeature(BlinkFeatures.WEB_RTC_METRONOME, "Inject a metronome into webrtc to allow task coalescing, " + " including synchronized decoding."),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java index 821908d..d411bba 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java
@@ -46,6 +46,7 @@ import androidx.annotation.IntDef; import androidx.test.espresso.DataInteraction; import androidx.test.espresso.Espresso; +import androidx.test.espresso.NoMatchingRootException; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; @@ -73,6 +74,8 @@ import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.util.CriteriaNotSatisfiedException; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.ViewUtils; @@ -512,15 +515,25 @@ */ private DataInteraction toggleFlag(DataInteraction flagInteraction, Boolean state) { String stateText = state == null ? "Default" : state ? "Enabled" : "Disabled"; - // We first select the spinner on the list of flags. - // That will make a dialog appear witch the option we wish to select. - flagInteraction.onChildView(withId(R.id.flag_toggle)).perform(click()); - // We then select the state we want from the dialog. - // We cannot use onData because in rare conditions, - // the onData check can be performed before the dialog has been displayed. - // Adding the inRoot check below ensures that we don't match with the spinner that also - // have the state we are waiting for (see crbug.com/1400515 for more details). - onView(withText(stateText)).inRoot(isDialog()).perform(click()); + CriteriaHelper.pollInstrumentationThread(() -> { + try { + // We first select the spinner on the list of flags. + // That will make a dialog appear witch the option we wish to select. + flagInteraction.onChildView(withId(R.id.flag_toggle)).perform(click()); + // We then select the state we want from the dialog. + onView(withText(stateText)).inRoot(isDialog()).perform(click()); + } catch (NoMatchingRootException noMatchException) { + // Espresso is flaky with dialogs from Spinners. + // It seems to rarely not open the dialog. + // To avoid this happening, the tests will re-attempt + // to select a flag if the root (ie the dialog), was not + // found. + // This is safe to do because the first click is explicitly on + // a flag toggle, and the second click is explicitly in a dialog. + // See crbug.com/1400515 for more details. + throw new CriteriaNotSatisfiedException(noMatchException); + } + }); // Finally we confirm that the original spinner was updated after the dialog option has // been selected. flagInteraction.onChildView(withId(R.id.flag_toggle))
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index e20efe94..d79146c38 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -47,7 +47,6 @@ "is_trichrome", "include_32_bit_webview", "include_64_bit_webview", - "use_trichrome_library", "weblayer_product_config_java_package", "weblayer_in_split", "webview_framework_dep", @@ -131,10 +130,7 @@ deps += [ "//android_webview/nonembedded:devui_launcher_icon_resources" ] } - # TODO(crbug.com/1408322): Delete use_trichrome_library reference. - _is_trichrome = (defined(invoker.use_trichrome_library) && - invoker.use_trichrome_library) || - (defined(invoker.is_trichrome) && invoker.is_trichrome) + _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome assert( _is_trichrome == defined(static_library_provider), "If trichrome library is used, static_library_provider must be set " +
diff --git a/android_webview/tools/system_webview_shell/lint-baseline.xml b/android_webview/tools/system_webview_shell/lint-baseline.xml index f15318c..334eabc2 100644 --- a/android_webview/tools/system_webview_shell/lint-baseline.xml +++ b/android_webview/tools/system_webview_shell/lint-baseline.xml
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.0.0-alpha10" type="baseline" client="" dependencies="true" name="" variant="all" version="8.0.0-alpha10"> +<issues format="6" by="lint 8.1.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-alpha01"> <issue id="MissingClass" @@ -129,7 +129,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java" - line="221" + line="214" column="24"/> </issue> @@ -145,6 +145,17 @@ </issue> <issue + id="UnspecifiedRegisterReceiverFlag" + message="`receiver` \
is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected \
broadcasts registered for an IntentFilter that cannot be inspected by lint" + errorLine1=" return context.registerReceiver(receiver, filter, permission, scheduler);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="../../base/android/java/src/org/chromium/base/ContextUtils.java" + line="307" + column="20"/> + </issue> + + <issue id="AssertionSideEffect" message="Assertion condition has a side effect: f.setAccessible(true)" errorLine1=" assert reachesWindowCallback(activity.getWindow().getCallback());"
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 41161ff1..d00f03e 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1334,8 +1334,12 @@ "system/input_device_settings/input_device_settings_controller_impl.h", "system/input_device_settings/input_device_settings_defaults.h", "system/input_device_settings/input_device_settings_pref_names.h", + "system/input_device_settings/input_device_settings_utils.cc", + "system/input_device_settings/input_device_settings_utils.h", "system/input_device_settings/input_device_tracker.cc", "system/input_device_settings/input_device_tracker.h", + "system/input_device_settings/keyboard_modifier_metrics_recorder.cc", + "system/input_device_settings/keyboard_modifier_metrics_recorder.h", "system/input_device_settings/pref_handlers/keyboard_pref_handler.h", "system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.cc", "system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h", @@ -1383,6 +1387,8 @@ "system/message_center/ash_message_popup_collection.h", "system/message_center/ash_notification_control_button_factory.cc", "system/message_center/ash_notification_control_button_factory.h", + "system/message_center/ash_notification_drag_controller.cc", + "system/message_center/ash_notification_drag_controller.h", "system/message_center/ash_notification_expand_button.cc", "system/message_center/ash_notification_expand_button.h", "system/message_center/ash_notification_input_container.cc", @@ -1469,19 +1475,13 @@ "system/network/network_detailed_view_controller.h", "system/network/network_feature_pod_button.cc", "system/network/network_feature_pod_button.h", - "system/network/network_feature_pod_button_legacy.cc", - "system/network/network_feature_pod_button_legacy.h", "system/network/network_feature_pod_controller.cc", "system/network/network_feature_pod_controller.h", - "system/network/network_feature_pod_controller_legacy.cc", - "system/network/network_feature_pod_controller_legacy.h", "system/network/network_icon.cc", "system/network/network_icon.h", "system/network/network_icon_animation.cc", "system/network/network_icon_animation.h", "system/network/network_icon_animation_observer.h", - "system/network/network_info.cc", - "system/network/network_info.h", "system/network/network_info_bubble.cc", "system/network/network_info_bubble.h", "system/network/network_list_header_view.cc", @@ -1496,8 +1496,6 @@ "system/network/network_list_network_header_view.h", "system/network/network_list_network_item_view.cc", "system/network/network_list_network_item_view.h", - "system/network/network_list_view.cc", - "system/network/network_list_view.h", "system/network/network_list_view_controller.cc", "system/network/network_list_view_controller.h", "system/network/network_list_view_controller_impl.cc", @@ -1507,10 +1505,6 @@ "system/network/network_list_wifi_header_view_impl.cc", "system/network/network_list_wifi_header_view_impl.h", "system/network/network_observer.h", - "system/network/network_row_title_view.cc", - "system/network/network_row_title_view.h", - "system/network/network_section_header_view.cc", - "system/network/network_section_header_view.h", "system/network/network_state_list_detailed_view.cc", "system/network/network_state_list_detailed_view.h", "system/network/network_tray_view.cc", @@ -1522,8 +1516,6 @@ "system/network/tray_network_state_model.cc", "system/network/tray_network_state_model.h", "system/network/tray_network_state_observer.h", - "system/network/unified_network_detailed_view_controller.cc", - "system/network/unified_network_detailed_view_controller.h", "system/network/unified_vpn_detailed_view_controller.cc", "system/network/unified_vpn_detailed_view_controller.h", "system/network/vpn_feature_pod_controller.cc", @@ -3082,6 +3074,7 @@ "system/input_device_settings/input_device_pref_manager_unittest.cc", "system/input_device_settings/input_device_settings_controller_unittest.cc", "system/input_device_settings/input_device_tracker_unittest.cc", + "system/input_device_settings/keyboard_modifier_metrics_recorder_unittest.cc", "system/input_device_settings/pref_handlers/keyboard_pref_handler_unittest.cc", "system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc", "system/keyboard_brightness/keyboard_backlight_color_nudge_controller_unittest.cc", @@ -3693,6 +3686,8 @@ "display/screen_orientation_controller_test_api.cc", "display/screen_orientation_controller_test_api.h", "drag_drop/drag_drop_controller_test_api.h", + "drag_drop/mock_drag_drop_observer.cc", + "drag_drop/mock_drag_drop_observer.h", "events/keyboard_capability_delegate_impl.cc", "events/keyboard_capability_delegate_impl.h", "fast_ink/laser/laser_pointer_controller_test_api.cc",
diff --git a/ash/accelerators/accelerator_commands.cc b/ash/accelerators/accelerator_commands.cc index f5e8e2c..fd949a5 100644 --- a/ash/accelerators/accelerator_commands.cc +++ b/ash/accelerators/accelerator_commands.cc
@@ -1013,9 +1013,17 @@ } void ShowKeyboardShortcutViewer() { + if (features::ShouldOnlyShowNewShortcutApp()) { + ShowShortcutCustomizationApp(); + return; + } NewWindowDelegate::GetInstance()->ShowKeyboardShortcutViewer(); } +void ShowShortcutCustomizationApp() { + NewWindowDelegate::GetInstance()->ShowShortcutCustomizationApp(); +} + void ShowStylusTools() { GetPaletteTray()->ShowBubble(); }
diff --git a/ash/accelerators/accelerator_commands.h b/ash/accelerators/accelerator_commands.h index 44dea06..ab62b71 100644 --- a/ash/accelerators/accelerator_commands.h +++ b/ash/accelerators/accelerator_commands.h
@@ -262,6 +262,9 @@ // Sees keyboard shortcut helper. ASH_EXPORT void ShowKeyboardShortcutViewer(); +// Opens Shortcut Customization. +ASH_EXPORT void ShowShortcutCustomizationApp(); + // Shows stylus tools. ASH_EXPORT void ShowStylusTools();
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index 7dca039f..8ff8521 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -1115,7 +1115,11 @@ accelerators::ToggleProjectorMarker(); break; case SHOW_SHORTCUT_VIEWER: - accelerators::ShowKeyboardShortcutViewer(); + if (features::ShouldOnlyShowNewShortcutApp()) { + accelerators::ShowShortcutCustomizationApp(); + } else { + accelerators::ShowKeyboardShortcutViewer(); + } break; case SHOW_STYLUS_TOOLS: base::RecordAction(UserMetricsAction("Accel_Show_Stylus_Tools"));
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc index 9475c08..a78247d 100644 --- a/ash/accelerators/debug_commands.cc +++ b/ash/accelerators/debug_commands.cc
@@ -36,8 +36,6 @@ #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/utf_string_conversions.h" -#include "chromeos/ui/wm/features.h" -#include "chromeos/ui/wm/window_util.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/aura/client/aura_constants.h" #include "ui/display/manager/display_manager.h" @@ -226,17 +224,14 @@ } void HandleTuckFloatedWindow(AcceleratorAction action) { - // Find the active floated window. - auto* float_controller = Shell::Get()->float_controller(); - auto* floated_window = float_controller->FindFloatedWindowOfDesk( - DesksController::Get()->GetTargetActiveDesk()); - + auto* floated_window = window_util::GetFloatedWindowForActiveDesk(); DCHECK(floated_window); const float velocity_x = action == DEBUG_TUCK_FLOATED_WINDOW_LEFT ? -500.f : 500.f; - float_controller->OnFlingOrSwipeForTablet(floated_window, velocity_x, - /*velocity_y=*/0.f); + Shell::Get()->float_controller()->OnFlingOrSwipeForTablet(floated_window, + velocity_x, + /*velocity_y=*/0.f); } } // namespace @@ -251,11 +246,7 @@ } bool CanTuckFloatedWindow() { - if (!chromeos::wm::features::IsFloatWindowEnabled()) - return false; - - return Shell::Get()->float_controller()->FindFloatedWindowOfDesk( - DesksController::Get()->GetTargetActiveDesk()); + return !!window_util::GetFloatedWindowForActiveDesk(); } bool DebugAcceleratorsEnabled() {
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc index bcb69cd4..56716de 100644 --- a/ash/ash_prefs.cc +++ b/ash/ash_prefs.cc
@@ -34,10 +34,10 @@ #include "ash/system/camera/autozoom_controller_impl.h" #include "ash/system/camera/autozoom_nudge_controller.h" #include "ash/system/camera/camera_effects_controller.h" -#include "ash/system/caps_lock_notification_controller.h" #include "ash/system/gesture_education/gesture_education_notification_controller.h" #include "ash/system/human_presence/snooping_protection_controller.h" #include "ash/system/input_device_settings/input_device_tracker.h" +#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" #include "ash/system/keyboard_brightness/keyboard_backlight_color_controller.h" #include "ash/system/media/media_tray.h" #include "ash/system/message_center/message_center_controller.h" @@ -84,7 +84,6 @@ AmbientController::RegisterProfilePrefs(registry); CalendarController::RegisterProfilePrefs(registry); CameraEffectsController::RegisterProfilePrefs(registry); - CapsLockNotificationController::RegisterProfilePrefs(registry, for_test); CaptureModeController::RegisterProfilePrefs(registry); CellularSetupNotifier::RegisterProfilePrefs(registry); contextual_tooltip::RegisterProfilePrefs(registry); @@ -105,6 +104,7 @@ LogoutConfirmationController::RegisterProfilePrefs(registry); KeyboardBacklightColorController::RegisterPrefs(registry); KeyboardControllerImpl::RegisterProfilePrefs(registry); + KeyboardModifierMetricsRecorder::RegisterProfilePrefs(registry, for_test); MediaControllerImpl::RegisterProfilePrefs(registry); MessageCenterController::RegisterProfilePrefs(registry); NightLightControllerImpl::RegisterProfilePrefs(registry);
diff --git a/ash/assistant/assistant_controller_impl.cc b/ash/assistant/assistant_controller_impl.cc index 2552806..d503ae0 100644 --- a/ash/assistant/assistant_controller_impl.cc +++ b/ash/assistant/assistant_controller_impl.cc
@@ -20,6 +20,7 @@ #include "base/functional/bind.h" #include "base/memory/scoped_refptr.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/assistant_prefs.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" #include "chromeos/ash/services/assistant/public/cpp/features.h" @@ -78,9 +79,6 @@ assistant_notification_controller_.SetAssistant(assistant); assistant_ui_controller_.SetAssistant(assistant); - OnAccessibilityStatusChanged(); - OnColorModeChanged(DarkLightModeControllerImpl::Get()->IsDarkModeEnabled()); - if (assistant) { for (AssistantControllerObserver& observer : observers_) observer.OnAssistantReady(); @@ -342,10 +340,17 @@ void AssistantControllerImpl::OnAssistantStatusChanged( assistant::AssistantStatus status) { - if (status == assistant::AssistantStatus::NOT_READY) { - assistant_volume_control_receiver_.reset(); - assistant_ui_controller_.CloseUi( - assistant::AssistantExitPoint::kUnspecified); + switch (status) { + case assistant::AssistantStatus::NOT_READY: + assistant_volume_control_receiver_.reset(); + assistant_ui_controller_.CloseUi( + assistant::AssistantExitPoint::kUnspecified); + break; + case assistant::AssistantStatus::READY: + OnAccessibilityStatusChanged(); + OnColorModeChanged( + DarkLightModeControllerImpl::Get()->IsDarkModeEnabled()); + break; } }
diff --git a/ash/assistant/assistant_controller_impl_unittest.cc b/ash/assistant/assistant_controller_impl_unittest.cc index c4f1988..7cc9d81 100644 --- a/ash/assistant/assistant_controller_impl_unittest.cc +++ b/ash/assistant/assistant_controller_impl_unittest.cc
@@ -106,17 +106,20 @@ const AssistantUiModel* ui_model() { return AssistantUiController::Get()->GetModel(); } - TestAssistantService* test_assistant_service() { - return &test_assistant_service_; - } private: MockNewWindowDelegate* new_window_delegate_; std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_; +}; - // AssistantService must outlive AssistantController as destructor can - // reference AssistantService. - TestAssistantService test_assistant_service_; +// Same with `AssistantControllerImplTest` except that this class does not set +// up an active user in `SetUp`. +class AssistantControllerImplTestForStartUp + : public AssistantControllerImplTest { + public: + AssistantControllerImplTestForStartUp() { + set_up_active_user_in_test_set_up_ = false; + } }; } // namespace @@ -256,19 +259,19 @@ // Dark mode is set to true if the DarkLightMode flag is off. This is determined // in DarkLightModeControllerImpl::IsDarkModeEnabled(). -TEST_F(AssistantControllerImplTest, ColorModeIsSetWhenAssistantIsReadyFlagOff) { +TEST_F(AssistantControllerImplTestForStartUp, + ColorModeIsSetWhenAssistantIsReadyFlagOff) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures( /*enabled_features=*/{}, /*disabled_features=*/{ chromeos::features::kDarkLightMode, features::kNotificationsRefresh}); + SetUpActiveUser(); - controller()->SetAssistant(test_assistant_service()); - - ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value()); - EXPECT_TRUE(test_assistant_service()->dark_mode_enabled().value()); + ASSERT_TRUE(assistant_service()->dark_mode_enabled().has_value()); + EXPECT_TRUE(assistant_service()->dark_mode_enabled().value()); } -TEST_F(AssistantControllerImplTest, ColorModeIsUpdated) { +TEST_F(AssistantControllerImplTestForStartUp, ColorModeIsUpdated) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(chromeos::features::kDarkLightMode); @@ -281,18 +284,18 @@ auto* dark_light_mode_controller = DarkLightModeControllerImpl::Get(); dark_light_mode_controller->OnActiveUserPrefServiceChanged( active_user_pref_service); - controller()->SetAssistant(test_assistant_service()); + SetUpActiveUser(); const bool initial_dark_mode_status = dark_light_mode_controller->IsDarkModeEnabled(); - ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value()); + ASSERT_TRUE(assistant_service()->dark_mode_enabled().has_value()); EXPECT_EQ(initial_dark_mode_status, - test_assistant_service()->dark_mode_enabled().value()); + assistant_service()->dark_mode_enabled().value()); // Switch the color mode. dark_light_mode_controller->ToggleColorMode(); - ASSERT_TRUE(test_assistant_service()->dark_mode_enabled().has_value()); + ASSERT_TRUE(assistant_service()->dark_mode_enabled().has_value()); EXPECT_NE(initial_dark_mode_status, - test_assistant_service()->dark_mode_enabled().value()); + assistant_service()->dark_mode_enabled().value()); } } // namespace ash
diff --git a/ash/assistant/test/assistant_ash_test_base.cc b/ash/assistant/test/assistant_ash_test_base.cc index 919f168..e08cf79 100644 --- a/ash/assistant/test/assistant_ash_test_base.cc +++ b/ash/assistant/test/assistant_ash_test_base.cc
@@ -118,7 +118,9 @@ test_api_->DisableAnimations(); EnableKeyboard(); - SetUpActiveUser(); + if (set_up_active_user_in_test_set_up_) { + SetUpActiveUser(); + } } void AssistantAshTestBase::TearDown() {
diff --git a/ash/assistant/test/assistant_ash_test_base.h b/ash/assistant/test/assistant_ash_test_base.h index d29a3131..ccea974 100644 --- a/ash/assistant/test/assistant_ash_test_base.h +++ b/ash/assistant/test/assistant_ash_test_base.h
@@ -204,9 +204,16 @@ TestAssistantService* assistant_service(); - private: + protected: + // Sets up an active user for a test. Note that this function is called in + // `SetUp` by default. You can change this behavior by setting + // `set_up_active_user_in_test_set_up_`. void SetUpActiveUser(); + // This variable must be set before `SetUp` function call. + bool set_up_active_user_in_test_set_up_ = true; + + private: std::unique_ptr<AssistantTestApi> test_api_; std::unique_ptr<TestAssistantSetup> test_setup_; std::unique_ptr<TestAshWebViewFactory> test_web_view_factory_;
diff --git a/ash/clipboard/clipboard_history_controller_impl.cc b/ash/clipboard/clipboard_history_controller_impl.cc index 839d991..8809950 100644 --- a/ash/clipboard/clipboard_history_controller_impl.cc +++ b/ash/clipboard/clipboard_history_controller_impl.cc
@@ -371,8 +371,9 @@ }, weak_ptr_factory_.GetWeakPtr())); - for (auto& observer : observers_) - observer.OnClipboardHistoryMenuShown(); + for (auto& observer : observers_) { + observer.OnClipboardHistoryMenuShown(show_source); + } } gfx::Rect ClipboardHistoryControllerImpl::GetMenuBoundsInScreenForTest() const {
diff --git a/ash/clipboard/clipboard_nudge.cc b/ash/clipboard/clipboard_nudge.cc index 23c44bc..25b1240 100644 --- a/ash/clipboard/clipboard_nudge.cc +++ b/ash/clipboard/clipboard_nudge.cc
@@ -6,7 +6,6 @@ #include <memory> -#include "ash/constants/notifier_catalogs.h" #include "ash/public/cpp/assistant/assistant_state.h" #include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shell_window_ids.h" @@ -58,9 +57,10 @@ } // namespace -ClipboardNudge::ClipboardNudge(ClipboardNudgeType nudge_type) +ClipboardNudge::ClipboardNudge(ClipboardNudgeType nudge_type, + NudgeCatalogName catalog_name) : SystemNudge(kClipboardNudgeName, - NudgeCatalogName::kMultipaste, + catalog_name, kClipboardIconSize, kIconLabelSpacing, kNudgePadding),
diff --git a/ash/clipboard/clipboard_nudge.h b/ash/clipboard/clipboard_nudge.h index e53e35f4..2a8f11f 100644 --- a/ash/clipboard/clipboard_nudge.h +++ b/ash/clipboard/clipboard_nudge.h
@@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "ash/clipboard/clipboard_nudge_constants.h" +#include "ash/constants/notifier_catalogs.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_observer.h" #include "ash/system/tray/system_nudge.h" @@ -20,7 +21,7 @@ // Implements a contextual nudge for multipaste. class ASH_EXPORT ClipboardNudge : public SystemNudge { public: - explicit ClipboardNudge(ClipboardNudgeType nudge_type); + ClipboardNudge(ClipboardNudgeType nudge_type, NudgeCatalogName catalog_name); ClipboardNudge(const ClipboardNudge&) = delete; ClipboardNudge& operator=(const ClipboardNudge&) = delete; ~ClipboardNudge() override;
diff --git a/ash/clipboard/clipboard_nudge_controller.cc b/ash/clipboard/clipboard_nudge_controller.cc index 2476448..186951f 100644 --- a/ash/clipboard/clipboard_nudge_controller.cc +++ b/ash/clipboard/clipboard_nudge_controller.cc
@@ -9,6 +9,7 @@ #include "ash/clipboard/clipboard_nudge.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" +#include "ash/constants/notifier_catalogs.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "base/json/values_util.h" @@ -65,6 +66,19 @@ kMaxSeconds); return true; } + +NudgeCatalogName GetCatalogName(ClipboardNudgeType type) { + switch (type) { + case kOnboardingNudge: + return NudgeCatalogName::kClipboardHistoryOnboarding; + case kZeroStateNudge: + return NudgeCatalogName::kClipboardHistoryZeroState; + case kScreenshotNotificationNudge: + NOTREACHED(); + } + return NudgeCatalogName::kTestCatalogName; +} + } // namespace ClipboardNudgeController::ClipboardNudgeController( @@ -218,15 +232,34 @@ update->Set(kLastTimeShown, base::TimeToValue(GetTime())); } -void ClipboardNudgeController::OnClipboardHistoryMenuShown() { - if (LogFeatureOpenTime(last_shown_time_, kOnboardingNudge_OpenTime)) +void ClipboardNudgeController::OnClipboardHistoryMenuShown( + crosapi::mojom::ClipboardHistoryControllerShowSource show_source) { + // The clipboard history nudges specifically suggest trying the Search+V + // shortcut. Opening the menu any other way should not count as the user + // responding to the nudge. + if (show_source != + crosapi::mojom::ClipboardHistoryControllerShowSource::kAccelerator) { + return; + } + + if (LogFeatureOpenTime(last_shown_time_, kOnboardingNudge_OpenTime)) { last_shown_time_.set_was_logged_as_opened(); - if (LogFeatureOpenTime(zero_state_last_shown_time_, kZeroStateNudge_OpenTime)) + } + if (LogFeatureOpenTime(zero_state_last_shown_time_, + kZeroStateNudge_OpenTime)) { zero_state_last_shown_time_.set_was_logged_as_opened(); + } if (LogFeatureOpenTime(screenshot_notification_last_shown_time_, kScreenshotNotification_OpenTime)) { screenshot_notification_last_shown_time_.set_was_logged_as_opened(); } + + // These metrics will not be recorded if the respective nudges have not been + // shown before. + SystemNudgeController::RecordNudgeAction( + NudgeCatalogName::kClipboardHistoryOnboarding); + SystemNudgeController::RecordNudgeAction( + NudgeCatalogName::kClipboardHistoryZeroState); } void ClipboardNudgeController::OnClipboardHistoryPasted() { @@ -258,7 +291,8 @@ } std::unique_ptr<SystemNudge> ClipboardNudgeController::CreateSystemNudge() { - return std::make_unique<ClipboardNudge>(current_nudge_type_); + return std::make_unique<ClipboardNudge>(current_nudge_type_, + GetCatalogName(current_nudge_type_)); } int ClipboardNudgeController::GetShownCount(PrefService* prefs) {
diff --git a/ash/clipboard/clipboard_nudge_controller.h b/ash/clipboard/clipboard_nudge_controller.h index ddcef6e..cc98f57 100644 --- a/ash/clipboard/clipboard_nudge_controller.h +++ b/ash/clipboard/clipboard_nudge_controller.h
@@ -87,8 +87,10 @@ // Increment the screenshot notification shown count. void MarkScreenshotNotificationShown(); - // ClipboardHistoryControllerImpl: - void OnClipboardHistoryMenuShown() override; + // ClipboardHistoryController::Observer: + void OnClipboardHistoryMenuShown( + crosapi::mojom::ClipboardHistoryControllerShowSource show_source) + override; void OnClipboardHistoryPasted() override; // Shows the nudge widget.
diff --git a/ash/clipboard/clipboard_nudge_controller_unittest.cc b/ash/clipboard/clipboard_nudge_controller_unittest.cc index ba3e2427..876d0dd 100644 --- a/ash/clipboard/clipboard_nudge_controller_unittest.cc +++ b/ash/clipboard/clipboard_nudge_controller_unittest.cc
@@ -8,12 +8,14 @@ #include "ash/clipboard/clipboard_history_controller_impl.h" #include "ash/clipboard/clipboard_nudge.h" #include "ash/clipboard/clipboard_nudge_constants.h" +#include "ash/constants/notifier_catalogs.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "base/test/task_environment.h" #include "chromeos/crosapi/mojom/clipboard_history.mojom.h" #include "ui/base/clipboard/clipboard_data.h" #include "ui/base/clipboard/clipboard_non_backed.h" @@ -24,9 +26,16 @@ namespace ash { +namespace { + +using crosapi::mojom::ClipboardHistoryControllerShowSource::kAccelerator; + +} // namespace + class ClipboardNudgeControllerTest : public AshTestBase { public: - ClipboardNudgeControllerTest() = default; + ClipboardNudgeControllerTest() + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} ClipboardNudgeControllerTest(const ClipboardNudgeControllerTest&) = delete; ClipboardNudgeControllerTest& operator=(const ClipboardNudgeControllerTest&) = delete; @@ -93,7 +102,7 @@ EXPECT_EQ(ClipboardState::kSecondCopy, nudge_controller_->GetClipboardStateForTesting()); - // Check that clipbaord nudge has not yet been created. + // Check that clipboard nudge has not yet been created. EXPECT_FALSE(nudge_controller_->GetSystemNudgeForTesting()); // Checks that the second paste resets state as expected. @@ -101,7 +110,7 @@ EXPECT_EQ(ClipboardState::kInit, nudge_controller_->GetClipboardStateForTesting()); - // Check that clipbaord nudge has been created. + // Check that clipboard nudge has been created. EXPECT_TRUE(nudge_controller_->GetSystemNudgeForTesting()); } @@ -145,7 +154,7 @@ nudge_controller_->GetClipboardStateForTesting()); } - // Check that clipbaord nudge has not yet been created. + // Check that clipboard nudge has not yet been created. EXPECT_FALSE(nudge_controller_->GetSystemNudgeForTesting()); // Check that HandleClipboardChanged() will advance nudge_controller's @@ -158,7 +167,7 @@ EXPECT_EQ(ClipboardState::kInit, nudge_controller_->GetClipboardStateForTesting()); - // Check that clipbaord nudge has been created. + // Check that clipboard nudge has been created. EXPECT_TRUE(nudge_controller_->GetSystemNudgeForTesting()); } @@ -249,7 +258,7 @@ ASSERT_TRUE(nudge_widget->GetLayer()->GetAnimator()->is_animating()); } -// Assert that all nudge metric related histograms start at 0. +// Asserts that all nudge metric related histograms start at 0. TEST_F(ClipboardNudgeControllerTest, NudgeMetrics_StartAtZero) { histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 0); histograms().ExpectTotalCount(kOnboardingNudge_PasteTime, 0); @@ -259,14 +268,14 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 0); } -// Test that opening the clipboard history after showing the nudges logs only +// Tests that opening the clipboard history after showing the nudges logs only // the metrics for the open time histograms. For this test, we only verify the // number of emits, but not the timing mechanism. TEST_F(ClipboardNudgeControllerTest, ShowMenuAfterNudges_LogsOpenNudgeMetrics) { ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 1); histograms().ExpectTotalCount(kZeroStateNudge_OpenTime, 1); @@ -276,14 +285,14 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 0); } -// Test that pasting something from the clipboard history after showing the +// Tests that pasting something from the clipboard history after showing the // nudges only the metrics for the paste time histograms. For this test, we only // verify the number of emits, but not the timing mechanism. TEST_F(ClipboardNudgeControllerTest, PasteAfterNudges_LogsPasteNudgeMetrics) { ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 1); @@ -294,11 +303,11 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 1); } -// Test that the onboarding nudge being shown only logs the metrics for the -// onboarding nudge histograms, +// Tests that the onboarding nudge being shown only logs the metrics for the +// onboarding nudge histograms. TEST_F(ClipboardNudgeControllerTest, OnboardingNudge_DoesNotLogOtherMetrics) { ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 1); @@ -309,11 +318,11 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 0); } -// Test that the zero state nudge being shown only logs the metrics for the zero -// state nudge histograms, +// Tests that the zero state nudge being shown only logs the metrics for the +// zero state nudge histograms. TEST_F(ClipboardNudgeControllerTest, ZeroStateNudge_DoesNotLogOtherMetrics) { ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 0); @@ -324,12 +333,12 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 0); } -// Test that the screenshot notification nudge being shown only logs the metrics -// for the screenshot notification nudge histograms, +// Tests that the screenshot notification nudge being shown only logs the +// metrics for the screenshot notification nudge histograms. TEST_F(ClipboardNudgeControllerTest, ScreenshotNotification_DoesNotLogOtherMetrics) { ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 0); @@ -340,15 +349,15 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 1); } -// Test that nudge metrics will not log multiple times if the nudges are not +// Tests that nudge metrics will not log multiple times if the nudges are not // shown before. TEST_F(ClipboardNudgeControllerTest, SecondTimeAction_DoesNotLogNudgeMetrics) { ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 1); @@ -359,17 +368,17 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 1); } -// Test that nudge metrics can log more times as the nudges are shown before. +// Tests that nudge metrics can log more times as the nudges are shown before. TEST_F(ClipboardNudgeControllerTest, ShowNudgeTwice_LogsMetricsTwoTimes) { ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); nudge_controller_->OnClipboardHistoryPasted(); histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 2); @@ -380,4 +389,63 @@ histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 2); } +// Tests that showing clipboard history from a source other than the accelerator +// does not log any metrics, because the nudge only mentions the accelerator as +// an option for opening the menu. +TEST_F(ClipboardNudgeControllerTest, + NonAcceleratorShowMenuAfterNudges_DoesNotLogNudgeMetrics) { + using crosapi::mojom::ClipboardHistoryControllerShowSource; + + ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); + ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); + ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); + for (size_t i = + static_cast<size_t>(ClipboardHistoryControllerShowSource::kMinValue); + i < static_cast<size_t>(ClipboardHistoryControllerShowSource::kMaxValue); + ++i) { + auto show_source = static_cast<ClipboardHistoryControllerShowSource>(i); + if (show_source != kAccelerator) { + nudge_controller_->OnClipboardHistoryMenuShown(show_source); + } + } + + histograms().ExpectTotalCount(kOnboardingNudge_OpenTime, 0); + histograms().ExpectTotalCount(kZeroStateNudge_OpenTime, 0); + histograms().ExpectTotalCount(kScreenshotNotification_OpenTime, 0); + histograms().ExpectTotalCount(kOnboardingNudge_PasteTime, 0); + histograms().ExpectTotalCount(kZeroStateNudge_PasteTime, 0); + histograms().ExpectTotalCount(kScreenshotNotification_PasteTime, 0); +} + +// Tests that nudge `TimeToAction` metric is logged after the nudge has been +// shown and clipboard history is opened through the accelerator. +TEST_F(ClipboardNudgeControllerTest, TimeToActionMetric) { + constexpr char kNudgeShownCount[] = "Ash.NotifierFramework.Nudge.ShownCount"; + constexpr char kNudgeTimeToActionWithin1m[] = + "Ash.NotifierFramework.Nudge.TimeToAction.Within1m"; + constexpr char kNudgeTimeToActionWithin1h[] = + "Ash.NotifierFramework.Nudge.TimeToAction.Within1h"; + + constexpr NudgeCatalogName kOnboardingCatalogName = + NudgeCatalogName::kClipboardHistoryOnboarding; + constexpr NudgeCatalogName kZeroStateCatalogName = + NudgeCatalogName::kClipboardHistoryZeroState; + + ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); + task_environment()->FastForwardBy(base::Hours(1)); + ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); + + // Open clipboard history through the accelerator after one hour of having + // shown the onboarding nudge, and right after showing the zero state nudge. + nudge_controller_->OnClipboardHistoryMenuShown( + /*show_source=*/crosapi::mojom::ClipboardHistoryControllerShowSource:: + kAccelerator); + + histograms().ExpectTotalCount(kNudgeShownCount, 2); + histograms().ExpectBucketCount(kNudgeTimeToActionWithin1m, + kZeroStateCatalogName, 1); + histograms().ExpectBucketCount(kNudgeTimeToActionWithin1h, + kOnboardingCatalogName, 1); +} + } // namespace ash
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc index c464eb6..eca1dff50 100644 --- a/ash/components/arc/arc_features.cc +++ b/ash/components/arc/arc_features.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ash/components/arc/arc_features.h" +#include "base/feature_list.h" namespace arc { @@ -153,7 +154,7 @@ // for a currently-active ARCVM game. BASE_FEATURE(kGameModeFeature, "ArcGameModeFeature", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); // Controls whether the guest zram is enabled. This is only for ARCVM. BASE_FEATURE(kGuestZram, "ArcGuestZram", base::FEATURE_DISABLED_BY_DEFAULT); @@ -317,4 +318,8 @@ "ArcVmBroadcastPreAnrHandling", base::FEATURE_DISABLED_BY_DEFAULT); +// Controls experimental key to enable Vmm swap for ARCVM by keyboard shortcut. +BASE_FEATURE(kVmmSwapKeyboardShortcut, + "ArcvmSwapoutKeyboardShortcut", + base::FEATURE_DISABLED_BY_DEFAULT); } // namespace arc
diff --git a/ash/components/arc/arc_features.h b/ash/components/arc/arc_features.h index 715241b..f02095d 100644 --- a/ash/components/arc/arc_features.h +++ b/ash/components/arc/arc_features.h
@@ -67,6 +67,7 @@ extern const base::FeatureParam<int> kVmMemorySizeMaxMiB; BASE_DECLARE_FEATURE(kVmBroadcastPreNotifyANR); BASE_DECLARE_FEATURE(kVmGmsCoreLowMemoryKillerProtection); +BASE_DECLARE_FEATURE(kVmmSwapKeyboardShortcut); } // namespace arc
diff --git a/ash/components/arc/mojom/app.mojom b/ash/components/arc/mojom/app.mojom index 0b4fe71e..8eb7c5ad3 100644 --- a/ash/components/arc/mojom/app.mojom +++ b/ash/components/arc/mojom/app.mojom
@@ -386,7 +386,7 @@ // TODO(lhchavez): Migrate all request/response messages to Mojo. // Next method ID: 42 -// Deprecated method IDs: 0, 1, 2, 3, 4, 9, 12, 13, 15, 17, 18, 19, 22, 31 +// Deprecated method IDs: 0, 1, 2, 3, 4, 6, 9, 12, 13, 15, 17, 18, 19, 22, 31 interface AppInstance { // Establishes full-duplex communication with the host. [MinVersion=26] Init@21(pending_remote<AppHost> host_remote) => (); @@ -398,9 +398,11 @@ // Closes the the given task. [MinVersion=4] CloseTask@8(int32 task_id); - // Requests information about task. - [MinVersion=3] GetTaskInfo@6(int32 task_id) => (string package_name, - string activity); + // Requests information about task. Deprecated: b/265158447 + // Use the kArcPackageNameKey window property to get the package name, and + // OnTaskCreated to get the activity. + [MinVersion=3] GetTaskInfoDeprecated@6(int32 task_id) => + (string package_name, string activity); // Sends a request to ARC to install package. [MinVersion=8] InstallPackage@11(ArcPackageInfo arcPackageInfo);
diff --git a/ash/components/arc/test/fake_app_instance.cc b/ash/components/arc/test/fake_app_instance.cc index affd1ce..7bea7cb 100644 --- a/ash/components/arc/test/fake_app_instance.cc +++ b/ash/components/arc/test/fake_app_instance.cc
@@ -268,12 +268,6 @@ return icon; } -void FakeAppInstance::SetTaskInfo(int32_t task_id, - const std::string& package_name, - const std::string& activity) { - task_id_to_info_[task_id] = std::make_unique<Request>(package_name, activity); -} - void FakeAppInstance::SendRefreshPackageList( std::vector<mojom::ArcPackageInfoPtr> packages) { app_host_->OnPackageListRefreshed(std::move(packages)); @@ -316,14 +310,9 @@ app_host_->OnPackageRemoved(package_name); } -void FakeAppInstance::GetTaskInfo(int32_t task_id, - GetTaskInfoCallback callback) { - TaskIdToInfo::const_iterator it = task_id_to_info_.find(task_id); - if (it == task_id_to_info_.end()) { - std::move(callback).Run(std::string(), std::string()); - return; - } - std::move(callback).Run(it->second->package_name(), it->second->activity()); +void FakeAppInstance::GetTaskInfoDeprecated( + int32_t task_id, GetTaskInfoDeprecatedCallback callback) { + LOG(FATAL) << "GetTaskInfo is deprecated: b/265158447"; } void FakeAppInstance::SetTaskActive(int32_t task_id) {}
diff --git a/ash/components/arc/test/fake_app_instance.h b/ash/components/arc/test/fake_app_instance.h index 3afab8b..7f23d7f 100644 --- a/ash/components/arc/test/fake_app_instance.h +++ b/ash/components/arc/test/fake_app_instance.h
@@ -139,7 +139,8 @@ const gfx::Rect& dimension, CanHandleResolutionDeprecatedCallback callback) override; void UninstallPackage(const std::string& package_name) override; - void GetTaskInfo(int32_t task_id, GetTaskInfoCallback callback) override; + void GetTaskInfoDeprecated(int32_t task_id, + GetTaskInfoDeprecatedCallback callback) override; void SetTaskActive(int32_t task_id) override; void CloseTask(int32_t task_id) override; void ShowPackageInfoDeprecated(const std::string& package_name, @@ -192,9 +193,6 @@ void SendUninstallShortcut(const std::string& package_name, const std::string& intent_uri); void SendInstallShortcuts(const std::vector<mojom::ShortcutInfo>& shortcuts); - void SetTaskInfo(int32_t task_id, - const std::string& package_name, - const std::string& activity); void SendRefreshPackageList(std::vector<mojom::ArcPackageInfoPtr> packages); void SendPackageAdded(mojom::ArcPackageInfoPtr package); void SendPackageModified(mojom::ArcPackageInfoPtr package); @@ -287,8 +285,6 @@ std::vector<std::unique_ptr<IconRequest>> icon_requests_; // Keeps information about shortcut icon load requests. std::vector<std::unique_ptr<ShortcutIconRequest>> shortcut_icon_requests_; - // Keeps information for running tasks. - TaskIdToInfo task_id_to_info_; // Defines how to response to icon requests. IconResponseType icon_response_type_ = IconResponseType::ICON_RESPONSE_SEND_GOOD;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 2885e60..47b48085 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -686,7 +686,7 @@ // network information to provide more context on connection errors. BASE_FEATURE(kEcheSWACheckAndroidNetworkInfo, "EcheSWACheckAndroidNetworkInfo", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // If enabled, allows the creation of up to 16 desks (default is 8). BASE_FEATURE(kEnable16Desks, @@ -804,6 +804,11 @@ "EnforceAshExtensionKeeplist", base::FEATURE_ENABLED_BY_DEFAULT); +// Enables access to the chrome://enterprise-reporting WebUI. +BASE_FEATURE(kEnterpriseReportingUI, + "EnterpriseReportingUI", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enables Device End Of Lifetime warning notifications. BASE_FEATURE(kEolWarningNotifications, "EolWarningNotifications", @@ -864,7 +869,7 @@ // Enables using new Handshake retry logic for Fast Pair. BASE_FEATURE(kFastPairHandshakeRefactor, "FastPairHandshakeRefactor", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // The amount of minutes we should wait before allowing notifications for a // recently lost device. @@ -3087,10 +3092,6 @@ return base::FeatureList::IsEnabled(kQuickDim) && switches::HasHps(); } -bool IsQuickSettingsNetworkRevampEnabled() { - return true; -} - bool IsPerDeskZOrderEnabled() { return base::FeatureList::IsEnabled(kEnablePerDeskZOrder); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 2f2adf39..3e29b9f9 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -267,6 +267,7 @@ extern const base::FeatureParam<double> kFastPairDeviceLostNotificationTimeoutMinutes; COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kFastPairLowPower); +COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnterpriseReportingUI); COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::FeatureParam<double> kFastPairLowPowerActiveSeconds; COMPONENT_EXPORT(ASH_CONSTANTS) @@ -851,8 +852,6 @@ bool IsProjectorFoldShortGapIntoPreviousTranscriptEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsQsRevampEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsQuickDimEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) -bool IsQuickSettingsNetworkRevampEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPerDeskZOrderEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsReleaseTrackUiEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsReverseScrollGesturesEnabled();
diff --git a/ash/constants/notifier_catalogs.h b/ash/constants/notifier_catalogs.h index f409bf5..ef78835 100644 --- a/ash/constants/notifier_catalogs.h +++ b/ash/constants/notifier_catalogs.h
@@ -185,15 +185,19 @@ // Current values should not be renumbered or removed. Please keep in sync with // "NudgeCatalogName" in tools/metrics/histograms/enums.xml. // To deprecate comment out the entry. +// Please call `SystemNudgeController::RecordNudgeAction` when the nudge's +// suggested action is performed by the user, if applicable. enum class NudgeCatalogName { kTestCatalogName = 0, kDictation = 1, - kMultipaste = 2, + // [Deprecated] kMultipaste = 2, kDarkLightMode = 3, kAutozoom = 4, kAdaptiveCharging = 5, kPhoneHub = 6, - kMaxValue = kPhoneHub, + kClipboardHistoryZeroState = 7, + kClipboardHistoryOnboarding = 8, + kMaxValue = kClipboardHistoryOnboarding, }; // A living catalog that registers toasts.
diff --git a/ash/controls/scroll_view_gradient_helper.cc b/ash/controls/scroll_view_gradient_helper.cc index c8ee697..5d61506 100644 --- a/ash/controls/scroll_view_gradient_helper.cc +++ b/ash/controls/scroll_view_gradient_helper.cc
@@ -62,8 +62,12 @@ // Vertical linear gradient, from top to bottom. gfx::LinearGradient gradient_mask(/*angle=*/-90); - float fade_position = - static_cast<float>(gradient_height_) / scroll_view_->bounds().height(); + // Clamp fade_position to the ~middle. If we don't do this, then in degenerate + // cases (where the gradients are larger than the scroll view itself) we would + // end up passing bogus values to the gradient mask. + const float fade_position = std::min( + static_cast<float>(gradient_height_) / scroll_view_->bounds().height(), + 0.49f); // Top fade in section. if (show_top_gradient) {
diff --git a/ash/drag_drop/mock_drag_drop_observer.cc b/ash/drag_drop/mock_drag_drop_observer.cc new file mode 100644 index 0000000..0a759dfd --- /dev/null +++ b/ash/drag_drop/mock_drag_drop_observer.cc
@@ -0,0 +1,18 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/drag_drop/mock_drag_drop_observer.h" + +#include "ui/aura/client/drag_drop_client.h" + +namespace ash { + +MockDragDropObserver::MockDragDropObserver( + aura::client::DragDropClient* client) { + observation_.Observe(client); +} + +MockDragDropObserver::~MockDragDropObserver() = default; + +} // namespace ash
diff --git a/ash/drag_drop/mock_drag_drop_observer.h b/ash/drag_drop/mock_drag_drop_observer.h new file mode 100644 index 0000000..2e336e4 --- /dev/null +++ b/ash/drag_drop/mock_drag_drop_observer.h
@@ -0,0 +1,45 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_DRAG_DROP_MOCK_DRAG_DROP_OBSERVER_H_ +#define ASH_DRAG_DROP_MOCK_DRAG_DROP_OBSERVER_H_ + +#include "base/scoped_observation.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/aura/client/drag_drop_client_observer.h" + +namespace aura::client { +class DragDropClient; +} // namespace aura::client + +namespace ui { +class DropTargetEvent; +} // namespace ui + +namespace ash { + +// A mock observer on drag-and-drop events. Used for testing only. +class MockDragDropObserver : public aura::client::DragDropClientObserver { + public: + explicit MockDragDropObserver(aura::client::DragDropClient* client); + MockDragDropObserver(const MockDragDropObserver&) = delete; + MockDragDropObserver& operator=(const MockDragDropObserver&) = delete; + ~MockDragDropObserver() override; + + // aura::client::DragDropClientObserver: + MOCK_METHOD(void, OnDragStarted, (), (override)); + MOCK_METHOD(void, + OnDragUpdated, + (const ui::DropTargetEvent& event), + (override)); + + private: + base::ScopedObservation<aura::client::DragDropClient, + aura::client::DragDropClientObserver> + observation_{this}; +}; + +} // namespace ash + +#endif // ASH_DRAG_DROP_MOCK_DRAG_DROP_OBSERVER_H_
diff --git a/ash/public/cpp/clipboard_history_controller.h b/ash/public/cpp/clipboard_history_controller.h index af8a96c..0c52a86 100644 --- a/ash/public/cpp/clipboard_history_controller.h +++ b/ash/public/cpp/clipboard_history_controller.h
@@ -36,13 +36,13 @@ class Observer : public base::CheckedObserver { public: // Called when the clipboard history menu is shown. - virtual void OnClipboardHistoryMenuShown() {} + virtual void OnClipboardHistoryMenuShown( + crosapi::mojom::ClipboardHistoryControllerShowSource show_source) {} // Called when the user pastes from the clipboard history menu. virtual void OnClipboardHistoryPasted() {} // Called when the clipboard history changes. virtual void OnClipboardHistoryItemListAddedOrRemoved() {} // Called when existing clipboard items in the history have changes. - // virtual void OnClipboardHistoryItemsUpdated( virtual void OnClipboardHistoryItemsUpdated( const std::vector<base::UnguessableToken>& menu_item_ids) {} };
diff --git a/ash/public/cpp/new_window_delegate.h b/ash/public/cpp/new_window_delegate.h index d57aea4..8c6578e 100644 --- a/ash/public/cpp/new_window_delegate.h +++ b/ash/public/cpp/new_window_delegate.h
@@ -111,6 +111,9 @@ // Show the keyboard shortcut viewer. virtual void ShowKeyboardShortcutViewer() = 0; + // Show the shortcut customization app. + virtual void ShowShortcutCustomizationApp() = 0; + // Shows the task manager window. virtual void ShowTaskManager() = 0;
diff --git a/ash/public/cpp/test/test_new_window_delegate.cc b/ash/public/cpp/test/test_new_window_delegate.cc index 8e533d31..736c63c 100644 --- a/ash/public/cpp/test/test_new_window_delegate.cc +++ b/ash/public/cpp/test/test_new_window_delegate.cc
@@ -33,6 +33,7 @@ void TestNewWindowDelegate::OpenGetHelp() {} void TestNewWindowDelegate::RestoreTab() {} void TestNewWindowDelegate::ShowKeyboardShortcutViewer() {} +void TestNewWindowDelegate::ShowShortcutCustomizationApp() {} void TestNewWindowDelegate::ShowTaskManager() {} void TestNewWindowDelegate::OpenFeedbackPage( FeedbackSource source,
diff --git a/ash/public/cpp/test/test_new_window_delegate.h b/ash/public/cpp/test/test_new_window_delegate.h index 4e91d8c..7c33063 100644 --- a/ash/public/cpp/test/test_new_window_delegate.h +++ b/ash/public/cpp/test/test_new_window_delegate.h
@@ -38,6 +38,7 @@ void OpenGetHelp() override; void RestoreTab() override; void ShowKeyboardShortcutViewer() override; + void ShowShortcutCustomizationApp() override; void ShowTaskManager() override; void OpenFeedbackPage(FeedbackSource source, const std::string& description_template) override;
diff --git a/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc b/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc index fb64e26..587d9944 100644 --- a/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc +++ b/ash/quick_pair/common/fast_pair/fast_pair_metrics.cc
@@ -825,6 +825,13 @@ const char kHandshakeEffectiveSuccessRate[] = "FastPair.Handshake.EffectiveSuccessRate"; const char kHandshakeAttemptCount[] = "FastPair.Handshake.AttemptCount"; +const char kGattServiceDiscoveryTime[] = + "FastPair.GattServiceDiscovery.Latency"; +const char kCreateBondTime[] = "FastPair.CreateBond.Latency"; +const char kPasskeyNotify[] = "FastPair.PasskeyNotify.Latency"; +const char kKeyBasedNotify[] = "FastPair.KeyBasedNotify.Latency"; +const char kPasskeyWriteRequest[] = "FastPair.PasskeyWriteRequest.Latency"; +const char kKeyBasedWriteRequest[] = "FastPair.KeyBasedWriteRequest.Latency"; const std::string GetEngagementFlowInitialModelIdMetric( const ash::quick_pair::Device& device) { @@ -1461,6 +1468,36 @@ base::UmaHistogramTimes(kConfirmPasskeyAskTime, total_ask_time); } +void RecordGattServiceDiscoveryTime( + base::TimeDelta total_gatt_service_discovery_time) { + base::UmaHistogramTimes(kGattServiceDiscoveryTime, + total_gatt_service_discovery_time); +} + +void RecordCreateBondTime(base::TimeDelta total_create_bond_time) { + base::UmaHistogramTimes(kCreateBondTime, total_create_bond_time); +} + +void RecordPasskeyNotifyTime(base::TimeDelta total_passkey_notify_time) { + base::UmaHistogramTimes(kPasskeyNotify, total_passkey_notify_time); +} + +void RecordKeyBasedNotifyTime(base::TimeDelta total_key_based_notify_time) { + base::UmaHistogramTimes(kKeyBasedNotify, total_key_based_notify_time); +} + +void RecordPasskeyWriteRequestTime( + base::TimeDelta total_passkey_write_request_time) { + base::UmaHistogramTimes(kPasskeyWriteRequest, + total_passkey_write_request_time); +} + +void RecordKeyBasedWriteRequestTime( + base::TimeDelta total_key_based_write_request_time) { + base::UmaHistogramTimes(kKeyBasedWriteRequest, + total_key_based_write_request_time); +} + void RecordPairFailureRetry(int num_retries) { base::UmaHistogramExactLinear(kFastPairRetryCount, num_retries, /*exclusive_max=*/10);
diff --git a/ash/quick_pair/common/fast_pair/fast_pair_metrics.h b/ash/quick_pair/common/fast_pair/fast_pair_metrics.h index 342465ead..0b1a830a 100644 --- a/ash/quick_pair/common/fast_pair/fast_pair_metrics.h +++ b/ash/quick_pair/common/fast_pair/fast_pair_metrics.h
@@ -195,13 +195,13 @@ kPairingStarted = 0, kExhaustedRetries = 1, kAlreadyPaired = 2, - kBondSuccessful = 3, + kPairingComplete = 3, kPasskeyNegotiated = 4, kRecievedPasskeyResponse = 5, kPasskeyValidated = 6, kPasskeyConfirmed = 7, - kPairingComplete = 8, - kMaxValue = kPairingComplete, + kDeviceConnected = 8, + kMaxValue = kDeviceConnected, }; COMPONENT_EXPORT(QUICK_PAIR_COMMON) @@ -436,6 +436,27 @@ void RecordConfirmPasskeyAskTime(base::TimeDelta total_ask_time); COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordGattServiceDiscoveryTime( + base::TimeDelta total_gatt_service_discovery_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordCreateBondTime(base::TimeDelta total_create_bond_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordPasskeyNotifyTime(base::TimeDelta total_passkey_notify_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordKeyBasedNotifyTime(base::TimeDelta total_key_based_notify_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordPasskeyWriteRequestTime( + base::TimeDelta total_passkey_write_request_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) +void RecordKeyBasedWriteRequestTime( + base::TimeDelta total_key_based_write_request_time); + +COMPONENT_EXPORT(QUICK_PAIR_COMMON) void RecordPairFailureRetry(int num_retries); COMPONENT_EXPORT(QUICK_PAIR_COMMON)
diff --git a/ash/quick_pair/common/pair_failure.cc b/ash/quick_pair/common/pair_failure.cc index 31f6b81..3a0b8231 100644 --- a/ash/quick_pair/common/pair_failure.cc +++ b/ash/quick_pair/common/pair_failure.cc
@@ -107,6 +107,14 @@ "connection. This is not a complete failure, and Fast Pair may " "retry.]"; break; + case PairFailure::kDisconnectResponseTimeout: + stream << "[Timed out while waiting for a response after attempt to " + "disconnect]"; + break; + case PairFailure::kFailedToConnectAfterPairing: + stream << "[Failed to connect to discovered device after pairing when " + "the device is known to the adapter.]"; + break; } return stream;
diff --git a/ash/quick_pair/common/pair_failure.h b/ash/quick_pair/common/pair_failure.h index a5d85535..16d680bb6 100644 --- a/ash/quick_pair/common/pair_failure.h +++ b/ash/quick_pair/common/pair_failure.h
@@ -78,7 +78,12 @@ // Failed to create a GATT connection in the platform layer due to a Bluetooth // device error. kBluetoothDeviceFailureCreatingGattConnection = 28, - kMaxValue = kBluetoothDeviceFailureCreatingGattConnection, + // Timed out while waiting for a response after attempt to disconnect. + kDisconnectResponseTimeout = 29, + // Failed to connect to discovered device after pairing when the device is + // known to the adapter. + kFailedToConnectAfterPairing = 30, + kMaxValue = kFailedToConnectAfterPairing, }; COMPONENT_EXPORT(QUICK_PAIR_COMMON)
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.cc b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.cc index 478c647..80ee621 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.cc +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.cc
@@ -44,6 +44,7 @@ constexpr int kMaxNumGattConnectionAttempts = 3; constexpr base::TimeDelta kCoolOffPeriodBeforeGattConnectionAfterDisconnect = base::Seconds(2); +constexpr base::TimeDelta kDisconnectResponseTimeout = base::Seconds(5); constexpr const char* ToString( device::BluetoothGattService::GattErrorCode error_code) { @@ -197,6 +198,14 @@ // is no connection established, we call `Disconnect` regardless. QP_LOG(INFO) << __func__ << ": Disconnecting any previous connections before attempt"; + + // Start a timer so if we don't get a response from the disconnect call, we + // still proceed with GATT connection attempts. + gatt_disconnect_timer_.Start( + FROM_HERE, kDisconnectResponseTimeout, + base::BindOnce(&FastPairGattServiceClientImpl::OnDisconnectTimeout, + weak_ptr_factory_.GetWeakPtr())); + device->Disconnect( base::BindOnce( &FastPairGattServiceClientImpl::CoolOffBeforeCreateGattConnection, @@ -209,6 +218,16 @@ void FastPairGattServiceClientImpl::CoolOffBeforeCreateGattConnection() { QP_LOG(INFO) << __func__; + if (!gatt_disconnect_timer_.IsRunning()) { + // The disconnect has already timed out so return early here. + QP_LOG(INFO) << __func__ + << ": Returning early due to prior disconnect timeout."; + return; + } + + // A response to the disconnect call was received, stop the associated timer. + gatt_disconnect_timer_.Stop(); + // In order for the Disconnect to propagate into the platform code, we need // a cool off period before we attempt to create a GATT connection in the case // we did disconnect an active GATT connection. @@ -218,6 +237,18 @@ weak_ptr_factory_.GetWeakPtr())); } +void FastPairGattServiceClientImpl::OnDisconnectTimeout() { + // This PairFailure is not surfaced to consumers on the + // `on_initialized_callback_` because we retry the GATT connection. We don't + // want the consumers to retry a FastPairHandshake before retries are + // complete so we log the failure here and continue with the retry if we + // haven't maxed out yet. + QP_LOG(INFO) << __func__ << ": reattempting after GATT disconnect timeout: " + << PairFailure::kDisconnectResponseTimeout; + RecordGattRetryFailureReason(PairFailure::kDisconnectResponseTimeout); + AttemptGattConnection(); +} + void FastPairGattServiceClientImpl::CreateGattConnection() { QP_LOG(INFO) << __func__; @@ -229,7 +260,7 @@ PairFailure::kPairingDeviceLostBetweenGattConnectionAttempts); return; } - + gatt_service_discovery_start_time_ = base::TimeTicks::Now(); gatt_service_discovery_timer_.Start( FROM_HERE, kGattOperationTimeout, base::BindOnce( @@ -297,6 +328,7 @@ key_based_characteristic_ = nullptr; passkey_characteristic_ = nullptr; gatt_service_discovery_timer_.Stop(); + gatt_disconnect_timer_.Stop(); passkey_notify_session_timer_.Stop(); keybased_notify_session_timer_.Stop(); passkey_write_request_timer_.Stop(); @@ -362,6 +394,8 @@ // Verify that the discovered service and device are the ones we care about. if (service->GetUUID() == kFastPairBluetoothUuid && service->GetDevice()->GetAddress() == device_address_) { + RecordGattServiceDiscoveryTime(base::TimeTicks::Now() - + gatt_service_discovery_start_time_); gatt_service_discovery_timer_.Stop(); QP_LOG(INFO) << __func__ << ": Completed discovery for Fast Pair GATT service"; @@ -434,6 +468,8 @@ void FastPairGattServiceClientImpl::OnKeyBasedRequestNotifySession( const std::vector<uint8_t>& request_data, std::unique_ptr<device::BluetoothGattNotifySession> session) { + RecordKeyBasedNotifyTime(base::TimeTicks::Now() - + keybased_notify_session_start_time_); keybased_notify_session_timer_.Stop(); notify_keybased_start_time_ = base::TimeTicks::Now(); @@ -441,6 +477,7 @@ // scope and being destroyed. key_based_notify_session_ = std::move(session); + key_based_write_request_start_time_ = base::TimeTicks::Now(); key_based_write_request_timer_.Start( FROM_HERE, kGattOperationTimeout, base::BindOnce(&FastPairGattServiceClientImpl::NotifyWriteRequestError, @@ -459,6 +496,8 @@ void FastPairGattServiceClientImpl::OnPasskeyNotifySession( const std::vector<uint8_t>& passkey_data, std::unique_ptr<device::BluetoothGattNotifySession> session) { + RecordPasskeyNotifyTime(base::TimeTicks::Now() - + passkey_notify_session_start_time_); passkey_notify_session_timer_.Stop(); notify_passkey_start_time_ = base::TimeTicks::Now(); @@ -469,6 +508,7 @@ RecordGattInitializationStep( FastPairGattConnectionSteps::kNotifiationsEnabledForKeybasedPairing); + passkey_write_request_start_time_ = base::TimeTicks::Now(); passkey_write_request_timer_.Start( FROM_HERE, kGattOperationTimeout, base::BindOnce(&FastPairGattServiceClientImpl::NotifyWritePasskeyError, @@ -589,6 +629,7 @@ public_key_vec.end()); } + keybased_notify_session_start_time_ = base::TimeTicks::Now(); keybased_notify_session_timer_.Start( FROM_HERE, kGattOperationTimeout, base::BindOnce( @@ -626,6 +667,7 @@ std::vector<uint8_t> data_to_write_vec(data_to_write.begin(), data_to_write.end()); + passkey_notify_session_start_time_ = base::TimeTicks::Now(); passkey_notify_session_timer_.Start( FROM_HERE, kGattOperationTimeout, base::BindOnce(&FastPairGattServiceClientImpl::NotifyWritePasskeyError, @@ -681,6 +723,8 @@ // we get response bytes here. if (characteristic == key_based_characteristic_ && key_based_write_response_callback_) { + RecordKeyBasedWriteRequestTime(base::TimeTicks::Now() - + key_based_write_request_start_time_); key_based_write_request_timer_.Stop(); std::move(key_based_write_response_callback_) .Run(value, /*failure=*/absl::nullopt); @@ -688,6 +732,8 @@ notify_keybased_start_time_); } else if (characteristic == passkey_characteristic_ && passkey_write_response_callback_) { + RecordPasskeyWriteRequestTime(base::TimeTicks::Now() - + passkey_write_request_start_time_); passkey_write_request_timer_.Stop(); RecordNotifyPasskeyCharacteristicTime(base::TimeTicks::Now() - notify_passkey_start_time_);
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h index d27e0ca0..b218405 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl.h
@@ -115,6 +115,7 @@ void AttemptGattConnection(); void CreateGattConnection(); void CoolOffBeforeCreateGattConnection(); + void OnDisconnectTimeout(); void OnGattServiceDiscoveryTimeout(); // Callback from the adapter's call to create GATT connection. @@ -170,6 +171,7 @@ device::BluetoothGattService::GattErrorCode error); base::OneShotTimer gatt_connect_after_disconnect_cool_off_timer_; + base::OneShotTimer gatt_disconnect_timer_; base::OneShotTimer gatt_service_discovery_timer_; base::OneShotTimer passkey_notify_session_timer_; base::OneShotTimer keybased_notify_session_timer_; @@ -177,6 +179,12 @@ base::OneShotTimer key_based_write_request_timer_; base::OneShotTimer account_key_write_request_timer_; + base::TimeTicks gatt_service_discovery_start_time_; + base::TimeTicks passkey_notify_session_start_time_; + base::TimeTicks keybased_notify_session_start_time_; + base::TimeTicks passkey_write_request_start_time_; + base::TimeTicks key_based_write_request_start_time_; + base::OnceCallback<void(absl::optional<PairFailure>)> on_initialized_callback_; base::OnceCallback<void(std::vector<uint8_t>, absl::optional<PairFailure>)>
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl_unittest.cc b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl_unittest.cc index 96ea6eb..8372b9d 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl_unittest.cc +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client_impl_unittest.cc
@@ -63,11 +63,20 @@ const char kFastPairGattConnectionStep[] = "FastPair.GattConnection"; const char kFastPairGattRetryFailureReason[] = "Bluetooth.ChromeOS.FastPair.GattConnection.RetryFailureReason"; +const char kGattServiceDiscoveryTime[] = + "FastPair.GattServiceDiscovery.Latency"; +const char kPasskeyNotify[] = "FastPair.PasskeyNotify.Latency"; +const char kKeyBasedNotify[] = "FastPair.KeyBasedNotify.Latency"; +const char kPasskeyWriteRequest[] = "FastPair.PasskeyWriteRequest.Latency"; +const char kKeyBasedWriteRequest[] = "FastPair.KeyBasedWriteRequest.Latency"; +/* + */ constexpr base::TimeDelta kConnectingTestTimeout = base::Seconds(15); constexpr base::TimeDelta kSimulateStackFrameHangSeconds = base::Seconds(90); constexpr base::TimeDelta kCoolOffPeriodBeforeGattConnectionAfterDisconnect = base::Seconds(2); +constexpr base::TimeDelta kDisconnectResponseTimeout = base::Seconds(5); // 51 seconds is from 2 seconds for a cooloff period before GATT connection // attempts * 3 GATT attempts + 15 seconds GATT connecting timeout * 3 GATT @@ -162,7 +171,9 @@ base::OnceClosure error_callback) override { was_disconnect_called_ = true; if (has_disconnect_error_) { - std::move(error_callback).Run(); + if (!no_disconnect_response_) { + std::move(error_callback).Run(); + } return; } std::move(callback).Run(); @@ -172,6 +183,10 @@ has_disconnect_error_ = has_disconnect_error; } + void SetNoDisconnectResponse(bool no_disconnect_response) { + no_disconnect_response_ = no_disconnect_response; + } + bool WasDisconnectCalled() { return was_disconnect_called_; } void SetError(bool has_gatt_connection_error) { @@ -195,6 +210,7 @@ bool has_gatt_connection_error_ = false; bool has_gatt_connection_hang_ = false; bool has_disconnect_error_ = false; + bool no_disconnect_response_ = false; base::test::TaskEnvironment* task_environment_ = nullptr; ash::quick_pair::FakeBluetoothAdapter* fake_adapter_ = nullptr; }; @@ -356,6 +372,21 @@ weak_ptr_factory_.GetWeakPtr())); } + void NoDisconectResponseGattSetup() { + adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>(); + unique_fake_bt_device_ = CreateTestBluetoothDevice( + adapter_.get(), ash::quick_pair::kFastPairBluetoothUuid); + unique_fake_bt_device_->SetDisconnectError(true); + unique_fake_bt_device_->SetNoDisconnectResponse(true); + raw_fake_bt_device_ = unique_fake_bt_device_.get(); + adapter_->AddMockDevice(std::move(unique_fake_bt_device_)); + gatt_service_client_ = FastPairGattServiceClientImpl::Factory::Create( + adapter_->GetDevice(kTestBleDeviceAddress), adapter_.get(), + base::BindRepeating(&::ash::quick_pair::FastPairGattServiceClientTest:: + InitializedTestCallback, + weak_ptr_factory_.GetWeakPtr())); + } + void NonFastPairServiceDataSetUp() { adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>(); unique_fake_bt_device_ = @@ -534,6 +565,10 @@ kCoolOffPeriodBeforeGattConnectionAfterDisconnect); } + void FastForwardTimeByGattDisconnectResponseTimeout() { + task_environment_.FastForwardBy(kDisconnectResponseTimeout); + } + void FastForwardTimeByAllGattRetries() { task_environment_.FastForwardBy(kAllGattRetriesPeriod); } @@ -676,6 +711,7 @@ histogram_tester().ExpectTotalCount(kGattConnectionResult, 1); histogram_tester().ExpectTotalCount(kGattConnectionEffectiveSuccessRate, 1); histogram_tester().ExpectTotalCount(kGattConnectionAttemptCount, 1); + histogram_tester().ExpectTotalCount(kGattServiceDiscoveryTime, 1); histogram_tester().ExpectTotalCount(kGattConnectionErrorMetric, 0); histogram_tester().ExpectTotalCount(kWriteKeyBasedCharacteristicGattError, 0); histogram_tester().ExpectTotalCount(kNotifyKeyBasedCharacteristicTime, 0); @@ -807,6 +843,8 @@ histogram_tester().ExpectTotalCount(kFastPairGattConnectionStep, 4); histogram_tester().ExpectTotalCount(kWriteKeyBasedCharacteristicGattError, 0); histogram_tester().ExpectTotalCount(kNotifyKeyBasedCharacteristicTime, 1); + histogram_tester().ExpectTotalCount(kKeyBasedNotify, 1); + histogram_tester().ExpectTotalCount(kKeyBasedWriteRequest, 1); } TEST_F(FastPairGattServiceClientTest, WriteKeyBasedRequestError) { @@ -853,6 +891,8 @@ EXPECT_EQ(GetWriteCallbackResult(), absl::nullopt); histogram_tester().ExpectTotalCount(kWritePasskeyCharacteristicGattError, 0); histogram_tester().ExpectTotalCount(kNotifyPasskeyCharacteristicTime, 1); + histogram_tester().ExpectTotalCount(kPasskeyNotify, 1); + histogram_tester().ExpectTotalCount(kPasskeyWriteRequest, 1); } TEST_F(FastPairGattServiceClientTest, WritePasskeyRequestError) { @@ -982,6 +1022,16 @@ EXPECT_TRUE(raw_fake_bt_device_->WasDisconnectCalled()); } +TEST_F(FastPairGattServiceClientTest, + FailedToRecieveDisconnectResponseAfterGattFailure) { + DisconectFailGattSetup(); + FastForwardTimeByGattDisconnectResponseTimeout(); + EXPECT_EQ(GetInitializedCallbackResult(), + PairFailure::kFailureToDisconnectGattBetweenRetries); + EXPECT_FALSE(ServiceIsSet()); + EXPECT_TRUE(raw_fake_bt_device_->WasDisconnectCalled()); +} + TEST_F(FastPairGattServiceClientTest, SuccessfulGattConnectionDisconnects) { SuccessfulGattConnectionSetUp(); FastForwardTimeByGattDisconnectCoolOff();
diff --git a/ash/quick_pair/keyed_service/quick_pair_mediator.cc b/ash/quick_pair/keyed_service/quick_pair_mediator.cc index 2c59a7c4..86ca2ed 100644 --- a/ash/quick_pair/keyed_service/quick_pair_mediator.cc +++ b/ash/quick_pair/keyed_service/quick_pair_mediator.cc
@@ -450,8 +450,13 @@ CancelPairing(); } } -// TODO(b/243586447): Remove this function and associated changes that were used -// to disable FastPair while classic pair dialog was open. + +// TODO(b/243586447): Investigate why the classic BT pairing dialog being open +// interferes with Fast Pair GATT connections. +// +// The logic here is necessary to prevent Fast Pair connecting notification +// hanging when Fast Pair pairing has starting and the classic BT pairing +// dialog is open. void Mediator::OnHasAtLeastOneDiscoverySessionChanged( bool has_at_least_one_discovery_session) { has_at_least_one_discovery_session_ = has_at_least_one_discovery_session; @@ -459,6 +464,19 @@ << ": Discovery session status changed, we" " have at least one discovery session: " << has_at_least_one_discovery_session_; + + // If we have a discovery session via the Settings pairing dialog, stop + // Fast Pair scanning. Else, start/stop scanning according to the feature + // status tracker. + SetFastPairState(!has_at_least_one_discovery_session_ && + feature_status_tracker_->IsFastPairEnabled()); + + // If we haven't begun pairing, dismiss all in-progress handshakes which + // will interfere with the discovery session. Note that V1 device Fast Pair + // via the Settings pairing dialog, so we also check for that case here. + if (has_at_least_one_discovery_session_ && !pairer_broker_->IsPairing()) { + CancelPairing(); + } } } // namespace quick_pair
diff --git a/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc b/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc index 7a99d92..709826f 100644 --- a/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc +++ b/ash/quick_pair/keyed_service/quick_pair_mediator_unittest.cc
@@ -196,6 +196,86 @@ feature_status_tracker_->SetIsFastPairEnabled(true); EXPECT_CALL(*mock_scanner_broker_, StopScanning); feature_status_tracker_->SetIsFastPairEnabled(false); + + // When one or more discovery sessions are active, don't toggle + // scanning when fast pair enabled changes. + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(true); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + feature_status_tracker_->SetIsFastPairEnabled(true); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + feature_status_tracker_->SetIsFastPairEnabled(false); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + feature_status_tracker_->SetIsFastPairEnabled(true); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + feature_status_tracker_->SetIsFastPairEnabled(false); +} + +TEST_F(MediatorTest, TogglesScanningWhenHasAtLeastOneDiscoverySessionChanges) { + EXPECT_CALL(*mock_scanner_broker_, StartScanning); + feature_status_tracker_->SetIsFastPairEnabled(true); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(true); + EXPECT_CALL(*mock_scanner_broker_, StartScanning); + SetHasAtLeastOneDiscoverySessionChanged(false); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(true); + + // When fast pair is disabled, don't toggle scanning when "we have at + // least one discovery session" changes. + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + feature_status_tracker_->SetIsFastPairEnabled(false); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(false); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(true); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + SetHasAtLeastOneDiscoverySessionChanged(false); +} + +TEST_F(MediatorTest, + CancelsPairingsWhenHasAtLeastOneDiscoverySessionChangesNotPairing) { + // Start with fast pair enabled and one handshake in progress. + feature_status_tracker_->SetIsFastPairEnabled(true); + FastPairHandshakeLookup::GetInstance()->Create(adapter_, initial_device_, + base::DoNothing()); + EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(initial_device_)); + + // When one or more discovery sessions are active, stop scanning and dismiss + // notifications. If we aren't actively pairing, dismiss all handshakes. + EXPECT_CALL(*mock_pairer_broker_, IsPairing).WillOnce(Return(false)); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + EXPECT_CALL(*mock_pairer_broker_, StopPairing); + EXPECT_CALL(*mock_ui_broker_, RemoveNotifications); + SetHasAtLeastOneDiscoverySessionChanged(true); + EXPECT_FALSE(FastPairHandshakeLookup::GetInstance()->Get(initial_device_)); + + // When no discovery sessions are active, resume scanning. + EXPECT_CALL(*mock_scanner_broker_, StartScanning); + SetHasAtLeastOneDiscoverySessionChanged(false); +} + +TEST_F(MediatorTest, + CancelsPairingsWhenHasAtLeastOneDiscoverySessionChangesIsPairing) { + // Start with fast pair enabled and one handshake in progress. + feature_status_tracker_->SetIsFastPairEnabled(true); + FastPairHandshakeLookup::GetInstance()->Create(adapter_, initial_device_, + base::DoNothing()); + EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(initial_device_)); + + // When one or more discovery sessions are active, stop scanning and dismiss + // notifications. Simulate the case where the user has already begun pairing + // before opening Settings, or has initiated V1 device pair. + EXPECT_CALL(*mock_pairer_broker_, IsPairing).WillOnce(Return(true)); + EXPECT_CALL(*mock_scanner_broker_, StopScanning); + EXPECT_CALL(*mock_pairer_broker_, StopPairing).Times(0); + EXPECT_CALL(*mock_ui_broker_, RemoveNotifications); + SetHasAtLeastOneDiscoverySessionChanged(true); + EXPECT_TRUE(FastPairHandshakeLookup::GetInstance()->Get(initial_device_)); + + // When no discovery sessions are active, resume scanning. + EXPECT_CALL(*mock_scanner_broker_, StartScanning); + SetHasAtLeastOneDiscoverySessionChanged(false); } TEST_F(MediatorTest, CancelsPairingsWhenFastPairDisabled) {
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc index 3ad1c40d..9bc1f67c 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.cc
@@ -35,7 +35,6 @@ // 15s timeouts chosen to align with Android's Fast Pair implementation. constexpr base::TimeDelta kCreateBondTimeout = base::Seconds(15); -constexpr base::TimeDelta kConfirmPasskeyTimeout = base::Seconds(15); std::string MessageTypeToString( ash::quick_pair::FastPairMessageType message_type) { @@ -183,27 +182,62 @@ "returning success."; RecordProtocolPairingStep(FastPairProtocolPairingSteps::kAlreadyPaired, *device_); - RecordProtocolPairingStep( - FastPairProtocolPairingSteps::kPairingComplete, *device_); AttemptRecordingFastPairEngagementFlow( *device_, FastPairEngagementFlowEvent::kPairingSucceededAlreadyPaired); std::move(paired_callback_).Run(device_); + + if (!bt_device->IsConnected()) { + QP_LOG(INFO) << __func__ << ": connecting a paired device"; + create_bond_start_time_ = base::TimeTicks::Now(); + create_bond_timeout_timer_.Start( + FROM_HERE, kCreateBondTimeout, + base::BindOnce(&FastPairPairerImpl::OnCreateBondTimeout, + weak_ptr_factory_.GetWeakPtr())); + bt_device->Connect(/*pairing_delegate=*/this, + base::BindOnce(&FastPairPairerImpl::OnConnected, + weak_ptr_factory_.GetWeakPtr())); + return; + } + + RecordProtocolPairingStep( + FastPairProtocolPairingSteps::kDeviceConnected, *device_); AttemptSendAccountKey(); return; } + // There are two flows a device can go through for V2 pairing: + // `device::BluetoothAdapter::ConnectDevice` and + // `device::BluetoothDevice::Pair`. The flows for each are as follows: + // + // ConnectDevice : `ConnectDevice` -> `OnConnectDevice -> `ConfirmPasskey` + // -> `WritePasskeyAsync` -> `OnPasskeyResponse` -> `DevicePairedChanged` + // + // Pair: `Pair` -> `ConfirmPasskey` -> `WritePasskeyAsync` -> + // `OnPasskeyResponse` -> `DevicePairedChanged` -> `OnPairConnected` -> + // `Connect` -> `OnConnected` + // + // This timer captures a bonding timeout for the both scenarios. + create_bond_start_time_ = base::TimeTicks::Now(); create_bond_timeout_timer_.Start( FROM_HERE, kCreateBondTimeout, base::BindOnce(&FastPairPairerImpl::OnCreateBondTimeout, - base::Unretained(this))); + weak_ptr_factory_.GetWeakPtr())); + // TODO(b/266502308): Re-evaluate how we can force a Bluetooth profile + // for a device to avoid `device::BluetoothAdapter::ConnectDevice` API. + // + // The Sony SRS-XB13 is expected to fail `ConnectDevice`, due to SDP + // collisions, and succeed on a second retry with + // `device::BluetoothDevice::Pair` because the device profile is ready. if (bt_device) { - bt_device->Pair(this, + pairing_flow_ = FastPairPairingFlow::kPair; + bt_device->Pair(/*pairing_delegate=*/this, base::BindOnce(&FastPairPairerImpl::OnPairConnected, weak_ptr_factory_.GetWeakPtr())); } else { + pairing_flow_ = FastPairPairingFlow::kConnectDevice; adapter_->AddPairingDelegate( this, device::BluetoothAdapter::PairingDelegatePriority:: PAIRING_DELEGATE_PRIORITY_HIGH); @@ -226,47 +260,10 @@ } } -void FastPairPairerImpl::OnPairConnected( - absl::optional<device::BluetoothDevice::ConnectErrorCode> error) { - if (!StopCreateBondTimer(__func__)) { - return; - } - - QP_LOG(INFO) << __func__; - RecordPairDeviceResult(/*success=*/!error.has_value()); - - if (error) { - QP_LOG(WARNING) << "Failed to start pairing procedure by pairing to " - "device due to error: " - << error.value(); - std::move(pair_failed_callback_).Run(device_, PairFailure::kPairingConnect); - // |this| may be destroyed after this line. - RecordPairDeviceErrorReason(error.value()); - return; - } - - RecordProtocolPairingStep(FastPairProtocolPairingSteps::kBondSuccessful, - *device_); - ask_confirm_passkey_initial_time_ = base::TimeTicks::Now(); - confirm_passkey_timeout_timer_.Start( - FROM_HERE, kConfirmPasskeyTimeout, - base::BindOnce(&FastPairPairerImpl::OnConfirmPasskeyTimeout, - base::Unretained(this))); -} - void FastPairPairerImpl::OnConnectDevice(device::BluetoothDevice* device) { - if (!StopCreateBondTimer(__func__)) { - return; - } - QP_LOG(INFO) << __func__; - RecordProtocolPairingStep(FastPairProtocolPairingSteps::kBondSuccessful, + RecordProtocolPairingStep(FastPairProtocolPairingSteps::kDeviceConnected, *device_); - ask_confirm_passkey_initial_time_ = base::TimeTicks::Now(); - confirm_passkey_timeout_timer_.Start( - FROM_HERE, kConfirmPasskeyTimeout, - base::BindOnce(&FastPairPairerImpl::OnConfirmPasskeyTimeout, - base::Unretained(this))); RecordConnectDeviceResult(/*success=*/true); // The device ID can change between device discovery and connection, so // ensure that device images are mapped to the current device ID. @@ -286,13 +283,9 @@ void FastPairPairerImpl::ConfirmPasskey(device::BluetoothDevice* device, uint32_t passkey) { - confirm_passkey_timeout_timer_.Stop(); QP_LOG(INFO) << __func__; RecordProtocolPairingStep(FastPairProtocolPairingSteps::kPasskeyNegotiated, *device_); - RecordConfirmPasskeyAskTime(base::TimeTicks::Now() - - ask_confirm_passkey_initial_time_); - confirm_passkey_initial_time_ = base::TimeTicks::Now(); // TODO(b/251281330): Make handling this edge case more robust. // @@ -304,6 +297,10 @@ if (!FastPairHandshakeLookup::GetInstance()->Get(device_)) { QP_LOG(ERROR) << __func__ << ": BLE device instance lost during passkey exchange"; + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); device->CancelPairing(); std::move(pair_failed_callback_) .Run(device_, PairFailure::kBleDeviceLostMidPair); @@ -330,6 +327,10 @@ if (failure) { QP_LOG(WARNING) << __func__ << ": Failed to write passkey. Error: " << failure.value(); + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); RecordWritePasskeyCharacteristicPairFailure(failure.value()); std::move(pair_failed_callback_).Run(device_, failure.value()); // |this| may be destroyed after this line. @@ -347,10 +348,14 @@ const absl::optional<DecryptedPasskey>& passkey) { if (!passkey) { QP_LOG(WARNING) << "Missing decrypted passkey from parse."; + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); + RecordPasskeyCharacteristicDecryptResult(/*success=*/false); std::move(pair_failed_callback_) .Run(device_, PairFailure::kPasskeyDecryptFailure); // |this| may be destroyed after this line. - RecordPasskeyCharacteristicDecryptResult(/*success=*/false); return; } @@ -359,10 +364,14 @@ << "Incorrect message type from decrypted passkey. Expected: " << MessageTypeToString(FastPairMessageType::kProvidersPasskey) << ". Actual: " << MessageTypeToString(passkey->message_type); + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); + RecordPasskeyCharacteristicDecryptResult(/*success=*/false); std::move(pair_failed_callback_) .Run(device_, PairFailure::kIncorrectPasskeyResponseType); // |this| may be destroyed after this line. - RecordPasskeyCharacteristicDecryptResult(/*success=*/false); return; } @@ -372,26 +381,30 @@ if (passkey->passkey != expected_passkey_) { QP_LOG(ERROR) << "Passkeys do not match. Expected: " << expected_passkey_ << ". Actual: " << passkey->passkey; + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); + RecordPasskeyCharacteristicDecryptResult(/*success=*/false); std::move(pair_failed_callback_) .Run(device_, PairFailure::kPasskeyMismatch); // |this| may be destroyed after this line. - RecordPasskeyCharacteristicDecryptResult(/*success=*/false); return; } RecordProtocolPairingStep(FastPairProtocolPairingSteps::kPasskeyConfirmed, *device_); RecordPasskeyCharacteristicDecryptResult(/*success=*/true); - RecordPasskeyCharacteristicDecryptTime(base::TimeTicks::Now() - - decrypt_start_time); - RecordConfirmPasskeyConfirmTime(base::TimeTicks::Now() - - confirm_passkey_initial_time_); device::BluetoothDevice* pairing_device = adapter_->GetDevice(pairing_device_address_); if (!pairing_device) { - QP_LOG(ERROR) << "Bluetooth pairing device lost during write to passkey."; + QP_LOG(WARNING) << "Bluetooth pairing device lost during write to passkey."; + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state. + StopCreateBondTimer(__func__); std::move(pair_failed_callback_) .Run(device_, PairFailure::kPairingDeviceLost); // |this| may be destroyed after this line. @@ -632,6 +645,7 @@ if (device->GetAddress() == device_->ble_address() || device->GetAddress() == device_->classic_address()) { QP_LOG(INFO) << __func__ << ": Completing pairing procedure " << device_; + RecordProtocolPairingStep(FastPairProtocolPairingSteps::kPairingComplete, *device_); @@ -642,18 +656,123 @@ // |pairing_procedure_complete_| whereas V1 devices need to run the callback // in this function since they don't write account keys, and their pairing // procedure is not complete at this point. + // + // For `ConnectDevice`, this is the end of the flow. Stop the timer since + // we have reached a terminal state of success, and start sending the + // account key. For `Pair`, we don't `AttemptSendAccountKey` until after + // `OnConnected` fires. if (device_->version().has_value() && - device_->version().value() == DeviceFastPairVersion::kHigherThanV1) { + device_->version().value() == DeviceFastPairVersion::kHigherThanV1 && + pairing_flow_ == FastPairPairingFlow::kConnectDevice) { + StopCreateBondTimer(__func__); + QP_LOG(INFO) << __func__ + << ": Stopping create bond timer and attempting to send " + "account key for ConnectDevice flow"; adapter_->RemovePairingDelegate(this); AttemptSendAccountKey(); - } else if (pairing_procedure_complete_) { + } else if (pairing_procedure_complete_ && device_->version().has_value() && + device_->version().value() == DeviceFastPairVersion::kV1) { // This covers the case where we are pairing a v1 device and are using the // Bluetooth pairing dialog to do it. + QP_LOG(INFO) << __func__ + << ": pairing procedure completed for V1 device."; std::move(pairing_procedure_complete_).Run(device_); } } } +void FastPairPairerImpl::OnPairConnected( + absl::optional<device::BluetoothDevice::ConnectErrorCode> error) { + // Check that the timer is still running before continuing. If the timer has + // expired, then we already have surface an error through + // `OnCreateBondTimeout` and we should not continue here. This handles the + // case where this object has not been destroyed yet following a PairFailure, + // and the `OnPairConnected` callback executes. + if (!create_bond_timeout_timer_.IsRunning()) { + return; + } + + QP_LOG(INFO) << __func__; + + if (error) { + QP_LOG(WARNING) << __func__ + << ": Failed to start pairing procedure by pairing to " + "device due to error: " + << error.value(); + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state for the `Pair` flow. + StopCreateBondTimer(__func__); + RecordPairDeviceErrorReason(error.value()); + RecordPairDeviceResult(/*success=*/false); + // |this| may be destroyed after this line. + std::move(pair_failed_callback_).Run(device_, PairFailure::kPairingConnect); + return; + } + + std::string device_address = device_->classic_address().value(); + device::BluetoothDevice* bt_device = adapter_->GetDevice(device_address); + if (!bt_device) { + QP_LOG(WARNING) + << __func__ + << ": Bluetooth pairing device lost during during device connection"; + + // Stop create bond timer on error because at this point, the pairing is + // in a terminal state for the `Pair` flow. + StopCreateBondTimer(__func__); + std::move(pair_failed_callback_) + .Run(device_, PairFailure::kPairingDeviceLost); + // |this| may be destroyed after this line. + return; + } + + // We must follow `Pair` with `Connect`. Not all Fast Pair devices initiate + // a connection following pairing. For device that do initiate connecting + // following pairing, this may result in `OnConnected` to return a failure, + // however the connection is successful. + QP_LOG(VERBOSE) << __func__ + << ": attempting connection to device following pair"; + bt_device->Connect(/*pairing_delegate=*/this, + base::BindOnce(&FastPairPairerImpl::OnConnected, + weak_ptr_factory_.GetWeakPtr())); +} + +void FastPairPairerImpl::OnConnected( + absl::optional<device::BluetoothDevice::ConnectErrorCode> error) { + // Terminal state for `Pair` flow, so we stop the timer here for this path. + // We don't need to check which flow we are in here, since we can only + // reach this point with `Pair`. + if (!StopCreateBondTimer(__func__)) { + return; + } + + QP_LOG(INFO) << __func__; + RecordPairDeviceResult(/*success=*/!error.has_value()); + + if (error) { + QP_LOG(WARNING) << __func__ + << ": Failed to start pairing procedure by pairing to " + "device due to error: " + << error.value(); + RecordPairDeviceErrorReason(error.value()); + std::move(pair_failed_callback_) + .Run(device_, PairFailure::kFailedToConnectAfterPairing); + // |this| may be destroyed after this line. + return; + } + + RecordProtocolPairingStep(FastPairProtocolPairingSteps::kDeviceConnected, + *device_); + + // The device ID can change between device discovery and connection, so + // ensure that device images are mapped to the current device ID. + FastPairRepository::Get()->FetchDeviceImages(device_); + + QP_LOG(INFO) << __func__ << ": starting account key write for `Pair` flow"; + adapter_->RemovePairingDelegate(this); + AttemptSendAccountKey(); +} + void FastPairPairerImpl::OnCreateBondTimeout() { QP_LOG(WARNING) << __func__ << ": Timeout while attempting to create bond with device."; @@ -661,16 +780,9 @@ .Run(device_, PairFailure::kCreateBondTimeout); } -void FastPairPairerImpl::OnConfirmPasskeyTimeout() { - QP_LOG(WARNING) - << __func__ - << ": Timeout while awaiting passkey from GATT connected device."; - std::move(pair_failed_callback_) - .Run(device_, PairFailure::kConfirmPasskeyTimeout); -} - bool FastPairPairerImpl::StopCreateBondTimer(const std::string& callback_name) { if (create_bond_timeout_timer_.IsRunning()) { + RecordCreateBondTime(base::TimeTicks::Now() - create_bond_start_time_); create_bond_timeout_timer_.Stop(); return true; }
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h index ad5d973b..6ed0672e 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl.h
@@ -89,6 +89,25 @@ ~FastPairPairerImpl() override; private: + // There are two flows a device can go through for V2 pairing: + // `device::BluetoothAdapter::ConnectDevice` and + // `device::BluetoothDevice::Pair`. The flows for each are as follows: + // + // ConnectDevice : `ConnectDevice` -> `OnConnectDevice -> `ConfirmPasskey` -> + // `WritePasskeyAsync` -> `OnPasskeyResponse` -> `DevicePairedChanged` + // + // Pair: `Pair` -> `ConfirmPasskey` -> `WritePasskeyAsync` -> + // `OnPasskeyResponse` -> `DevicePairedChanged` -> `OnPairConnected` -> + // `Connect` -> `OnConnected` + // + // We need to capture which flow we are using in order to correctly stop + // the bonding timer when the flow has ended, since each has a different + // end. + enum class FastPairPairingFlow { + kConnectDevice, + kPair, + }; + // device::BluetoothDevice::PairingDelegate void RequestPinCode(device::BluetoothDevice* device) override; void ConfirmPasskey(device::BluetoothDevice* device, @@ -101,7 +120,7 @@ void KeysEntered(device::BluetoothDevice* device, uint32_t entered) override; void AuthorizePairing(device::BluetoothDevice* device) override; - // device::BluetoothAdapter::Obserer + // device::BluetoothAdapter::Observer void DevicePairedChanged(device::BluetoothAdapter* adapter, device::BluetoothDevice* device, bool new_paired_status) override; @@ -117,6 +136,10 @@ void OnPairConnected( absl::optional<device::BluetoothDevice::ConnectErrorCode> error); + // device::BluetoothDevice::Connect callback + void OnConnected( + absl::optional<device::BluetoothDevice::ConnectErrorCode> error); + // device::BluetoothAdapter::ConnectDevice callbacks void OnConnectDevice(device::BluetoothDevice* device); void OnConnectError(const std::string& error_message); @@ -125,9 +148,6 @@ // StartPairing. void OnCreateBondTimeout(); - // Callback for timeout on waiting to confirm |device_|'s passkey. - void OnConfirmPasskeyTimeout(); - // FastPairHandshakeLookup::Create callback void OnHandshakeComplete(scoped_refptr<Device> device, absl::optional<PairFailure> failure); @@ -161,10 +181,7 @@ void WriteAccountKey(); - // Initial timestamps used for metrics. - base::TimeTicks ask_confirm_passkey_initial_time_; - base::TimeTicks confirm_passkey_initial_time_; - + FastPairPairingFlow pairing_flow_; uint32_t expected_passkey_; scoped_refptr<device::BluetoothAdapter> adapter_; scoped_refptr<Device> device_; @@ -184,10 +201,8 @@ // A timer to time the bonding with |device_| in StartPairing and invoke a // timeout if necessary. base::OneShotTimer create_bond_timeout_timer_; + base::TimeTicks create_bond_start_time_; - // A timer which allows this pairer to time out while waiting to confirm - // |device_|'s passkey. - base::OneShotTimer confirm_passkey_timeout_timer_; base::WeakPtrFactory<FastPairPairerImpl> weak_ptr_factory_{this}; };
diff --git a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc index 2d5bd0da..5668c46 100644 --- a/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc +++ b/ash/quick_pair/pairing/fast_pair/fast_pair_pairer_impl_unittest.cc
@@ -50,8 +50,6 @@ namespace { constexpr base::TimeDelta kCreateBondTimeout = base::Seconds(15); -constexpr base::TimeDelta kConfirmPasskeyTimeout = base::Seconds(15); - const std::vector<uint8_t> kResponseBytes = {0x01, 0x5E, 0x3F, 0x45, 0x61, 0xC3, 0x32, 0x1D, 0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6}; @@ -78,8 +76,6 @@ "Bluetooth.ChromeOS.FastPair.Passkey.Write.Result"; const char kWritePasskeyCharacteristicPairFailureMetric[] = "Bluetooth.ChromeOS.FastPair.Passkey.Write.PairFailure"; -const char kPasskeyCharacteristicDecryptTime[] = - "Bluetooth.ChromeOS.FastPair.Passkey.Decrypt.Time"; const char kPasskeyCharacteristicDecryptResult[] = "Bluetooth.ChromeOS.FastPair.Passkey.Decrypt.Result"; const char kWriteAccountKeyCharacteristicResultMetric[] = @@ -90,10 +86,6 @@ "Bluetooth.ChromeOS.FastPair.PairDevice.Result"; const char kPairDeviceErrorReason[] = "Bluetooth.ChromeOS.FastPair.PairDevice.ErrorReason"; -const char kConfirmPasskeyAskTime[] = - "Bluetooth.ChromeOS.FastPair.RequestPasskey.Latency"; -const char kConfirmPasskeyConfirmTime[] = - "Bluetooth.ChromeOS.FastPair.ConfirmPasskey.Latency"; const char kSavedDeviceUpdateOptInStatusInitialResult[] = "Bluetooth.ChromeOS.FastPair.SavedDevices.UpdateOptInStatus.Result." "InitialPairingProtocol"; @@ -110,6 +102,7 @@ "FastPair.SubsequentPairing.Pairing"; constexpr char kInitializePairingProcessInitial[] = "FastPair.InitialPairing.Initialization"; +const char kCreateBondTime[] = "FastPair.CreateBond.Latency"; class FakeBluetoothDevice : public testing::NiceMock<device::MockBluetoothDevice> { @@ -141,6 +134,26 @@ return; } + pair_callback_ = std::move(callback); + } + + void TriggerPairCallback() { + std::move(pair_callback_).Run(/*error_code=*/absl::nullopt); + } + + void Connect( + BluetoothDevice::PairingDelegate* pairing_delegate, + base::OnceCallback<void(absl::optional<ConnectErrorCode> error_code)> + callback) override { + if (connect_failure_) { + std::move(callback).Run(ConnectErrorCode::ERROR_FAILED); + return; + } + + if (connect_timeout_) { + return; + } + std::move(callback).Run(absl::nullopt); } @@ -148,14 +161,22 @@ void SetPairTimeout() { pair_timeout_ = true; } + void SetConnectFailure() { connect_failure_ = true; } + + void SetConnectTimeout() { connect_timeout_ = true; } + void ConfirmPairing() override { is_device_paired_ = true; } bool IsDevicePaired() { return is_device_paired_; } protected: + base::OnceCallback<void(absl::optional<ConnectErrorCode> error_code)> + pair_callback_; ash::quick_pair::FakeBluetoothAdapter* fake_adapter_; bool pair_failure_ = false; bool pair_timeout_ = false; + bool connect_failure_ = false; + bool connect_timeout_ = false; bool is_device_paired_ = false; }; @@ -324,10 +345,20 @@ void SetPairFailure() { fake_bluetooth_device_ptr_->SetPairFailure(); } + void SetConnectFailureAfterPair() { + fake_bluetooth_device_ptr_->SetConnectFailure(); + } + // Causes FakeBluetoothDevice::Pair() to hang instead of triggering either a // success or a failure callback. void SetPairTimeout() { fake_bluetooth_device_ptr_->SetPairTimeout(); } + // Causes FakeBluetoothDevice::Connect() to hang instead of triggering either + // a success or a failure callback. + void SetConnectTimeoutAfterPair() { + fake_bluetooth_device_ptr_->SetConnectTimeout(); + } + void SetConnectFailure() { adapter_->SetConnectFailure(); } // Causes FakeBluetoothAdapter::ConnectDevice() to hang instead of triggering @@ -472,6 +503,44 @@ // PairByDevice refers to the fact that we aren't pairing by address, unlike // most other tests in this file. +TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_ConnectFailure_Initial) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + + histogram_tester().ExpectTotalCount(kPairDeviceResult, 0); + histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 0); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + SetConnectFailureAfterPair(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); + EXPECT_EQ(GetPairFailure(), PairFailure::kFailedToConnectAfterPairing); + histogram_tester().ExpectTotalCount(kPairDeviceResult, 1); + histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 1); +} + +// PairByDevice refers to the fact that we aren't pairing by address, unlike +// most other tests in this file. +TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_ConnectFailure_Subsequent) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + + histogram_tester().ExpectTotalCount(kPairDeviceResult, 0); + histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 0); + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairSubsequent); + SetConnectFailureAfterPair(); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); + EXPECT_EQ(GetPairFailure(), PairFailure::kFailedToConnectAfterPairing); + histogram_tester().ExpectTotalCount(kPairDeviceResult, 1); + histogram_tester().ExpectTotalCount(kPairDeviceErrorReason, 1); +} + +// PairByDevice refers to the fact that we aren't pairing by address, unlike +// most other tests in this file. TEST_F(FastPairPairerImplTest, PairByDeviceFailure_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); @@ -531,10 +600,12 @@ AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful}); + FastPairProtocolPairingSteps::kDeviceConnected}); + histogram_tester().ExpectTotalCount(kCreateBondTime, 1); } TEST_F(FastPairPairerImplTest, @@ -548,6 +619,8 @@ // Mock that the device is already paired. EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); + EXPECT_CALL(*fake_bluetooth_device_ptr_, IsConnected()) + .WillOnce(Return(true)); EXPECT_CALL(paired_callback_, Run); CreatePairer(); @@ -560,7 +633,35 @@ ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, FastPairProtocolPairingSteps::kAlreadyPaired, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); +} + +TEST_F(FastPairPairerImplTest, + PairByDeviceSuccess_Initial_AlreadyClassicPaired_Disconnected) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + + // Mock that the device is already paired. + EXPECT_CALL(*fake_bluetooth_device_ptr_, IsBonded()).WillOnce(Return(true)); + EXPECT_CALL(*fake_bluetooth_device_ptr_, IsConnected()) + .WillOnce(Return(false)); + EXPECT_CALL(paired_callback_, Run); + CreatePairer(); + + EXPECT_EQ(GetPairFailure(), absl::nullopt); + + // For an already classic paired device, we skip right to Account Key writing. + EXPECT_CALL(pairing_procedure_complete_, Run); + RunWriteAccountKeyCallback(); + EXPECT_TRUE(IsAccountKeySavedToFootprints()); + ExpectStepMetrics(kProtocolPairingStepInitial, + {FastPairProtocolPairingSteps::kPairingStarted, + FastPairProtocolPairingSteps::kAlreadyPaired, + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Initial_AlreadyFastPaired) { @@ -589,7 +690,7 @@ ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, FastPairProtocolPairingSteps::kAlreadyPaired, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, @@ -610,7 +711,7 @@ ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, FastPairProtocolPairingSteps::kAlreadyPaired, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, @@ -634,7 +735,7 @@ ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, FastPairProtocolPairingSteps::kAlreadyPaired, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_Subsequent) { @@ -645,10 +746,11 @@ AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); EXPECT_EQ(GetPairFailure(), absl::nullopt); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, ConnectFailure_Initial) { @@ -718,7 +820,7 @@ kWritePasskeyCharacteristicPairFailureMetric, 0); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, ConnectSuccess_Subsequent) { @@ -745,7 +847,7 @@ kWritePasskeyCharacteristicPairFailureMetric, 0); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyFailure_Initial) { @@ -755,8 +857,6 @@ 0); histogram_tester().ExpectTotalCount( kWritePasskeyCharacteristicPairFailureMetric, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -776,11 +876,9 @@ 1); histogram_tester().ExpectTotalCount( kWritePasskeyCharacteristicPairFailureMetric, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -792,8 +890,6 @@ 0); histogram_tester().ExpectTotalCount( kWritePasskeyCharacteristicPairFailureMetric, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -812,11 +908,9 @@ 1); histogram_tester().ExpectTotalCount( kWritePasskeyCharacteristicPairFailureMetric, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -825,8 +919,6 @@ ParseDecryptedPasskeyIncorrectMessageType_Initial_SeekersPasskey) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -843,11 +935,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -857,8 +948,6 @@ ParseDecryptedPasskeyIncorrectMessageType_Initial_KeyBasedPairingRequest) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -875,11 +964,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -889,8 +977,6 @@ ParseDecryptedPasskeyIncorrectMessageType_Initial_KeyBasedPairingResponse) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -907,11 +993,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -919,8 +1004,6 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyNoPasskey) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -936,11 +1019,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyDecryptFailure); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -949,8 +1031,6 @@ ParseDecryptedPasskeyIncorrectMessageType_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -967,11 +1047,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kIncorrectPasskeyResponseType); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse}); } @@ -979,8 +1058,6 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyMismatch_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -996,11 +1073,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyMismatch); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated}); @@ -1009,8 +1085,6 @@ TEST_F(FastPairPairerImplTest, ParseDecryptedPasskeyMismatch_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -1026,11 +1100,10 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPasskeyMismatch); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated}); @@ -1039,8 +1112,6 @@ TEST_F(FastPairPairerImplTest, PairedDeviceLost_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -1060,11 +1131,9 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingDeviceLost); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated, @@ -1074,8 +1143,6 @@ TEST_F(FastPairPairerImplTest, PairedDeviceLost_Subsequent) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -1095,11 +1162,9 @@ NotifyConfirmPasskey(); RunWritePasskeyCallback(kResponseBytes); EXPECT_EQ(GetPairFailure(), PairFailure::kPairingDeviceLost); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kDeviceConnected, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated, @@ -1109,9 +1174,6 @@ TEST_F(FastPairPairerImplTest, PairSuccess_Initial) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -1131,18 +1193,14 @@ EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->NotifyDevicePairedChanged(fake_bluetooth_device_ptr_, true); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 1); ExpectStepMetrics(kProtocolPairingStepInitial, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kPairingComplete, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated, FastPairProtocolPairingSteps::kPasskeyConfirmed, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, BleDeviceLostMidPair) { @@ -1173,9 +1231,6 @@ TEST_F(FastPairPairerImplTest, PairSuccess_Initial_FactoryCreate) { Login(user_manager::UserType::USER_TYPE_REGULAR); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairInitial); @@ -1195,10 +1250,6 @@ EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->NotifyDevicePairedChanged(fake_bluetooth_device_ptr_, true); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 1); } TEST_F(FastPairPairerImplTest, PairSuccess_Subsequent_FlagEnabled) { @@ -1211,10 +1262,6 @@ fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_IN); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -1235,18 +1282,14 @@ EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->NotifyDevicePairedChanged(fake_bluetooth_device_ptr_, true); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 1); ExpectStepMetrics(kProtocolPairingStepSubsequent, {FastPairProtocolPairingSteps::kPairingStarted, - FastPairProtocolPairingSteps::kBondSuccessful, + FastPairProtocolPairingSteps::kPairingComplete, FastPairProtocolPairingSteps::kPasskeyNegotiated, FastPairProtocolPairingSteps::kRecievedPasskeyResponse, FastPairProtocolPairingSteps::kPasskeyValidated, FastPairProtocolPairingSteps::kPasskeyConfirmed, - FastPairProtocolPairingSteps::kPairingComplete}); + FastPairProtocolPairingSteps::kDeviceConnected}); } TEST_F(FastPairPairerImplTest, PairSuccess_Subsequent_FlagDisabled) { @@ -1259,10 +1302,6 @@ fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -1283,10 +1322,6 @@ EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->NotifyDevicePairedChanged(fake_bluetooth_device_ptr_, true); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 1); } TEST_F(FastPairPairerImplTest, PairSuccess_Subsequent_StrictFlagDisabled) { @@ -1298,10 +1333,6 @@ fast_pair_repository_.SetOptInStatus( nearby::fastpair::OptInStatus::STATUS_OPTED_OUT); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 0); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 0); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 0); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, /*protocol=*/Protocol::kFastPairSubsequent); @@ -1322,10 +1353,6 @@ EXPECT_TRUE(IsDevicePaired()); EXPECT_EQ(DeviceFastPairVersion::kHigherThanV1, device_->version().value()); adapter_->NotifyDevicePairedChanged(fake_bluetooth_device_ptr_, true); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptTime, 1); - histogram_tester().ExpectTotalCount(kPasskeyCharacteristicDecryptResult, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyAskTime, 1); - histogram_tester().ExpectTotalCount(kConfirmPasskeyConfirmTime, 1); } TEST_F(FastPairPairerImplTest, WriteAccountKey_Initial_FlagEnabled) { @@ -2405,7 +2432,6 @@ /*success=*/false, 0); } -// There are two pairing flows in which PairFailure::kCreateBondTimeout occurs. // In this test's scenario, |adapter_| knows of |device_|, so the // FastPairPairerImpl object in |fake_fast_pair_handshake_| will attempt and // fail to pair with it directly using FastPairPairerImpl::Pair. @@ -2422,10 +2448,6 @@ EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } -// There are two pairing flows in which PairFailure::kCreateBondTimeout occurs. -// In this test's scenario, |adapter_| doesn't know of |device_|, so the -// FastPairPairerImpl object in |fake_fast_pair_handshake_| will attempt and -// fail to connect with it using FastPairPairerImpl::ConnectDevice. TEST_F(FastPairPairerImplTest, CreateBondTimeout_AdapterDoesNotHaveDeviceAddress) { Login(user_manager::UserType::USER_TYPE_REGULAR); @@ -2444,6 +2466,40 @@ EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } +// PairByDevice refers to the fact that we aren't pairing by address, unlike +// most other tests in this file. +TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_ConnectTimeout_Initial) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + SetConnectTimeoutAfterPair(); + CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); + task_environment()->FastForwardBy(kCreateBondTimeout); + EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); +} + +// PairByDevice refers to the fact that we aren't pairing by address, unlike +// most other tests in this file. +TEST_F(FastPairPairerImplTest, PairByDeviceSuccess_ConnectTimeout_Subsequent) { + Login(user_manager::UserType::USER_TYPE_REGULAR); + + CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, + /*protocol=*/Protocol::kFastPairInitial); + + AddConnectedHandshake(); + fake_fast_pair_handshake_->InvokeCallback(); + SetConnectTimeoutAfterPair(); + CreatePairer(); + fake_bluetooth_device_ptr_->TriggerPairCallback(); + task_environment()->FastForwardBy(kCreateBondTimeout); + EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); +} + TEST_F(FastPairPairerImplTest, RetroactiveNotLoggedToInitial) { Login(user_manager::UserType::USER_TYPE_REGULAR); fast_pair_repository_.SetOptInStatus( @@ -2476,12 +2532,11 @@ 0); } -// There are two paths in the code in which |confirm_passkey_timeout_timer_| can -// be started which must both be tested. In the first test, because |adapter_| -// knows the device address, |OnPairConnected| starts the timer. In the second -// test, because |adapter_| doesn't know the device address, |OnConnectDevice| -// starts the timer. -TEST_F(FastPairPairerImplTest, ConfirmPasskeyTimeout_AdapterHasDeviceAddress) { +// Because we have an overall bonding timer, we still test what happens when +// the `ConfirmPasskey` event times out, and expect the overall timer to +// fire. +TEST_F(FastPairPairerImplTest, + CreateBondTimeout_ConfirmPasskey_AdapterHasDeviceAddress) { Login(user_manager::UserType::USER_TYPE_REGULAR); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, @@ -2489,12 +2544,12 @@ AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); - task_environment()->FastForwardBy(kConfirmPasskeyTimeout); - EXPECT_EQ(GetPairFailure(), PairFailure::kConfirmPasskeyTimeout); + task_environment()->FastForwardBy(kCreateBondTimeout); + EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } TEST_F(FastPairPairerImplTest, - ConfirmPasskeyTimeout_AdapterDoesNotHaveDeviceAddress) { + CreateBondTimeout_ConfirmPasskey_AdapterDoesNotHaveDeviceAddress) { Login(user_manager::UserType::USER_TYPE_REGULAR); CreateMockDevice(DeviceFastPairVersion::kHigherThanV1, @@ -2507,8 +2562,8 @@ AddConnectedHandshake(); fake_fast_pair_handshake_->InvokeCallback(); CreatePairer(); - task_environment()->FastForwardBy(kConfirmPasskeyTimeout); - EXPECT_EQ(GetPairFailure(), PairFailure::kConfirmPasskeyTimeout); + task_environment()->FastForwardBy(kCreateBondTimeout); + EXPECT_EQ(GetPairFailure(), PairFailure::kCreateBondTimeout); } } // namespace quick_pair
diff --git a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc index c94a8553..36bd23f4 100644 --- a/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc +++ b/ash/quick_pair/pairing/pairer_broker_impl_unittest.cc
@@ -825,7 +825,9 @@ /*protocol=*/Protocol::kFastPairInitial); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); @@ -850,7 +852,9 @@ /*protocol=*/Protocol::kFastPairSubsequent); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); @@ -875,7 +879,9 @@ /*protocol=*/Protocol::kFastPairRetroactive); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(); EXPECT_TRUE(pairer_broker_->IsPairing()); @@ -884,7 +890,9 @@ EXPECT_EQ(device_paired_count_, 1); EXPECT_EQ(pair_failure_count_, 0); histogram_tester_.ExpectTotalCount(kHandshakeEffectiveSuccessRate, 1); + task_environment()->FastForwardBy(kRetryHandshakeDelay); histogram_tester_.ExpectTotalCount(kHandshakeAttemptCount, 1); + task_environment()->FastForwardBy(kRetryHandshakeDelay); histogram_tester_.ExpectBucketCount(kHandshakeAttemptCount, 3, 1); fast_pair_pairer_factory_->fake_fast_pair_pairer() @@ -900,7 +908,9 @@ /*protocol=*/Protocol::kFastPairInitial); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); EXPECT_FALSE(pairer_broker_->IsPairing()); @@ -921,7 +931,9 @@ /*protocol=*/Protocol::kFastPairSubsequent); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); EXPECT_FALSE(pairer_broker_->IsPairing()); @@ -942,7 +954,9 @@ /*protocol=*/Protocol::kFastPairRetroactive); pairer_broker_->PairDevice(device_); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); + task_environment()->FastForwardBy(kRetryHandshakeDelay); fake_fast_pair_handshake_->InvokeCallback(PairFailure::kCreateGattConnection); EXPECT_FALSE(pairer_broker_->IsPairing());
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc index 1be1b47..7c6633c 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_impl.cc
@@ -491,6 +491,7 @@ void RetroactivePairingDetectorImpl::RemoveDeviceInformationHelper( const std::string& device_address) { + QP_LOG(INFO) << __func__; potential_retroactive_addresses_.erase(device_address); device_pairing_information_.erase(device_address); @@ -511,15 +512,20 @@ // `CheckPairingInformation` if it has exceeded the allotted time for // detecting the scenario (kDetectRetroactiveScenarioTimeout). We clean up // these devices here. + std::vector<std::string> devices_to_remove; for (auto it = device_pairing_information_.begin(); it != device_pairing_information_.end(); ++it) { if (base::Time::Now() >= it->second.expiry_timestamp) { - QP_LOG(VERBOSE) << __func__ << ": Removing device at " << it->first - << "that has exceeded the time allotted for detecting " - "retroactive scenario."; - RemoveDeviceInformationHelper(it->first); + devices_to_remove.push_back(it->first); } } + + for (std::string device_address : devices_to_remove) { + QP_LOG(VERBOSE) << __func__ << ": Removing device at " << device_address + << "that has exceeded the time allotted for detecting " + "retroactive scenario."; + RemoveDeviceInformationHelper(device_address); + } } void RetroactivePairingDetectorImpl::OnPairFailure(scoped_refptr<Device> device,
diff --git a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc index 70a389e..36c6fde 100644 --- a/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc +++ b/ash/quick_pair/pairing/retroactive_pairing_detector_unittest.cc
@@ -43,12 +43,16 @@ namespace { constexpr base::TimeDelta kRetroactiveDevicePairingTimeout = base::Seconds(60); -constexpr char kTestDeviceAddress[] = "11:12:13:14:15:16"; constexpr char kTestDeviceAddress2[] = "11:12:13:14:15:17"; constexpr char kTestBleDeviceName[] = "Test Device Name"; constexpr char kValidModelId[] = "718c17"; const std::string kUserEmail = "test@test.test"; +// Expect no crash with invalid UTF-8 strings as device address. +constexpr char kTestDeviceAddress[6] = { + static_cast<char>(0xFE), static_cast<char>(0xFE), static_cast<char>(0xFF), + static_cast<char>(0xFF), static_cast<char>(0xFF), static_cast<char>(0xFF)}; + const std::vector<uint8_t> kModelIdBytes = { /*message_group=*/0x03, /*message_code=*/0x01,
diff --git a/ash/session/test_session_controller_client.cc b/ash/session/test_session_controller_client.cc index fcd6674..734055c 100644 --- a/ash/session/test_session_controller_client.cc +++ b/ash/session/test_session_controller_client.cc
@@ -228,6 +228,7 @@ } void TestSessionControllerClient::RequestHideLockScreen() { + ++request_hide_lock_screen_count_; SetSessionState(session_manager::SessionState::ACTIVE); }
diff --git a/ash/session/test_session_controller_client.h b/ash/session/test_session_controller_client.h index c3ea9880..de2e8f84 100644 --- a/ash/session/test_session_controller_client.h +++ b/ash/session/test_session_controller_client.h
@@ -62,6 +62,9 @@ int attempt_restart_chrome_count() const { return attempt_restart_chrome_count_; } + int request_hide_lock_screen_count() const { + return request_hide_lock_screen_count_; + } int request_sign_out_count() const { return request_sign_out_count_; } int request_restart_for_update_count() const { return request_restart_for_update_count_; @@ -168,6 +171,7 @@ SessionInfo session_info_; bool use_lower_case_user_id_ = true; + int request_hide_lock_screen_count_ = 0; int request_sign_out_count_ = 0; int request_restart_for_update_count_ = 0; int attempt_restart_chrome_count_ = 0;
diff --git a/ash/shelf/drag_window_from_shelf_controller.cc b/ash/shelf/drag_window_from_shelf_controller.cc index cc682c1..bbf0034d 100644 --- a/ash/shelf/drag_window_from_shelf_controller.cc +++ b/ash/shelf/drag_window_from_shelf_controller.cc
@@ -167,35 +167,32 @@ // Find the other window that is visible while `window_` is being dragged. // There will only be another window if there is a float window (splitview has // two visible windows but is handled separately). - if (auto* float_controller = Shell::Get()->float_controller()) { - if (auto* floated_window = float_controller->FindFloatedWindowOfDesk( - DesksController::Get()->GetTargetActiveDesk())) { - // If the floated window is the dragged window, then the other window is - // the top most non floated window, if it exists. Otherwise the floated - // window is the active window. - if (floated_window == window_) { - aura::Window* candidate_other_window = - window_util::GetTopNonFloatedWindow(); - if (candidate_other_window && - !WindowState::Get(candidate_other_window)->IsMinimized()) { - other_window_ = candidate_other_window; - } - } else { - other_window_ = floated_window; + if (auto* floated_window = window_util::GetFloatedWindowForActiveDesk()) { + // If the floated window is the dragged window, then the other window is + // the top most non floated window, if it exists. Otherwise the floated + // window is the active window. + if (floated_window == window_) { + aura::Window* candidate_other_window = + window_util::GetTopNonFloatedWindow(); + if (candidate_other_window && + !WindowState::Get(candidate_other_window)->IsMinimized()) { + other_window_ = candidate_other_window; } + } else { + other_window_ = floated_window; + } - // Create a copy of the other window. This will be stacked on top and - // faded out as we drag. The original window will be placed immediately - // into overview mode on a successful drag, or return to its original - // position on a canceled drag. - if (other_window_) { - other_window_->AddObserver(this); - other_window_copy_ = wm::RecreateLayers(other_window_); - other_window_copy_->root()->SetVisible(true); - other_window_copy_->root()->SetOpacity(1.f); - other_window_->layer()->parent()->StackAbove(other_window_copy_->root(), - other_window_->layer()); - } + // Create a copy of the other window. This will be stacked on top and + // faded out as we drag. The original window will be placed immediately + // into overview mode on a successful drag, or return to its original + // position on a canceled drag. + if (other_window_) { + other_window_->AddObserver(this); + other_window_copy_ = wm::RecreateLayers(other_window_); + other_window_copy_->root()->SetVisible(true); + other_window_copy_->root()->SetOpacity(1.f); + other_window_->layer()->parent()->StackAbove(other_window_copy_->root(), + other_window_->layer()); } }
diff --git a/ash/shell.cc b/ash/shell.cc index 3957c09..0b1b58e 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -131,6 +131,7 @@ #include "ash/system/human_presence/snooping_protection_controller.h" #include "ash/system/input_device_settings/input_device_settings_controller_impl.h" #include "ash/system/input_device_settings/input_device_tracker.h" +#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" #include "ash/system/keyboard_brightness/keyboard_backlight_color_controller.h" #include "ash/system/keyboard_brightness/keyboard_brightness_controller.h" #include "ash/system/keyboard_brightness_control_delegate.h" @@ -738,6 +739,7 @@ wm_mode_controller_.reset(); event_rewriter_controller_.reset(); + keyboard_modifier_metrics_recorder_.reset(); input_device_tracker_.reset(); input_device_settings_controller_.reset(); @@ -1240,10 +1242,13 @@ std::make_unique<::wm::WindowModalityController>(this, env); // The `InputDeviceSettingsController` is a dependency of the - // `EventRewriterController` so it must be initialized first. + // `EventRewriterController`, `InputDeviceTracker` and + // `KeyboardModifierMetricsRecorder` so it must be initialized first. input_device_settings_controller_ = std::make_unique<InputDeviceSettingsControllerImpl>(); input_device_tracker_ = std::make_unique<InputDeviceTracker>(); + keyboard_modifier_metrics_recorder_ = + std::make_unique<KeyboardModifierMetricsRecorder>(); event_rewriter_controller_ = std::make_unique<EventRewriterControllerImpl>(); env_filter_ = std::make_unique<::wm::CompoundEventFilter>();
diff --git a/ash/shell.h b/ash/shell.h index aafc581..51fe948 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -18,6 +18,7 @@ #include "ash/public/cpp/system_sounds_delegate.h" #include "ash/system/input_device_settings/input_device_settings_controller_impl.h" #include "ash/system/input_device_settings/input_device_tracker.h" +#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" #include "ash/wm/system_modal_container_event_filter_delegate.h" #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" @@ -537,6 +538,9 @@ KeyboardControllerImpl* keyboard_controller() { return keyboard_controller_.get(); } + KeyboardModifierMetricsRecorder* keyboard_modifier_metrics_recorder() { + return keyboard_modifier_metrics_recorder_.get(); + } LaserPointerController* laser_pointer_controller() { return laser_pointer_controller_.get(); } @@ -860,7 +864,8 @@ input_device_settings_controller_; std::unique_ptr<InputDeviceTracker> input_device_tracker_; - + std::unique_ptr<KeyboardModifierMetricsRecorder> + keyboard_modifier_metrics_recorder_; std::unique_ptr<UserMetricsRecorder> user_metrics_recorder_; std::unique_ptr<WindowPositioner> window_positioner_;
diff --git a/ash/system/caps_lock_notification_controller.cc b/ash/system/caps_lock_notification_controller.cc index 34b4b3cf4..2adfa26 100644 --- a/ash/system/caps_lock_notification_controller.cc +++ b/ash/system/caps_lock_notification_controller.cc
@@ -96,19 +96,6 @@ static_cast<int>(ui::chromeos::ModifierKey::kCapsLockKey); } -// static -void CapsLockNotificationController::RegisterProfilePrefs( - PrefRegistrySimple* registry, - bool for_test) { - if (for_test) { - // There is no remote pref service, so pretend that ash owns the pref. - registry->RegisterIntegerPref( - prefs::kLanguageRemapSearchKeyTo, - static_cast<int>(ui::chromeos::ModifierKey::kSearchKey)); - return; - } -} - void CapsLockNotificationController::OnCapsLockChanged(bool enabled) { // Send an a11y alert. Shell::Get()->accessibility_controller()->TriggerAccessibilityAlert(
diff --git a/ash/system/caps_lock_notification_controller.h b/ash/system/caps_lock_notification_controller.h index 615a13f..caa9924f 100644 --- a/ash/system/caps_lock_notification_controller.h +++ b/ash/system/caps_lock_notification_controller.h
@@ -26,9 +26,6 @@ static bool IsSearchKeyMappedToCapsLock(); - // See Shell::RegisterProfilePrefs(). - static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test); - // ImeControllerImpl::Observer: void OnCapsLockChanged(bool enabled) override; void OnKeyboardLayoutNameChanged(const std::string&) override {}
diff --git a/ash/system/human_presence/snooping_protection_controller_unittest.cc b/ash/system/human_presence/snooping_protection_controller_unittest.cc index a0069ee..7e44c10 100644 --- a/ash/system/human_presence/snooping_protection_controller_unittest.cc +++ b/ash/system/human_presence/snooping_protection_controller_unittest.cc
@@ -166,7 +166,9 @@ // Test that daemon signals are only enabled when session and pref state means // they will be used. -TEST_F(SnoopingProtectionControllerTestAbsent, ReconfigureOnPrefs) { +// +// TODO(https://crbug.com/1410425): Flaky test. +TEST_F(SnoopingProtectionControllerTestAbsent, DISABLED_ReconfigureOnPrefs) { // When the service becomes available for the first time, one disable is // performed in case the last session ended in a crash without de-configuring // the daemon. @@ -201,7 +203,9 @@ // Test that daemon signals are correctly enabled/disabled when the daemon // starts and stops. -TEST_F(SnoopingProtectionControllerTestAbsent, ReconfigureOnRestarts) { +// +// TODO(https://crbug.com/1410425): Flaky test. +TEST_F(SnoopingProtectionControllerTestAbsent, DISABLED_ReconfigureOnRestarts) { SimulateLogin(); SetEnabledPref(true);
diff --git a/ash/system/input_device_settings/OWNERS b/ash/system/input_device_settings/OWNERS index 1bef084..c3375bb 100644 --- a/ash/system/input_device_settings/OWNERS +++ b/ash/system/input_device_settings/OWNERS
@@ -1 +1,3 @@ +dpad@google.com +michaelcheco@google.com zentaro@chromium.org
diff --git a/ash/system/input_device_settings/input_device_pref_manager_impl.cc b/ash/system/input_device_settings/input_device_pref_manager_impl.cc index f2221638..d19769764 100644 --- a/ash/system/input_device_settings/input_device_pref_manager_impl.cc +++ b/ash/system/input_device_settings/input_device_pref_manager_impl.cc
@@ -6,6 +6,7 @@ #include <cstdint> +#include "ash/constants/ash_features.h" #include "ash/public/mojom/input_device_settings.mojom.h" #include "base/notreached.h" #include "base/strings/strcat.h" @@ -39,6 +40,9 @@ // connected. void InputDevicePrefManagerImpl::InitializeKeyboardSettings( mojom::Keyboard* keyboard) { + if (!features::IsInputDeviceSettingsSplitEnabled()) { + return; + } NOTIMPLEMENTED(); }
diff --git a/ash/system/input_device_settings/input_device_settings_utils.cc b/ash/system/input_device_settings/input_device_settings_utils.cc new file mode 100644 index 0000000..5e17c2a --- /dev/null +++ b/ash/system/input_device_settings/input_device_settings_utils.cc
@@ -0,0 +1,16 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/input_device_settings/input_device_settings_utils.h" + +#include "ash/public/mojom/input_device_settings.mojom.h" + +namespace ash { + +bool IsValidModifier(int val) { + return val >= static_cast<int>(mojom::ModifierKey::kMinValue) && + val <= static_cast<int>(mojom::ModifierKey::kMaxValue); +} + +} // namespace ash
diff --git a/ash/system/input_device_settings/input_device_settings_utils.h b/ash/system/input_device_settings/input_device_settings_utils.h new file mode 100644 index 0000000..de64c411 --- /dev/null +++ b/ash/system/input_device_settings/input_device_settings_utils.h
@@ -0,0 +1,15 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_SETTINGS_UTILS_H_ +#define ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_SETTINGS_UTILS_H_ + +namespace ash { + +// Checks if a given value is within the bounds set by `mojom::ModifierKey`. +bool IsValidModifier(int val); + +} // namespace ash + +#endif // ASH_SYSTEM_INPUT_DEVICE_SETTINGS_INPUT_DEVICE_SETTINGS_UTILS_H_
diff --git a/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.cc b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.cc new file mode 100644 index 0000000..df35f37 --- /dev/null +++ b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.cc
@@ -0,0 +1,220 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" + +#include <cstdint> +#include <memory> + +#include "ash/constants/ash_features.h" +#include "ash/public/mojom/input_device_settings.mojom-shared.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shell.h" +#include "ash/system/input_device_settings/input_device_settings_utils.h" +#include "base/check_op.h" +#include "base/functional/bind.h" +#include "base/functional/callback_forward.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" +#include "base/strings/string_piece_forward.h" +#include "components/prefs/pref_member.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" + +namespace ash { +namespace { +constexpr base::StringPiece kModifierMetricPrefix = + "ChromeOS.Settings.Keyboard.Modifiers."; +constexpr base::StringPiece kModifierMetricIndividualChangedSuffix = + "RemappedTo.Changed"; +constexpr base::StringPiece kModifierMetricIndividualInitSuffix = + "RemappedTo.Started"; +constexpr base::StringPiece kModifierMetricHash = + "ChromeOS.Settings.Keyboard.Modifiers.Hash"; + +// The modifier hash is made up of `kNumModifiers` blocks of +// `kModifierHashWidth` bits. Each modifier is assigned a `kModifierHashWidth` +// width block to track its user configured setting. These user configured +// settings are contained within [0, `kMaxModifierValue`] and are assigned in +// /ash/public/input_device_settings.mojom in the `mojom::ModifierKey` struct. +// Indices are assigned to each modifier based on the order of the table +// `KeyboardModifierMetricsRecorder::kKeyboardModifierPrefs`. + +// To decode, break up the hash into `kModifierHashWidth` bit integers. +// For example, if `kModifierHashWidth` is 3, use the following bit ranges to +// extract the value of the remapped modifier: + +// | Index in kKeyboardModifierPrefs | Bit Range | +// | 0 | [0, 2] | +// | 1 | [3, 5] | +// | 2 | [6, 8] | +// | 3 | [9, 11] | +// | 4 | [12, 14] | +// | 5 | [15, 17] | +// | 6 | [18, 20] | +// | 7 | [21, 23] | +// | 8 | [24, 26] | +// | 9 | [27, 29] | + +constexpr int kModifierHashWidth = 3; +constexpr int kMaxModifierValue = (1 << kModifierHashWidth) - 1; +constexpr int kNumModifiers = + std::size(KeyboardModifierMetricsRecorder::kKeyboardModifierPrefs); + +// Verify that the number of modifiers we are trying to hash together into a +// 32-bit int will fit without any overflow or UB. +// Modifier hash is limited to 32 bits as metrics can only handle 32 bit ints. +static_assert((sizeof(int32_t) * 8) >= (kModifierHashWidth * kNumModifiers)); +static_assert(static_cast<int>(mojom::ModifierKey::kMaxValue) <= + kMaxModifierValue); + +constexpr mojom::ModifierKey GetDefaultModifier(size_t index) { + return KeyboardModifierMetricsRecorder::kKeyboardModifierPrefs[index] + .default_modifier_key; +} + +// Precomputes the value of the modifier hash when all prefs are configured to +// their default value. +constexpr int32_t PrecalculateDefaultModifierHash() { + uint32_t hash = 0; + for (ssize_t i = kNumModifiers - 1u; i >= 0; i--) { + hash <<= kModifierHashWidth; + hash += static_cast<int>(GetDefaultModifier(i)); + } + return static_cast<uint32_t>(hash); +} +constexpr int32_t kDefaultModifierHash = PrecalculateDefaultModifierHash(); +} // namespace + +KeyboardModifierMetricsRecorder::KeyboardModifierMetricsRecorder() { + Shell::Get()->session_controller()->AddObserver(this); +} + +KeyboardModifierMetricsRecorder::~KeyboardModifierMetricsRecorder() { + Shell::Get()->session_controller()->RemoveObserver(this); +} + +// static +void KeyboardModifierMetricsRecorder::RegisterProfilePrefs( + PrefRegistrySimple* registry, + bool for_test) { + if (for_test) { + for (const auto& modifier_pref : kKeyboardModifierPrefs) { + registry->RegisterIntegerPref( + modifier_pref.pref_name, + static_cast<int>(modifier_pref.default_modifier_key)); + } + } +} + +void KeyboardModifierMetricsRecorder::OnActiveUserPrefServiceChanged( + PrefService* pref_service) { + // Once per device settings launches, this method of publishing metrics will + // no longer work. + if (!features::IsInputDeviceSettingsSplitEnabled()) { + // Initialize all pref members with the updated `pref_service`. Callback for + // each pref member is + // `KeyboardModifierMetricsRecorder::OnModifierRemappingChanged` where the + // index is bound into the callback so it is known which modifier the + // callback applies to. + ResetPrefMembers(); + for (size_t index = 0; index < std::size(kKeyboardModifierPrefs); index++) { + pref_members_[index]->Init( + kKeyboardModifierPrefs[index].pref_name, pref_service, + base::BindRepeating( + &KeyboardModifierMetricsRecorder::OnModifierRemappingChanged, + base::Unretained(this), index)); + } + + // Track the account ids that have already had a metric recorded so it is + // only emitted once. + const auto account_id = + Shell::Get()->session_controller()->GetActiveAccountId(); + if (base::Contains(recorded_accounts_, account_id)) { + return; + } + recorded_accounts_.insert(account_id); + + // Record the metric for each pref member. + for (size_t index = 0; index < pref_members_.size(); index++) { + const auto& pref_member = pref_members_[index]; + DCHECK(pref_member); + + const int value = pref_member->GetValue(); + DCHECK(IsValidModifier(value)); + RecordModifierRemappingInit(index, + static_cast<mojom::ModifierKey>(value)); + } + RecordModifierRemappingHash(); + } +} + +void KeyboardModifierMetricsRecorder::OnModifierRemappingChanged( + size_t index, + const std::string& pref_name) { + DCHECK_LT(index, pref_members_.size()); + IntegerPrefMember* pref_member = pref_members_[index].get(); + DCHECK(pref_member); + DCHECK_EQ(pref_member->GetPrefName(), pref_name); + + int value = pref_member->GetValue(); + DCHECK(IsValidModifier(value)); + RecordModifierRemappingChanged(index, static_cast<mojom::ModifierKey>(value)); +} + +void KeyboardModifierMetricsRecorder::RecordModifierRemappingChanged( + size_t index, + mojom::ModifierKey modifier_key) { + const std::string changed_metric_name = base::StrCat( + {kModifierMetricPrefix, kKeyboardModifierPrefs[index].key_name, + kModifierMetricIndividualChangedSuffix}); + base::UmaHistogramEnumeration(changed_metric_name, modifier_key); +} + +void KeyboardModifierMetricsRecorder::RecordModifierRemappingInit( + size_t index, + mojom::ModifierKey modifier_key) { + DCHECK_LT(index, std::size(kKeyboardModifierPrefs)); + // Skip publishing the metric if the pref is set to its default value. + if (GetDefaultModifier(index) == modifier_key) { + return; + } + + const std::string changed_metric_name = base::StrCat( + {kModifierMetricPrefix, kKeyboardModifierPrefs[index].key_name, + kModifierMetricIndividualInitSuffix}); + base::UmaHistogramEnumeration(changed_metric_name, modifier_key); +} + +void KeyboardModifierMetricsRecorder::ResetPrefMembers() { + for (auto& pref_member : pref_members_) { + pref_member = std::make_unique<IntegerPrefMember>(); + } +} + +void KeyboardModifierMetricsRecorder::RecordModifierRemappingHash() { + // Compute hash by left-shifting by `kModifierHashWidth` and then inserting + // the modifier value from prefs at into the lowest `kModifierHashWidth` bits. + // Repeat for all prefs in `kKeyboardModifierPrefs`. + uint32_t hash = 0; + for (ssize_t i = pref_members_.size() - 1; i >= 0; i--) { + const int value = pref_members_[i]->GetValue(); + + // Check that shifting and adding value will not overflow `hash`. + DCHECK(value <= kMaxModifierValue && value >= 0); + DCHECK(hash < (1u << ((sizeof(uint32_t) * 8u) - kModifierHashWidth))); + + hash <<= kModifierHashWidth; + hash += value; + } + + // If the computed hash matches the hash when settings are in a default state, + // the metric should not be published. + if (hash != kDefaultModifierHash) { + base::UmaHistogramSparse(std::string(kModifierMetricHash), + static_cast<int>(hash)); + } +} + +} // namespace ash
diff --git a/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h new file mode 100644 index 0000000..f73dc1bf --- /dev/null +++ b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h
@@ -0,0 +1,85 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_INPUT_DEVICE_SETTINGS_KEYBOARD_MODIFIER_METRICS_RECORDER_H_ +#define ASH_SYSTEM_INPUT_DEVICE_SETTINGS_KEYBOARD_MODIFIER_METRICS_RECORDER_H_ + +#include <array> +#include <memory> + +#include "ash/ash_export.h" +#include "ash/public/cpp/session/session_observer.h" +#include "ash/public/mojom/input_device_settings.mojom-shared.h" +#include "components/account_id/account_id.h" +#include "components/prefs/pref_member.h" +#include "ui/chromeos/events/pref_names.h" + +class PrefService; +class PrefRegistrySimple; + +namespace ash { + +// Records metrics for whenever keyboard modifier settings change and when a +// user session is first initialized. +class ASH_EXPORT KeyboardModifierMetricsRecorder : public SessionObserver { + public: + // Do not change ordering of this list as the ordering is used to compute + // modifier hash in `RecordModifierRemappingHash()`. + static constexpr struct { + const char* key_name; + const char* pref_name; + mojom::ModifierKey default_modifier_key; + } kKeyboardModifierPrefs[] = { + {"Alt", ::prefs::kLanguageRemapAltKeyTo, mojom::ModifierKey::kAlt}, + {"Control", ::prefs::kLanguageRemapControlKeyTo, + mojom::ModifierKey::kControl}, + {"Escape", ::prefs::kLanguageRemapEscapeKeyTo, + mojom::ModifierKey::kEscape}, + {"Backspace", ::prefs::kLanguageRemapBackspaceKeyTo, + mojom::ModifierKey::kBackspace}, + {"Assistant", ::prefs::kLanguageRemapAssistantKeyTo, + mojom::ModifierKey::kAssistant}, + {"CapsLock", ::prefs::kLanguageRemapCapsLockKeyTo, + mojom::ModifierKey::kCapsLock}, + {"ExternalMeta", ::prefs::kLanguageRemapExternalMetaKeyTo, + mojom::ModifierKey::kMeta}, + {"Search", ::prefs::kLanguageRemapSearchKeyTo, mojom::ModifierKey::kMeta}, + {"ExternalCommand", ::prefs::kLanguageRemapExternalCommandKeyTo, + mojom::ModifierKey::kControl}, + }; + + KeyboardModifierMetricsRecorder(); + KeyboardModifierMetricsRecorder(const KeyboardModifierMetricsRecorder&) = + delete; + KeyboardModifierMetricsRecorder& operator=( + const KeyboardModifierMetricsRecorder&) = delete; + ~KeyboardModifierMetricsRecorder() override; + + static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test); + + void RecordModifierRemappingHash(); + + // SessionObserver: + void OnActiveUserPrefServiceChanged(PrefService* pref_service) override; + + private: + void OnModifierRemappingChanged(size_t index, const std::string& pref_name); + void ResetPrefMembers(); + + void RecordModifierRemappingChanged(size_t index, + mojom::ModifierKey modifier_key); + void RecordModifierRemappingInit(size_t index, + mojom::ModifierKey modifier_key); + + // TODO(dpad): Remove pref members once transitioned to per device settings. + std::array<std::unique_ptr<IntegerPrefMember>, + std::size(kKeyboardModifierPrefs)> + pref_members_; + + base::flat_set<AccountId> recorded_accounts_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_INPUT_DEVICE_SETTINGS_KEYBOARD_MODIFIER_METRICS_RECORDER_H_
diff --git a/ash/system/input_device_settings/keyboard_modifier_metrics_recorder_unittest.cc b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder_unittest.cc new file mode 100644 index 0000000..b41c541 --- /dev/null +++ b/ash/system/input_device_settings/keyboard_modifier_metrics_recorder_unittest.cc
@@ -0,0 +1,404 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/input_device_settings/keyboard_modifier_metrics_recorder.h" + +#include <memory> + +#include "ash/public/cpp/ash_prefs.h" +#include "ash/public/mojom/input_device_settings.mojom-shared.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_helper.h" +#include "base/containers/flat_map.h" +#include "base/memory/raw_ptr.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" +#include "components/account_id/account_id.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "ui/chromeos/events/pref_names.h" + +namespace ash { + +namespace { +constexpr char kUserEmail1[] = "example1@abc.com"; +constexpr char kUserEmail2[] = "example2@abc.com"; + +// Table containing the list of modifier remapping prefs with their expected +// metric names and their matching default key. Used by the following test +// suites. +struct KeyboardModifierMetricsRecorderTestData { + std::string pref_name; + std::string changed_metric_name; + std::string started_metric_name; + mojom::ModifierKey default_modifier_key; +} kKeyboardModifierMetricTestData[] = { + {prefs::kLanguageRemapAltKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.AltRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.AltRemappedTo.Started", + mojom::ModifierKey::kAlt}, + {prefs::kLanguageRemapControlKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.ControlRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.ControlRemappedTo.Started", + mojom::ModifierKey::kControl}, + {prefs::kLanguageRemapEscapeKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.EscapeRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.EscapeRemappedTo.Started", + mojom::ModifierKey::kEscape}, + {prefs::kLanguageRemapBackspaceKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.BackspaceRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.BackspaceRemappedTo.Started", + mojom::ModifierKey::kBackspace}, + {prefs::kLanguageRemapAssistantKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.AssistantRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.AssistantRemappedTo.Started", + mojom::ModifierKey::kAssistant}, + {prefs::kLanguageRemapCapsLockKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.CapsLockRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.CapsLockRemappedTo.Started", + mojom::ModifierKey::kCapsLock}, + {prefs::kLanguageRemapSearchKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.SearchRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.SearchRemappedTo.Started", + mojom::ModifierKey::kMeta}, + {prefs::kLanguageRemapExternalMetaKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.ExternalMetaRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.ExternalMetaRemappedTo.Started", + mojom::ModifierKey::kMeta}, + {prefs::kLanguageRemapExternalCommandKeyTo, + "ChromeOS.Settings.Keyboard.Modifiers.ExternalCommandRemappedTo.Changed", + "ChromeOS.Settings.Keyboard.Modifiers.ExternalCommandRemappedTo.Started", + mojom::ModifierKey::kControl}, +}; +} // namespace + +class KeyboardModifierMetricsRecorderTest : public AshTestBase { + public: + KeyboardModifierMetricsRecorderTest() = default; + KeyboardModifierMetricsRecorderTest( + const KeyboardModifierMetricsRecorderTest&) = delete; + KeyboardModifierMetricsRecorderTest& operator=( + const KeyboardModifierMetricsRecorderTest&) = delete; + ~KeyboardModifierMetricsRecorderTest() override = default; + + void SetUp() override { + AshTestBase::SetUp(); + ResetHistogramTester(); + recorder_ = Shell::Get()->keyboard_modifier_metrics_recorder(); + } + + void TearDown() override { + histogram_tester_.reset(); + AshTestBase::TearDown(); + } + + void ResetHistogramTester() { + histogram_tester_ = std::make_unique<base::HistogramTester>(); + } + + protected: + raw_ptr<KeyboardModifierMetricsRecorder> recorder_; + std::unique_ptr<base::HistogramTester> histogram_tester_; +}; + +class KeyboardModifierMetricsRecorderPrefChangedTest + : public KeyboardModifierMetricsRecorderTest, + public testing::WithParamInterface< + std::tuple<KeyboardModifierMetricsRecorderTestData, int, int>> { + void SetUp() override { + KeyboardModifierMetricsRecorderTest::SetUp(); + int int_modifier_key_from, int_modifier_key_to; + std::tie(data_, int_modifier_key_from, int_modifier_key_to) = GetParam(); + modifier_key_from_ = static_cast<mojom::ModifierKey>(int_modifier_key_from); + modifier_key_to_ = static_cast<mojom::ModifierKey>(int_modifier_key_to); + + pref_service_ = Shell::Get()->session_controller()->GetActivePrefService(); + pref_service_->SetInteger(data_.pref_name, + static_cast<int>(data_.default_modifier_key)); + ResetHistogramTester(); + } + + protected: + raw_ptr<PrefService> pref_service_; + + KeyboardModifierMetricsRecorderTestData data_; + mojom::ModifierKey modifier_key_from_; + mojom::ModifierKey modifier_key_to_; +}; + +// Instantiates the test case with every combination of the modifiers in +// `kKeyboardModifierMetricTestData` and every combination of both a modifier +// to start with and a modifier to change to. Custom name generator is +// implemented to simplify searching through test results for failed cases. +INSTANTIATE_TEST_SUITE_P( + , + KeyboardModifierMetricsRecorderPrefChangedTest, + testing::Combine( + testing::ValuesIn(kKeyboardModifierMetricTestData), + testing::Range(static_cast<int>(mojom::ModifierKey::kMinValue), + static_cast<int>(mojom::ModifierKey::kMaxValue) + 1), + testing::Range(static_cast<int>(mojom::ModifierKey::kMinValue), + static_cast<int>(mojom::ModifierKey::kMaxValue) + 1)), + ([](const testing::TestParamInfo< + KeyboardModifierMetricsRecorderPrefChangedTest::ParamType>& info) { + const auto& [data, int_modifier_key_from, int_modifier_key_to] = + info.param; + // Pref name must replace periods with underscores for gtest output. + std::string result; + base::ReplaceChars(data.pref_name, ".", "_", &result); + return base::StringPrintf("%s_%d_%d", result.c_str(), + int_modifier_key_from, int_modifier_key_to); + })); + +TEST_P(KeyboardModifierMetricsRecorderPrefChangedTest, CheckChangedMetric) { + pref_service_->SetInteger(data_.pref_name, + static_cast<int>(modifier_key_from_)); + if (modifier_key_from_ != data_.default_modifier_key) { + histogram_tester_->ExpectUniqueSample(data_.changed_metric_name, + modifier_key_from_, 1); + } else { + histogram_tester_->ExpectUniqueSample(data_.changed_metric_name, + modifier_key_from_, 0); + } + + ResetHistogramTester(); + pref_service_->SetInteger(data_.pref_name, + static_cast<int>(modifier_key_to_)); + if (modifier_key_from_ != modifier_key_to_) { + histogram_tester_->ExpectUniqueSample(data_.changed_metric_name, + modifier_key_to_, 1); + } else { + histogram_tester_->ExpectUniqueSample(data_.changed_metric_name, + modifier_key_to_, 0); + } +} + +class KeyboardModifierMetricsRecorderPrefStartedTest + : public KeyboardModifierMetricsRecorderTest, + public testing::WithParamInterface< + std::tuple<KeyboardModifierMetricsRecorderTestData, int>> { + void SetUp() override { + KeyboardModifierMetricsRecorderTest::SetUp(); + int int_modifier_key; + std::tie(data_, int_modifier_key) = GetParam(); + modifier_key_ = static_cast<mojom::ModifierKey>(int_modifier_key); + ResetHistogramTester(); + } + + protected: + KeyboardModifierMetricsRecorderTestData data_; + mojom::ModifierKey modifier_key_; +}; + +// Instantiates the test case with every combination of the modifiers in +// `kKeyboardModifierMetricTestData` and with every possible remapped value in +// `mojom::ModifierKey`. A custom name generator is implemented to simplify +// searching through test results for failed cases. +INSTANTIATE_TEST_SUITE_P( + , + KeyboardModifierMetricsRecorderPrefStartedTest, + testing::Combine( + testing::ValuesIn(kKeyboardModifierMetricTestData), + testing::Range(static_cast<int>(mojom::ModifierKey::kMinValue), + static_cast<int>(mojom::ModifierKey::kMaxValue) + 1)), + ([](const testing::TestParamInfo< + KeyboardModifierMetricsRecorderPrefStartedTest::ParamType>& info) { + const auto& [data, int_modifier_key] = info.param; + // Pref name must replace periods with underscores for gtest output. + std::string result; + base::ReplaceChars(data.pref_name, ".", "_", &result); + return base::StringPrintf("%s_%d", result.c_str(), int_modifier_key); + })); + +TEST_P(KeyboardModifierMetricsRecorderPrefStartedTest, InitializeTest) { + // Initialize two pref services with the initial value of the metric. + const AccountId account_id1 = AccountId::FromUserEmail(kUserEmail1); + const AccountId account_id2 = AccountId::FromUserEmail(kUserEmail2); + + std::unique_ptr<TestingPrefServiceSimple> pref_service1 = + std::make_unique<TestingPrefServiceSimple>(); + ash::RegisterUserProfilePrefs(pref_service1->registry(), true); + + std::unique_ptr<TestingPrefServiceSimple> pref_service2 = + std::make_unique<TestingPrefServiceSimple>(); + ash::RegisterUserProfilePrefs(pref_service2->registry(), true); + + pref_service1->SetInteger(data_.pref_name, static_cast<int>(modifier_key_)); + pref_service2->SetInteger(data_.pref_name, static_cast<int>(modifier_key_)); + + ash_test_helper()->test_session_controller_client()->SetUserPrefService( + account_id1, std::move(pref_service1)); + ash_test_helper()->test_session_controller_client()->SetUserPrefService( + account_id2, std::move(pref_service2)); + + ResetHistogramTester(); + + // Sign into first account and verify the metric is emitted. + SimulateUserLogin(account_id1); + if (modifier_key_ != data_.default_modifier_key) { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 1); + } else { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 0); + } + + // Sign into second account and verify the metric is emitted. + SimulateUserLogin(account_id2); + if (modifier_key_ != data_.default_modifier_key) { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 2); + } else { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 0); + } + + // Sign back into the first account and verify no more metrics are emitted. + SimulateUserLogin(account_id1); + if (modifier_key_ != data_.default_modifier_key) { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 2); + } else { + histogram_tester_->ExpectUniqueSample(data_.started_metric_name, + static_cast<int>(modifier_key_), 0); + } +} + +// Contains a list of modifier remappings to apply and then the expected hash +// value after a user signs in. If `expected_value` is empty, then no metric is +// expected. +struct KeyboardModifierMetricsRecorderHashTestData { + base::flat_map<std::string, mojom::ModifierKey> modifier_remappings; + absl::optional<int32_t> expected_value; +}; + +class KeyboardModifierMetricsRecorderHashTest + : public KeyboardModifierMetricsRecorderTest, + public testing::WithParamInterface< + KeyboardModifierMetricsRecorderHashTestData> { + void SetUp() override { + KeyboardModifierMetricsRecorderTest::SetUp(); + data_ = GetParam(); + ResetHistogramTester(); + } + + protected: + KeyboardModifierMetricsRecorderHashTestData data_; +}; + +// Contains lists of modifier remappings to apply before signing in the user and +// then the expected computed hash once the user signs in. +INSTANTIATE_TEST_SUITE_P( + , + KeyboardModifierMetricsRecorderHashTest, + testing::ValuesIn(std::vector<KeyboardModifierMetricsRecorderHashTestData>{ + // With only default remappings, no metric is expected. + {{}, absl::nullopt}, + + // All keys remapped to `mojom::ModifierKey::kMeta` should hash to 0. + {{{::prefs::kLanguageRemapAltKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapCapsLockKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapBackspaceKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapEscapeKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapControlKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapAssistantKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapExternalMetaKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapExternalCommandKeyTo, + mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapSearchKeyTo, mojom::ModifierKey::kMeta}}, + 0x0}, + + // All keys remapped to `mojom::ModifierKey::kBackspace` should hash to + // 0x6db6db6. + {{{::prefs::kLanguageRemapAltKeyTo, mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapCapsLockKeyTo, + mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapBackspaceKeyTo, + mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapEscapeKeyTo, mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapControlKeyTo, mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapAssistantKeyTo, + mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapExternalMetaKeyTo, + mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapExternalCommandKeyTo, + mojom::ModifierKey::kBackspace}, + {::prefs::kLanguageRemapSearchKeyTo, mojom::ModifierKey::kBackspace}}, + 0x6db6db6}, + + // Random assortment of keys with a manually computed hash. + {{{::prefs::kLanguageRemapAltKeyTo, mojom::ModifierKey::kControl}, + {::prefs::kLanguageRemapCapsLockKeyTo, mojom::ModifierKey::kAlt}, + {::prefs::kLanguageRemapBackspaceKeyTo, + mojom::ModifierKey::kAssistant}, + {::prefs::kLanguageRemapEscapeKeyTo, mojom::ModifierKey::kVoid}, + {::prefs::kLanguageRemapControlKeyTo, mojom::ModifierKey::kMeta}, + {::prefs::kLanguageRemapAssistantKeyTo, mojom::ModifierKey::kAlt}, + {::prefs::kLanguageRemapExternalMetaKeyTo, + mojom::ModifierKey::kControl}, + {::prefs::kLanguageRemapExternalCommandKeyTo, + mojom::ModifierKey::kCapsLock}, + {::prefs::kLanguageRemapSearchKeyTo, mojom::ModifierKey::kAlt}}, + 0x4452ec1}, + })); + +TEST_P(KeyboardModifierMetricsRecorderHashTest, HashTest) { + // Initialize two pref services with the initial value of the metric. + const AccountId account_id1 = AccountId::FromUserEmail(kUserEmail1); + const AccountId account_id2 = AccountId::FromUserEmail(kUserEmail2); + + std::unique_ptr<TestingPrefServiceSimple> pref_service1 = + std::make_unique<TestingPrefServiceSimple>(); + ash::RegisterUserProfilePrefs(pref_service1->registry(), true); + + std::unique_ptr<TestingPrefServiceSimple> pref_service2 = + std::make_unique<TestingPrefServiceSimple>(); + ash::RegisterUserProfilePrefs(pref_service2->registry(), true); + + for (const auto& [pref, remapping] : data_.modifier_remappings) { + pref_service1->SetInteger(pref, static_cast<int>(remapping)); + pref_service2->SetInteger(pref, static_cast<int>(remapping)); + } + + ash_test_helper()->test_session_controller_client()->SetUserPrefService( + account_id1, std::move(pref_service1)); + ash_test_helper()->test_session_controller_client()->SetUserPrefService( + account_id2, std::move(pref_service2)); + + ResetHistogramTester(); + + // Sign into first account and verify the metric is emitted. + SimulateUserLogin(account_id1); + if (data_.expected_value.has_value()) { + histogram_tester_->ExpectUniqueSample( + "ChromeOS.Settings.Keyboard.Modifiers.Hash", + data_.expected_value.value(), 1); + } else { + histogram_tester_->ExpectTotalCount( + "ChromeOS.Settings.Keyboard.Modifiers.Hash", 0); + } + + // Sign into second account and verify the metric is emitted. + SimulateUserLogin(account_id2); + if (data_.expected_value.has_value()) { + histogram_tester_->ExpectUniqueSample( + "ChromeOS.Settings.Keyboard.Modifiers.Hash", + data_.expected_value.value(), 2); + } else { + histogram_tester_->ExpectTotalCount( + "ChromeOS.Settings.Keyboard.Modifiers.Hash", 0); + } + + ResetHistogramTester(); + + // Sign back into first account and verify the metric is not emitted again. + SimulateUserLogin(account_id1); + histogram_tester_->ExpectTotalCount( + "ChromeOS.Settings.Keyboard.Modifiers.Hash", 0); +} + +} // namespace ash
diff --git a/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.cc b/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.cc index 6a8a058..290eca2a 100644 --- a/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.cc +++ b/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.cc
@@ -7,6 +7,7 @@ #include "ash/public/mojom/input_device_settings.mojom.h" #include "ash/system/input_device_settings/input_device_settings_defaults.h" #include "ash/system/input_device_settings/input_device_settings_pref_names.h" +#include "ash/system/input_device_settings/input_device_settings_utils.h" #include "base/strings/string_number_conversions.h" #include "components/prefs/pref_service.h" @@ -99,11 +100,6 @@ return settings; } -bool KeyboardPrefHandlerImpl::IsValidModifier(int val) { - return val >= static_cast<int>(mojom::ModifierKey::kMinValue) && - val <= static_cast<int>(mojom::ModifierKey::kMaxValue); -} - void KeyboardPrefHandlerImpl::UpdateKeyboardSettings( PrefService* pref_service, const mojom::Keyboard& keyboard) {
diff --git a/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h b/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h index 1993d4d..427d786 100644 --- a/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h +++ b/ash/system/input_device_settings/pref_handlers/keyboard_pref_handler_impl.h
@@ -33,8 +33,6 @@ PrefService* prefs, const mojom::Keyboard& keyboard, const base::Value::Dict& settings_dict); - - bool IsValidModifier(int val); }; } // namespace ash
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc index 8937a67..0a2a768 100644 --- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc +++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller.cc
@@ -135,11 +135,8 @@ // Since |wallpaper_controller_observation_| does not start observering // until after Chrome is initially started, the rgb keyboard needs to be - // initialized to match the wallpaper if the colors have been calculated - // before. - if (wallpaper_controller->GetKMeanColor() != kInvalidWallpaperColor) { - OnWallpaperColorsChanged(); - } + // initialized to match the wallpaper. + OnWallpaperColorsChanged(); } if (Shell::Get()->session_controller()->GetSessionState() == session_manager::SessionState::LOGIN_PRIMARY) { @@ -191,6 +188,12 @@ DVLOG(3) << __func__ << " backlight_color=" << backlight_color; switch (backlight_color) { case personalization_app::mojom::BacklightColor::kWallpaper: { + // If colors have not been calculated yet, do nothing. + const auto* wallpaper_controller = Shell::Get()->wallpaper_controller(); + DCHECK(wallpaper_controller); + if (!wallpaper_controller->calculated_colors().has_value()) { + return; + } SkColor color = ConvertBacklightColorToSkColor(backlight_color); bool valid_color = color != kInvalidWallpaperColor; base::UmaHistogramBoolean(
diff --git a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc index a8e5bf47..6fe3d3c 100644 --- a/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc +++ b/ash/system/keyboard_brightness/keyboard_backlight_color_controller_unittest.cc
@@ -132,8 +132,10 @@ controller_->GetBacklightColor(account_id_1)); // Expect the Wallpaper color to be set to the default as wallpaper color is // not valid in this state. + // Backlight should be set twice. Once on login screen and then again once + // signed in. histogram_tester().ExpectBucketCount( - "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 1); + "Ash.Personalization.KeyboardBacklight.WallpaperColor.Valid", false, 2); EXPECT_EQ(kDefaultColor, displayed_color()); controller_->SetBacklightColor(
diff --git a/ash/system/message_center/ash_notification_drag_controller.cc b/ash/system/message_center/ash_notification_drag_controller.cc new file mode 100644 index 0000000..6daf4ee --- /dev/null +++ b/ash/system/message_center/ash_notification_drag_controller.cc
@@ -0,0 +1,67 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/message_center/ash_notification_drag_controller.h" + +#include "ash/system/message_center/ash_notification_view.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/base/dragdrop/os_exchange_data_provider.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/views/view.h" + +namespace ash { + +AshNotificationDragController::AshNotificationDragController() = default; + +AshNotificationDragController::~AshNotificationDragController() = default; + +void AshNotificationDragController::WriteDragDataForView( + views::View* sender, + const gfx::Point& press_pt, + ui::OSExchangeData* data) { + AshNotificationView* notification_view = + static_cast<AshNotificationView*>(sender); + const absl::optional<gfx::Rect> drag_area = + notification_view->GetDragAreaBounds(); + DCHECK(drag_area); + + const absl::optional<gfx::ImageSkia> drag_image = + notification_view->GetDragImage(); + DCHECK(drag_image); + data->provider().SetDragImage(*drag_image, press_pt - drag_area->origin()); +} + +int AshNotificationDragController::GetDragOperationsForView( + views::View* sender, + const gfx::Point& p) { + const absl::optional<gfx::Rect> drag_area = + static_cast<AshNotificationView*>(sender)->GetDragAreaBounds(); + + // Use `DRAG_COPY` if: + // 1. `sender` is draggable; and + // 2. `drag_area` contains `p`. + if (drag_area && drag_area->Contains(p)) { + return ui::DragDropTypes::DRAG_COPY; + } + + return ui::DragDropTypes::DRAG_NONE; +} + +bool AshNotificationDragController::CanStartDragForView( + views::View* sender, + const gfx::Point& press_pt, + const gfx::Point& p) { + const absl::optional<gfx::Rect> drag_area = + static_cast<AshNotificationView*>(sender)->GetDragAreaBounds(); + + // Enable dragging `notification_view_` if: + // 1. `notification_view_` is draggable; and + // 2. `drag_area` contains the initial press point. + return drag_area && drag_area->Contains(press_pt); +} + +} // namespace ash
diff --git a/ash/system/message_center/ash_notification_drag_controller.h b/ash/system/message_center/ash_notification_drag_controller.h new file mode 100644 index 0000000..bb3458c --- /dev/null +++ b/ash/system/message_center/ash_notification_drag_controller.h
@@ -0,0 +1,47 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_MESSAGE_CENTER_ASH_NOTIFICATION_DRAG_CONTROLLER_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_ASH_NOTIFICATION_DRAG_CONTROLLER_H_ + +#include "ui/views/drag_controller.h" + +namespace gfx { +class Point; +} // namespace gfx + +namespace ui { +class OSExchangeData; +} // namespace ui + +namespace views { +class View; +} // namespace views + +namespace ash { + +// Handles drag on Ash notification views. +class AshNotificationDragController : public views::DragController { + public: + AshNotificationDragController(); + AshNotificationDragController(const AshNotificationDragController&) = delete; + AshNotificationDragController& operator=( + const AshNotificationDragController&) = delete; + ~AshNotificationDragController() override; + + private: + // views::DragController: + void WriteDragDataForView(views::View* sender, + const gfx::Point& press_pt, + ui::OSExchangeData* data) override; + int GetDragOperationsForView(views::View* sender, + const gfx::Point& p) override; + bool CanStartDragForView(views::View* sender, + const gfx::Point& press_pt, + const gfx::Point& p) override; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_MESSAGE_CENTER_ASH_NOTIFICATION_DRAG_CONTROLLER_H_
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc index b28525e..69f2414 100644 --- a/ash/system/message_center/ash_notification_view.cc +++ b/ash/system/message_center/ash_notification_view.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "ash/constants/ash_features.h" #include "ash/public/cpp/metrics_util.h" #include "ash/public/cpp/rounded_image_view.h" #include "ash/public/cpp/style/color_provider.h" @@ -20,9 +21,11 @@ #include "ash/style/icon_button.h" #include "ash/style/pill_button.h" #include "ash/system/message_center/ash_notification_control_button_factory.h" +#include "ash/system/message_center/ash_notification_drag_controller.h" #include "ash/system/message_center/ash_notification_expand_button.h" #include "ash/system/message_center/ash_notification_input_container.h" #include "ash/system/message_center/message_center_constants.h" +#include "ash/system/message_center/message_center_controller.h" #include "ash/system/message_center/message_center_style.h" #include "ash/system/message_center/message_center_utils.h" #include "ash/system/message_center/metrics_utils.h" @@ -38,6 +41,8 @@ #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/compositor/animation_throughput_reporter.h" +#include "ui/compositor/canvas_painter.h" +#include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" @@ -45,9 +50,11 @@ #include "ui/gfx/color_utils.h" #include "ui/gfx/font.h" #include "ui/gfx/geometry/insets.h" +#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rounded_corners_f.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/transform.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/text_constants.h" @@ -71,6 +78,7 @@ #include "ui/views/controls/label.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/textfield/textfield.h" +#include "ui/views/drag_utils.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout_view.h" #include "ui/views/layout/flex_layout.h" @@ -411,6 +419,11 @@ is_grouped_parent_view_(notification.group_parent()), is_grouped_child_view_(notification.group_child()), shown_in_popup_(shown_in_popup) { + if (features::IsNotificationImageDragEnabled()) { + set_drag_controller( + Shell::Get()->message_center_controller()->drag_controller()); + } + message_center_observer_.Observe(message_center::MessageCenter::Get()); // TODO(crbug/1232197): fix views and layout to match spec. // Instantiate view instances and define layout and view hierarchy. @@ -790,6 +803,51 @@ PreferredSizeChanged(); } +absl::optional<gfx::Rect> AshNotificationView::GetDragAreaBounds() const { + DCHECK(features::IsNotificationImageDragEnabled()); + if (!IsDraggable()) { + return absl::nullopt; + } + + const views::View* large_image_view = + GetViewByID(message_center::NotificationViewBase::kLargeImageView); + gfx::RectF larget_image_bounds(large_image_view->GetLocalBounds()); + views::View::ConvertRectToTarget(large_image_view, /*target=*/this, + &larget_image_bounds); + return gfx::ToEnclosedRect(larget_image_bounds); +} + +absl::optional<gfx::ImageSkia> AshNotificationView::GetDragImage() { + DCHECK(features::IsNotificationImageDragEnabled()); + if (!IsDraggable()) { + return absl::nullopt; + } + + // Assume that an Ash notification has at most one large image view. + views::View* large_image_view = + GetViewByID(message_center::NotificationViewBase::kLargeImageView); + + // Paint `large_image_view` on a bitmap. + const gfx::Size& image_view_size = large_image_view->size(); + const views::Widget* widget = GetWidget(); + const float scale = views::ScaleFactorForDragFromWidget(widget); + SkBitmap bitmap; + large_image_view->Paint(views::PaintInfo::CreateRootPaintInfo( + ui::CanvasPainter(&bitmap, image_view_size, scale, + /*clear_color=*/SK_ColorTRANSPARENT, + widget->GetCompositor()->is_pixel_canvas()) + .context(), + image_view_size)); + + return gfx::ImageSkia::CreateFromBitmap(bitmap, scale); +} + +bool AshNotificationView::IsDraggable() const { + // A notification view is draggable only when it contains a large image. + DCHECK(features::IsNotificationImageDragEnabled()); + return GetViewByID(message_center::NotificationViewBase::kLargeImageView); +} + base::TimeDelta AshNotificationView::GetBoundsAnimationDuration( const message_center::Notification& notification) const { // This is called after the parent gets notified of
diff --git a/ash/system/message_center/ash_notification_view.h b/ash/system/message_center/ash_notification_view.h index 3d0116b..10b7cfb5 100644 --- a/ash/system/message_center/ash_notification_view.h +++ b/ash/system/message_center/ash_notification_view.h
@@ -70,6 +70,20 @@ // Called when a child notificaiton's preferred size changes. void GroupedNotificationsPreferredSizeChanged(); + // Drag related functions ---------------------------------------------------- + + // Returns the bounds of the area where the drag can be initiated. The + // returned bounds are in `AshNotificationView` local coordinates. Returns + // `absl::nullopt` if the notification view is not draggable. + absl::optional<gfx::Rect> GetDragAreaBounds() const; + + // Returns the drag image shown when the ash notification is under drag. + // Returns `absl::nullopt` if the notification view is not draggable. + absl::optional<gfx::ImageSkia> GetDragImage(); + + // Returns true if the notification view is draggable. + bool IsDraggable() const; + // message_center::MessageView: void AddGroupNotification( const message_center::Notification& notification) override; @@ -144,7 +158,7 @@ END_VIEW_BUILDER private: - friend class AshNotificationViewTest; + friend class AshNotificationViewTestBase; friend class NotificationGroupingControllerTest; // Customized title row for this notification view with added timestamp in @@ -177,7 +191,7 @@ views::Label* title_view() { return title_view_; } private: - friend class AshNotificationViewTest; + friend class AshNotificationViewTestBase; // Showing notification title. views::Label* const title_view_;
diff --git a/ash/system/message_center/ash_notification_view_unittest.cc b/ash/system/message_center/ash_notification_view_unittest.cc index d25e4602..ff2b79b 100644 --- a/ash/system/message_center/ash_notification_view_unittest.cc +++ b/ash/system/message_center/ash_notification_view_unittest.cc
@@ -7,24 +7,31 @@ #include <string> #include "ash/constants/ash_features.h" +#include "ash/drag_drop/drag_drop_controller.h" +#include "ash/drag_drop/mock_drag_drop_observer.h" #include "ash/public/cpp/rounded_image_view.h" +#include "ash/public/cpp/test/shell_test_api.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/icon_button.h" #include "ash/system/message_center/ash_notification_expand_button.h" #include "ash/system/message_center/ash_notification_input_container.h" #include "ash/system/message_center/message_center_style.h" +#include "ash/system/message_center/message_popup_animation_waiter.h" #include "ash/system/message_center/metrics_utils.h" #include "ash/system/message_center/unified_message_center_bubble.h" +#include "ash/system/notification_center/notification_center_test_api.h" #include "ash/system/notification_center/notification_center_view.h" #include "ash/system/notification_center/notification_list_view.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/test/ash_test_base.h" +#include "base/run_loop.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" -#include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/layer_animation_stopped_waiter.h" #include "ui/compositor/test/test_utils.h" @@ -41,7 +48,6 @@ #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" #include "ui/views/controls/textfield/textfield.h" -#include "ui/views/layout/flex_layout_view.h" #include "ui/views/test/button_test_api.h" using message_center::Notification; @@ -81,29 +87,25 @@ } // namespace -class AshNotificationViewTest : public AshTestBase, public views::ViewObserver { +// A test base class that helps to verify notification view features. +class AshNotificationViewTestBase : public AshTestBase, + public views::ViewObserver { public: - AshNotificationViewTest() - : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { + template <typename... TaskEnvironmentTraits> + explicit AshNotificationViewTestBase(TaskEnvironmentTraits&&... traits) + : AshTestBase(traits...) { scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>(); scoped_feature_list_->InitAndEnableFeature(features::kNotificationsRefresh); } - AshNotificationViewTest(const AshNotificationViewTest&) = delete; - AshNotificationViewTest& operator=(const AshNotificationViewTest&) = delete; - ~AshNotificationViewTest() override = default; + AshNotificationViewTestBase(const AshNotificationViewTestBase&) = delete; + AshNotificationViewTestBase& operator=(const AshNotificationViewTestBase&) = + delete; + ~AshNotificationViewTestBase() override = default; // AshTestBase: void SetUp() override { AshTestBase::SetUp(); delegate_ = new NotificationTestDelegate(); - auto notification = CreateTestNotification(); - notification_view_ = std::make_unique<AshNotificationView>( - *notification, /*is_popup=*/false); - } - - void TearDown() override { - notification_view_.reset(); - AshTestBase::TearDown(); } // Create a test notification that is used in the view. @@ -129,8 +131,9 @@ data, delegate_); notification->set_small_image(CreateTestImage(16, 16)); - if (has_image) + if (has_image) { notification->set_image(CreateTestImage(320, 240)); + } message_center::MessageCenter::Get()->AddNotification( std::make_unique<message_center::Notification>(*notification)); @@ -171,15 +174,9 @@ ->GetMessageViewForNotificationId(std::string(id))); } - void UpdateTimestamp(base::Time timestamp) { - notification_view()->title_row_->UpdateTimestamp(timestamp); - } - - void AdvanceClock(base::TimeDelta time_delta) { - // Note that AdvanceClock() is used here instead of FastForwardBy() to - // prevent long run time during an ash test session. - task_environment()->AdvanceClock(time_delta); - task_environment()->RunUntilIdle(); + void UpdateTimestampForNotification(AshNotificationView* notification_view, + base::Time timestamp) { + notification_view->title_row_->UpdateTimestamp(timestamp); } // Toggle inline settings with a dummy event. @@ -296,31 +293,31 @@ views::View* GetGroupedNotificationsContainer(AshNotificationView* view) { return view->grouped_notifications_container_; } - - AshNotificationView* notification_view() { return notification_view_.get(); } - views::View* content_row() { return notification_view_->content_row(); } - RoundedImageView* app_icon_view() { - return notification_view_->app_icon_view_; + views::View* GetContentRow(AshNotificationView* view) { + return view->content_row(); } - views::View* title_row() { return notification_view_->title_row_; } - views::Label* title_view() { - return notification_view_->title_row_->title_view_; + RoundedImageView* GetAppIconView(AshNotificationView* view) { + return view->app_icon_view_; } - AshNotificationExpandButton* expand_button() { - return notification_view_->expand_button_; + views::View* GetTitleRow(AshNotificationView* view) { + return view->title_row_; } - views::LabelButton* turn_off_notifications_button() { - return notification_view_->turn_off_notifications_button_; + views::Label* GetTitleView(AshNotificationView* view) { + return view->title_row_->title_view_; } - views::LabelButton* inline_settings_cancel_button() { - return notification_view_->inline_settings_cancel_button_; + views::LabelButton* GetTurnOffNotificationsButton(AshNotificationView* view) { + return view->turn_off_notifications_button_; } - IconButton* snooze_button() { return notification_view_->snooze_button_; } + views::LabelButton* GetInlineSettingsCancelButton(AshNotificationView* view) { + return view->inline_settings_cancel_button_; + } + IconButton* GetSnoozeButton(AshNotificationView* view) { + return view->snooze_button_; + } scoped_refptr<NotificationTestDelegate> delegate() { return delegate_; } private: - std::unique_ptr<AshNotificationView> notification_view_; scoped_refptr<NotificationTestDelegate> delegate_; std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; @@ -330,10 +327,44 @@ int current_id_ = 0; }; +// The notification view test class that uses the mock time. +class AshNotificationViewTest : public AshNotificationViewTestBase { + public: + AshNotificationViewTest() + : AshNotificationViewTestBase( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + + // AshNotificationViewTestBase: + void SetUp() override { + AshNotificationViewTestBase::SetUp(); + auto notification = CreateTestNotification(); + notification_view_ = std::make_unique<AshNotificationView>( + *notification, /*is_popup=*/false); + } + + void TearDown() override { + notification_view_.reset(); + AshTestBase::TearDown(); + } + + void AdvanceClock(base::TimeDelta time_delta) { + // Note that AdvanceClock() is used here instead of FastForwardBy() to + // prevent long run time during an ash test session. + task_environment()->AdvanceClock(time_delta); + task_environment()->RunUntilIdle(); + } + + AshNotificationView* notification_view() { return notification_view_.get(); } + + private: + std::unique_ptr<AshNotificationView> notification_view_; +}; + TEST_F(AshNotificationViewTest, UpdateViewsOrderingTest) { - EXPECT_NE(nullptr, title_row()); + EXPECT_NE(nullptr, GetTitleRow(notification_view())); EXPECT_NE(nullptr, GetMessageLabel(notification_view())); - EXPECT_EQ(0u, GetLeftContent(notification_view())->GetIndexOf(title_row())); + EXPECT_EQ(0u, GetLeftContent(notification_view()) + ->GetIndexOf(GetTitleRow(notification_view()))); EXPECT_EQ(1u, GetLeftContent(notification_view()) ->GetIndexOf(GetMessageLabel(notification_view()))); @@ -342,7 +373,7 @@ notification_view()->UpdateWithNotification(*notification); - EXPECT_EQ(nullptr, title_row()); + EXPECT_EQ(nullptr, GetTitleRow(notification_view())); EXPECT_NE(nullptr, GetMessageLabel(notification_view())); EXPECT_EQ(0u, GetLeftContent(notification_view()) ->GetIndexOf(GetMessageLabel(notification_view()))); @@ -351,16 +382,17 @@ notification_view()->UpdateWithNotification(*notification); - EXPECT_NE(nullptr, title_row()); + EXPECT_NE(nullptr, GetTitleRow(notification_view())); EXPECT_NE(nullptr, GetMessageLabel(notification_view())); - EXPECT_EQ(0u, GetLeftContent(notification_view())->GetIndexOf(title_row())); + EXPECT_EQ(0u, GetLeftContent(notification_view()) + ->GetIndexOf(GetTitleRow(notification_view()))); EXPECT_EQ(1u, GetLeftContent(notification_view()) ->GetIndexOf(GetMessageLabel(notification_view()))); } TEST_F(AshNotificationViewTest, CreateOrUpdateTitle) { - EXPECT_NE(nullptr, title_row()); - EXPECT_NE(nullptr, title_view()); + EXPECT_NE(nullptr, GetTitleRow(notification_view())); + EXPECT_NE(nullptr, GetTitleView(notification_view())); EXPECT_NE(nullptr, GetTitleRowDivider(notification_view())); EXPECT_NE(nullptr, GetTimestampInCollapsedView(notification_view())); @@ -370,15 +402,15 @@ notification->set_title(std::u16string()); notification_view()->UpdateWithNotification(*notification); - EXPECT_EQ(nullptr, title_row()); + EXPECT_EQ(nullptr, GetTitleRow(notification_view())); const std::u16string& expected_text = u"title"; notification->set_title(expected_text); notification_view()->UpdateWithNotification(*notification); - EXPECT_NE(nullptr, title_row()); - EXPECT_EQ(expected_text, title_view()->GetText()); + EXPECT_NE(nullptr, GetTitleRow(notification_view())); + EXPECT_EQ(expected_text, GetTitleView(notification_view())->GetText()); } TEST_F(AshNotificationViewTest, UpdatesTimestampOverTime) { @@ -388,7 +420,9 @@ EXPECT_TRUE(GetTimestampInCollapsedView(notification_view())->GetVisible()); - UpdateTimestamp(base::Time::Now() + base::Hours(3) + base::Minutes(30)); + UpdateTimestampForNotification( + notification_view(), + base::Time::Now() + base::Hours(3) + base::Minutes(30)); EXPECT_EQ(l10n_util::GetPluralStringFUTF16( IDS_MESSAGE_NOTIFICATION_DURATION_HOURS_SHORTEST_FUTURE, 3), GetTimestampInCollapsedView(notification_view())->GetText()); @@ -505,14 +539,18 @@ // check this by comparing the color of the app icon with the color of the // generated test image). EXPECT_EQ(color_utils::SkColorToRgbaString(SK_ColorBLUE), - color_utils::SkColorToRgbaString( - app_icon_view()->original_image().bitmap()->getColor(0, 0))); + color_utils::SkColorToRgbaString(GetAppIconView(notification_view()) + ->original_image() + .bitmap() + ->getColor(0, 0))); // This should not be changed after theme changed. notification_view()->OnThemeChanged(); EXPECT_EQ(color_utils::SkColorToRgbaString(SK_ColorBLUE), - color_utils::SkColorToRgbaString( - app_icon_view()->original_image().bitmap()->getColor(0, 0))); + color_utils::SkColorToRgbaString(GetAppIconView(notification_view()) + ->original_image() + .bitmap() + ->getColor(0, 0))); // Reset the notification to be group parent at the end. notification->SetGroupParent(); @@ -581,7 +619,7 @@ // Toggle back. ToggleInlineSettings(notification_view()); - EXPECT_TRUE(content_row()->GetVisible()); + EXPECT_TRUE(GetContentRow(notification_view())->GetVisible()); EXPECT_TRUE(GetExpandButton(notification_view())->GetVisible()); } @@ -620,7 +658,8 @@ EXPECT_TRUE(GetInlineSettingsRow(notification_view())->GetVisible()); // Clicking the turn off button should disable notifications. - views::test::ButtonTestApi test_api(turn_off_notifications_button()); + views::test::ButtonTestApi test_api( + GetTurnOffNotificationsButton(notification_view())); test_api.NotifyClick(ui::test::TestEvent()); EXPECT_TRUE(delegate()->disable_notification_called()); } @@ -633,7 +672,8 @@ EXPECT_TRUE(GetInlineSettingsRow(notification_view())->GetVisible()); // Clicking the cancel button should not disable notifications. - views::test::ButtonTestApi test_api(inline_settings_cancel_button()); + views::test::ButtonTestApi test_api( + GetInlineSettingsCancelButton(notification_view())); test_api.NotifyClick(ui::test::TestEvent()); EXPECT_FALSE(GetInlineSettingsRow(notification_view())->GetVisible()); @@ -645,14 +685,14 @@ notification_view()->UpdateWithNotification(*notification); // Snooze button should be null if notification does not use it. - EXPECT_EQ(snooze_button(), nullptr); + EXPECT_EQ(GetSnoozeButton(notification_view()), nullptr); notification = CreateTestNotification(/*has_image=*/false, /*show_snooze_button=*/true); notification_view()->UpdateWithNotification(*notification); // Snooze button should be visible if notification does use it. - EXPECT_TRUE(snooze_button()->GetVisible()); + EXPECT_TRUE(GetSnoozeButton(notification_view())->GetVisible()); } TEST_F(AshNotificationViewTest, AppIconAndExpandButtonAlignment) { @@ -662,15 +702,15 @@ // Make sure that app icon and expand button is vertically aligned in // collapsed mode. notification_view()->SetExpanded(false); - EXPECT_EQ(app_icon_view()->GetBoundsInScreen().y(), - expand_button()->GetBoundsInScreen().y()); + EXPECT_EQ(GetAppIconView(notification_view())->GetBoundsInScreen().y(), + GetExpandButton(notification_view())->GetBoundsInScreen().y()); // Make sure that app icon, expand button, and also header row is vertically // aligned in expanded mode. notification_view()->SetExpanded(true); - EXPECT_EQ(app_icon_view()->GetBoundsInScreen().y(), - expand_button()->GetBoundsInScreen().y()); - EXPECT_EQ(app_icon_view()->GetBoundsInScreen().y(), + EXPECT_EQ(GetAppIconView(notification_view())->GetBoundsInScreen().y(), + GetExpandButton(notification_view())->GetBoundsInScreen().y()); + EXPECT_EQ(GetAppIconView(notification_view())->GetBoundsInScreen().y(), GetHeaderRow(notification_view())->GetBoundsInScreen().y()); } @@ -1136,4 +1176,101 @@ EXPECT_TRUE(inline_reply->button()->GetEnabled()); } +// The test class that checks the notification drag feature with both mouse drag +// and gesture drag. +class AshNotificationViewDragTest + : public AshNotificationViewTestBase, + public testing::WithParamInterface</*use_gesture=*/bool> { + public: + AshNotificationViewDragTest() { + scoped_feature_list_.InitAndEnableFeature(features::kNotificationImageDrag); + } + + // Drags from the specific location. + void Drag(const gfx::Point& initial_press_point, int drag_step) { + base::RunLoop run_loop; + const bool use_gesture = GetParam(); + ShellTestApi().drag_drop_controller()->SetLoopClosureForTesting( + base::BindLambdaForTesting([&]() { + if (drag_step > 0) { + MoveDragByOneStep(); + --drag_step; + } else if (!drag_step) { + // End drag when having enough drag updates. + if (use_gesture) { + GetEventGenerator()->ReleaseTouch(); + } else { + GetEventGenerator()->ReleaseLeftButton(); + } + } + }), + run_loop.QuitClosure()); + + if (GetParam()) { + // Press touch to trigger notification drag. + GetEventGenerator()->PressTouch(initial_press_point); + } else { + // Press the mouse then move to trigger notification drag. + GetEventGenerator()->MoveMouseTo(initial_press_point); + GetEventGenerator()->PressLeftButton(); + MoveDragByOneStep(); + } + + run_loop.Run(); + } + + private: + // Moves drag by one step. + void MoveDragByOneStep() { + // The move distance for each drag move. + constexpr int kMoveDistancePerStep = 10; + + if (GetParam()) { + GetEventGenerator()->MoveTouchBy(-kMoveDistancePerStep, /*y=*/0); + } else { + GetEventGenerator()->MoveMouseBy(-kMoveDistancePerStep, /*y=*/0); + } + } + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P(All, + AshNotificationViewDragTest, + /*use_gesture=*/testing::Bool()); + +// Verifies dragging an image notification popup. +TEST_P(AshNotificationViewDragTest, DragPopup) { + // Add an image notification and wait until the notification popup shows. + std::unique_ptr<Notification> notification = CreateTestNotification( + /*has_image=*/true); + MessagePopupAnimationWaiter( + GetPrimaryUnifiedSystemTray()->GetMessagePopupCollection()) + .Wait(); + auto* popup_view = static_cast<message_center::MessagePopupView*>( + NotificationCenterTestApi(nullptr).GetPopupViewForId(notification->id())); + DCHECK(popup_view); + auto* notification_view = + static_cast<AshNotificationView*>(popup_view->message_view()); + + MockDragDropObserver drag_drop_observer( + aura::client::GetDragDropClient(Shell::GetPrimaryRootWindow())); + + // Expect that the drag on `notification_view` starts and updates. + constexpr int kMoveStep = 10; + EXPECT_CALL(drag_drop_observer, OnDragStarted); + EXPECT_CALL(drag_drop_observer, OnDragUpdated).Times(kMoveStep); + + // Calculate the center of the drag area in screen coordinates. + const absl::optional<gfx::Rect> drag_area_bounds = + notification_view->GetDragAreaBounds(); + ASSERT_TRUE(drag_area_bounds); + gfx::Point drag_area_origin = drag_area_bounds->origin(); + views::View::ConvertPointToScreen(notification_view, &drag_area_origin); + const gfx::Point drag_area_center = + gfx::Rect(drag_area_origin, drag_area_bounds->size()).CenterPoint(); + + Drag(drag_area_center, kMoveStep); +} + } // namespace ash
diff --git a/ash/system/message_center/message_center_controller.cc b/ash/system/message_center/message_center_controller.cc index f3e50071..e85bcaa3 100644 --- a/ash/system/message_center/message_center_controller.cc +++ b/ash/system/message_center/message_center_controller.cc
@@ -4,6 +4,7 @@ #include "ash/system/message_center/message_center_controller.h" +#include <memory> #include <utility> #include "ash/constants/ash_features.h" @@ -15,6 +16,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/system/message_center/arc_notification_manager_delegate_impl.h" #include "ash/system/message_center/ash_message_center_lock_screen_controller.h" +#include "ash/system/message_center/ash_notification_drag_controller.h" #include "ash/system/message_center/fullscreen_notification_blocker.h" #include "ash/system/message_center/inactive_user_notification_blocker.h" #include "ash/system/message_center/session_state_notification_blocker.h" @@ -114,6 +116,10 @@ // "ChromiumOS"). message_center::MessageCenter::Get()->SetSystemNotificationAppName( l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_SYSTEM_APP_NAME)); + + if (features::IsNotificationImageDragEnabled()) { + drag_controller_ = std::make_unique<AshNotificationDragController>(); + } } MessageCenterController::~MessageCenterController() {
diff --git a/ash/system/message_center/message_center_controller.h b/ash/system/message_center/message_center_controller.h index 74b5fff..bd0bf45e 100644 --- a/ash/system/message_center/message_center_controller.h +++ b/ash/system/message_center/message_center_controller.h
@@ -22,6 +22,7 @@ namespace ash { class ArcNotificationManagerBase; +class AshNotificationDragController; class FullscreenNotificationBlocker; class PhoneHubNotificationController; class InactiveUserNotificationBlocker; @@ -52,6 +53,10 @@ // SessionObserver: void OnActiveUserPrefServiceChanged(PrefService* pref_service) override; + AshNotificationDragController* drag_controller() { + return drag_controller_.get(); + } + InactiveUserNotificationBlocker* inactive_user_notification_blocker_for_testing() { return inactive_user_notification_blocker_.get(); @@ -75,6 +80,9 @@ std::unique_ptr<PhoneHubNotificationController> phone_hub_notification_controller_; + // Exists only if the notification drag feature is enabled. + std::unique_ptr<AshNotificationDragController> drag_controller_; + base::ObserverList<Observer> observers_; };
diff --git a/ash/system/network/network_detailed_network_view_impl.cc b/ash/system/network/network_detailed_network_view_impl.cc index 1f63695..9c7c815 100644 --- a/ash/system/network/network_detailed_network_view_impl.cc +++ b/ash/system/network/network_detailed_network_view_impl.cc
@@ -44,7 +44,6 @@ delegate, NetworkDetailedView::ListType::LIST_TYPE_NETWORK), NetworkDetailedNetworkView(delegate) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); RecordDetailedViewSection(DetailedViewSection::kDetailedSection); }
diff --git a/ash/system/network/network_detailed_view.cc b/ash/system/network/network_detailed_view.cc index d878d3a1..aa73569 100644 --- a/ash/system/network/network_detailed_view.cc +++ b/ash/system/network/network_detailed_view.cc
@@ -37,8 +37,6 @@ login_(Shell::Get()->session_controller()->login_status()), model_(Shell::Get()->system_tray_model()->network_state_model()), delegate_(delegate) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); - CreateTitleRow(list_type_ == ListType::LIST_TYPE_NETWORK ? IDS_ASH_STATUS_TRAY_NETWORK : IDS_ASH_STATUS_TRAY_VPN);
diff --git a/ash/system/network/network_detailed_view_controller.cc b/ash/system/network/network_detailed_view_controller.cc index a0e3727..881c16c 100644 --- a/ash/system/network/network_detailed_view_controller.cc +++ b/ash/system/network/network_detailed_view_controller.cc
@@ -6,7 +6,6 @@ #include <memory> -#include "ash/constants/ash_features.h" #include "ash/public/cpp/bluetooth_config_service.h" #include "ash/public/cpp/system_tray_client.h" #include "ash/session/session_controller_impl.h" @@ -126,8 +125,6 @@ : model_(Shell::Get()->system_tray_model()->network_state_model()), detailed_view_delegate_( std::make_unique<DetailedViewDelegate>(tray_controller)) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); - GetBluetoothConfigService( remote_cros_bluetooth_config_.BindNewPipeAndPassReceiver()); remote_cros_bluetooth_config_->ObserveSystemProperties(
diff --git a/ash/system/network/network_feature_pod_button_legacy.cc b/ash/system/network/network_feature_pod_button_legacy.cc deleted file mode 100644 index e529550..0000000 --- a/ash/system/network/network_feature_pod_button_legacy.cc +++ /dev/null
@@ -1,241 +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 "ash/system/network/network_feature_pod_button_legacy.h" - -#include "ash/shell.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/system/model/system_tray_model.h" -#include "ash/system/network/active_network_icon.h" -#include "ash/system/network/network_icon.h" -#include "ash/system/network/network_icon_animation.h" -#include "ash/system/network/tray_network_state_model.h" -#include "ash/system/tray/system_tray_notifier.h" -#include "base/strings/utf_string_conversions.h" -#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" -#include "components/onc/onc_constants.h" -#include "third_party/cros_system_api/dbus/service_constants.h" -#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" -#include "ui/base/l10n/l10n_util.h" - -using chromeos::network_config::mojom::ActivationStateType; -using chromeos::network_config::mojom::CellularStateProperties; -using chromeos::network_config::mojom::ConnectionStateType; -using chromeos::network_config::mojom::DeviceStateType; -using chromeos::network_config::mojom::NetworkStateProperties; -using chromeos::network_config::mojom::NetworkType; - -namespace ash { - -namespace { - -std::u16string GetSubLabelForConnectedNetwork( - const NetworkStateProperties* network) { - DCHECK(network && - chromeos::network_config::StateIsConnected(network->connection_state)); - - if (!chromeos::network_config::NetworkStateMatchesType( - network, NetworkType::kWireless)) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED); - } - - if (network->type == NetworkType::kCellular) { - CellularStateProperties* cellular = - network->type_state->get_cellular().get(); - if (cellular->network_technology == onc::cellular::kTechnologyCdma1Xrtt) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_ONE_X); - } - if (cellular->network_technology == onc::cellular::kTechnologyGsm) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_GSM); - } - if (cellular->network_technology == onc::cellular::kTechnologyGprs) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_GPRS); - } - if (cellular->network_technology == onc::cellular::kTechnologyEdge) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_EDGE); - } - if (cellular->network_technology == onc::cellular::kTechnologyEvdo || - cellular->network_technology == onc::cellular::kTechnologyUmts) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_THREE_G); - } - if (cellular->network_technology == onc::cellular::kTechnologyHspa) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_HSPA); - } - if (cellular->network_technology == onc::cellular::kTechnologyHspaPlus) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_HSPA_PLUS); - } - if (cellular->network_technology == onc::cellular::kTechnologyLte) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_LTE); - } - if (cellular->network_technology == onc::cellular::kTechnologyLteAdvanced) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CELLULAR_TYPE_LTE_PLUS); - } - - // All connectivity types exposed by Shill should be covered above. However, - // as a fail-safe, return the default "Connected" string here to protect - // against Shill providing an unexpected value. - NOTREACHED(); - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED); - } - - int signal_strength = - chromeos::network_config::GetWirelessSignalStrength(network); - switch (network_icon::GetSignalStrength(signal_strength)) { - case network_icon::SignalStrength::NONE: - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED); - case network_icon::SignalStrength::WEAK: - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_WEAK_SUBLABEL); - case network_icon::SignalStrength::MEDIUM: - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_MEDIUM_SUBLABEL); - case network_icon::SignalStrength::STRONG: - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_SIGNAL_STRONG_SUBLABEL); - } - NOTREACHED(); - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED); -} - -} // namespace - -NetworkFeaturePodButtonLegacy::NetworkFeaturePodButtonLegacy( - FeaturePodControllerBase* controller) - : FeaturePodButton(controller) { - Shell::Get()->system_tray_model()->network_state_model()->AddObserver(this); - ShowDetailedViewArrow(); - Update(); -} - -NetworkFeaturePodButtonLegacy::~NetworkFeaturePodButtonLegacy() { - network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); - Shell::Get()->system_tray_model()->network_state_model()->RemoveObserver( - this); -} - -void NetworkFeaturePodButtonLegacy::NetworkIconChanged() { - Update(); -} - -void NetworkFeaturePodButtonLegacy::ActiveNetworkStateChanged() { - Update(); -} - -void NetworkFeaturePodButtonLegacy::OnThemeChanged() { - FeaturePodButton::OnThemeChanged(); - - // Need to redraw all network icons with new colors. - Shell::Get() - ->system_tray_model() - ->active_network_icon() - ->PurgeNetworkIconCache(); - NetworkIconChanged(); -} - -const char* NetworkFeaturePodButtonLegacy::GetClassName() const { - // The name returned is intentionally missing the "Legacy" suffix to avoid - // updating tests that search for this node, both now and when this class - // is removed and is replaced by a new NetworkFeaturePodButton. - return "NetworkFeaturePodButton"; -} - -void NetworkFeaturePodButtonLegacy::Update() { - TrayNetworkStateModel* model = - Shell::Get()->system_tray_model()->network_state_model(); - const NetworkStateProperties* network = model->default_network(); - - const bool toggled = network || model->GetDeviceState(NetworkType::kWiFi) == - DeviceStateType::kEnabled; - network_icon::IconType icon_type = - toggled ? network_icon::ICON_TYPE_FEATURE_POD_TOGGLED - : network_icon::ICON_TYPE_FEATURE_POD; - bool image_animating = false; - gfx::ImageSkia image = - Shell::Get()->system_tray_model()->active_network_icon()->GetImage( - ActiveNetworkIcon::Type::kSingle, icon_type, &image_animating); - gfx::ImageSkia image_disabled = - Shell::Get()->system_tray_model()->active_network_icon()->GetImage( - ActiveNetworkIcon::Type::kSingle, - network_icon::ICON_TYPE_FEATURE_POD_DISABLED, &image_animating); - - if (image_animating) - network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this); - else - network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); - - icon_button()->SetImage(views::Button::STATE_NORMAL, image); - icon_button()->SetImage(views::Button::STATE_DISABLED, image_disabled); - SetToggled(toggled); - - std::u16string network_name; - if (network) { - network_name = network->type == NetworkType::kEthernet - ? l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET) - : base::UTF8ToUTF16(network->name); - } - // Check for Activating first since activating networks may be connected. - if (network && network->type == NetworkType::kCellular && - network->type_state->get_cellular()->activation_state == - ActivationStateType::kActivating) { - SetLabel(network_name); - SetSubLabel(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING_SUBLABEL)); - } else if (network && chromeos::network_config::StateIsConnected( - network->connection_state)) { - SetLabel(network_name); - SetSubLabel(GetSubLabelForConnectedNetwork(network)); - } else if (network && - network->connection_state == ConnectionStateType::kConnecting) { - SetLabel(network_name); - SetSubLabel(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING_SUBLABEL)); - } else { - SetLabel(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_LABEL)); - SetSubLabel(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_SUBLABEL)); - } - std::u16string tooltip; - Shell::Get() - ->system_tray_model() - ->active_network_icon() - ->GetConnectionStatusStrings(ActiveNetworkIcon::Type::kSingle, - /*a11y_name=*/nullptr, - /*a11y_desc=*/nullptr, &tooltip); - UpdateTooltip(tooltip); -} - -void NetworkFeaturePodButtonLegacy::UpdateTooltip( - const std::u16string& connection_state_message) { - // When the button is enabled, use tooltips to alert the user of the actions - // that will be taken when interacting with the button/toggle. However, if the - // button is disabled, those actions cannot be taken, so simply display the - // state of the connection as a tooltip - if (!GetEnabled()) { - SetIconTooltip(connection_state_message); - SetLabelTooltip(connection_state_message); - return; - } - - SetIconTooltip(l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_TOGGLE_TOOLTIP, connection_state_message)); - SetLabelTooltip(l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS_TOOLTIP, connection_state_message)); -} - -} // namespace ash
diff --git a/ash/system/network/network_feature_pod_button_legacy.h b/ash/system/network/network_feature_pod_button_legacy.h deleted file mode 100644 index 65ef7a9..0000000 --- a/ash/system/network/network_feature_pod_button_legacy.h +++ /dev/null
@@ -1,48 +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 ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_BUTTON_LEGACY_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_BUTTON_LEGACY_H_ - -#include "ash/system/network/network_icon_animation_observer.h" -#include "ash/system/network/tray_network_state_observer.h" -#include "ash/system/unified/feature_pod_button.h" - -namespace ash { - -// Button view class for network feature pod button. It uses network_icon -// animation to implement network connecting animation on feature pod button. -class NetworkFeaturePodButtonLegacy : public FeaturePodButton, - public network_icon::AnimationObserver, - public TrayNetworkStateObserver { - public: - explicit NetworkFeaturePodButtonLegacy(FeaturePodControllerBase* controller); - - NetworkFeaturePodButtonLegacy(const NetworkFeaturePodButtonLegacy&) = delete; - NetworkFeaturePodButtonLegacy& operator=( - const NetworkFeaturePodButtonLegacy&) = delete; - - ~NetworkFeaturePodButtonLegacy() override; - - // Updates the button's icon and tooltip based on the current state of the - // system. - void Update(); - - // network_icon::AnimationObserver: - void NetworkIconChanged() override; - - // TrayNetworkStateObserver: - void ActiveNetworkStateChanged() override; - - // views::Button: - void OnThemeChanged() override; - const char* GetClassName() const override; - - private: - void UpdateTooltip(const std::u16string& connection_state_message); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_BUTTON_LEGACY_H_
diff --git a/ash/system/network/network_feature_pod_controller.cc b/ash/system/network/network_feature_pod_controller.cc index 3e114ab..f4f41eee 100644 --- a/ash/system/network/network_feature_pod_controller.cc +++ b/ash/system/network/network_feature_pod_controller.cc
@@ -158,7 +158,6 @@ NetworkFeaturePodController::NetworkFeaturePodController( UnifiedSystemTrayController* tray_controller) : tray_controller_(tray_controller) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); Shell::Get()->system_tray_model()->network_state_model()->AddObserver(this); }
diff --git a/ash/system/network/network_feature_pod_controller_legacy.cc b/ash/system/network/network_feature_pod_controller_legacy.cc deleted file mode 100644 index 7152e8fe..0000000 --- a/ash/system/network/network_feature_pod_controller_legacy.cc +++ /dev/null
@@ -1,102 +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 "ash/system/network/network_feature_pod_controller_legacy.h" - -#include "ash/constants/ash_features.h" -#include "ash/constants/quick_settings_catalogs.h" -#include "ash/resources/vector_icons/vector_icons.h" -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/system/model/system_tray_model.h" -#include "ash/system/network/network_feature_pod_button_legacy.h" -#include "ash/system/network/tray_network_state_model.h" -#include "ash/system/unified/feature_pod_controller_base.h" -#include "ash/system/unified/quick_settings_metrics_util.h" -#include "ash/system/unified/unified_system_tray_controller.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" -#include "ui/base/l10n/l10n_util.h" - -using chromeos::network_config::mojom::NetworkStateProperties; -using chromeos::network_config::mojom::NetworkType; - -namespace ash { - -namespace { - -// Returns true if the network is actually toggled. -bool SetNetworkEnabled(bool enabled) { - TrayNetworkStateModel* model = - Shell::Get()->system_tray_model()->network_state_model(); - const NetworkStateProperties* network = model->default_network(); - - // For cellular and tether, users are only allowed to disable them from - // feature pod toggle. - if (!enabled && network && - (network->type == NetworkType::kCellular || - network->type == NetworkType::kTether)) { - model->SetNetworkTypeEnabledState(network->type, false); - return true; - } - - if (network && network->type != NetworkType::kWiFi) - return false; - - model->SetNetworkTypeEnabledState(NetworkType::kWiFi, enabled); - return true; -} - -} // namespace - -NetworkFeaturePodControllerLegacy::NetworkFeaturePodControllerLegacy( - UnifiedSystemTrayController* tray_controller) - : tray_controller_(tray_controller) { - DCHECK(!ash::features::IsQuickSettingsNetworkRevampEnabled()); -} - -NetworkFeaturePodControllerLegacy::~NetworkFeaturePodControllerLegacy() = - default; - -FeaturePodButton* NetworkFeaturePodControllerLegacy::CreateButton() { - DCHECK(!button_); - button_ = new NetworkFeaturePodButtonLegacy(this); - UpdateButton(); - TrackVisibilityUMA(); - return button_; -} - -QsFeatureCatalogName NetworkFeaturePodControllerLegacy::GetCatalogName() { - return QsFeatureCatalogName::kNetwork; -} - -void NetworkFeaturePodControllerLegacy::OnIconPressed() { - bool was_enabled = button_->IsToggled(); - bool can_toggle = SetNetworkEnabled(!was_enabled); - if (can_toggle) - TrackToggleUMA(/*target_toggle_state=*/!was_enabled); - - // If network was disabled, show network list as well as enabling network. - // Also, if the network could not be toggled e.g. Ethernet, show network list. - if (!was_enabled || !can_toggle) { - TrackDiveInUMA(); - tray_controller_->ShowNetworkDetailedView(!can_toggle /* force */); - } -} - -void NetworkFeaturePodControllerLegacy::OnLabelPressed() { - TrackDiveInUMA(); - SetNetworkEnabled(true); - tray_controller_->ShowNetworkDetailedView(true /* force */); -} - -void NetworkFeaturePodControllerLegacy::UpdateButton() { - // Network setting is always immutable in lock screen. - SessionControllerImpl* session_controller = - Shell::Get()->session_controller(); - button_->SetEnabled(!session_controller->IsScreenLocked()); - button_->Update(); -} - -} // namespace ash
diff --git a/ash/system/network/network_feature_pod_controller_legacy.h b/ash/system/network/network_feature_pod_controller_legacy.h deleted file mode 100644 index 24535ea5..0000000 --- a/ash/system/network/network_feature_pod_controller_legacy.h +++ /dev/null
@@ -1,45 +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 ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_CONTROLLER_LEGACY_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_CONTROLLER_LEGACY_H_ - -#include "ash/constants/quick_settings_catalogs.h" -#include "ash/system/unified/feature_pod_controller_base.h" - -namespace ash { - -class NetworkFeaturePodButtonLegacy; -class UnifiedSystemTrayController; - -// Controller of network feature pod button. -class NetworkFeaturePodControllerLegacy : public FeaturePodControllerBase { - public: - NetworkFeaturePodControllerLegacy( - UnifiedSystemTrayController* tray_controller); - - NetworkFeaturePodControllerLegacy(const NetworkFeaturePodControllerLegacy&) = - delete; - NetworkFeaturePodControllerLegacy& operator=( - const NetworkFeaturePodControllerLegacy&) = delete; - - ~NetworkFeaturePodControllerLegacy() override; - - // FeaturePodControllerBase: - FeaturePodButton* CreateButton() override; - QsFeatureCatalogName GetCatalogName() override; - void OnIconPressed() override; - void OnLabelPressed() override; - - private: - void UpdateButton(); - - // Unowned. - UnifiedSystemTrayController* tray_controller_; - NetworkFeaturePodButtonLegacy* button_ = nullptr; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_FEATURE_POD_CONTROLLER_LEGACY_H_
diff --git a/ash/system/network/network_info.cc b/ash/system/network/network_info.cc deleted file mode 100644 index 78ffc228..0000000 --- a/ash/system/network/network_info.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/network/network_info.h" - -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" - -namespace ash { - -NetworkInfo::NetworkInfo() : NetworkInfo(std::string()) {} - -NetworkInfo::NetworkInfo(const std::string& guid) - : guid(guid), - connection_state( - chromeos::network_config::mojom::ConnectionStateType::kNotConnected), - type(chromeos::network_config::mojom::NetworkType::kWiFi), - source(chromeos::network_config::mojom::OncSource::kNone), - activation_state( - chromeos::network_config::mojom::ActivationStateType::kUnknown) {} - -NetworkInfo::~NetworkInfo() = default; - -bool NetworkInfo::operator==(const NetworkInfo& other) const { - return guid == other.guid && label == other.label && - tooltip == other.tooltip && image.BackedBySameObjectAs(other.image) && - type == other.type && disable == other.disable && - sim_locked == other.sim_locked && sim_eid == other.sim_eid && - connection_state == other.connection_state && source == other.source && - activation_state == other.activation_state && - battery_percentage == other.battery_percentage; -} - -} // namespace ash
diff --git a/ash/system/network/network_info.h b/ash/system/network/network_info.h deleted file mode 100644 index fb635d4..0000000 --- a/ash/system/network/network_info.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_NETWORK_NETWORK_INFO_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_INFO_H_ - -#include <string> - -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" -#include "chromeos/services/network_config/public/mojom/network_types.mojom-forward.h" -#include "ui/gfx/image/image_skia.h" - -namespace gfx { -class ImageSkia; -} - -namespace ash { - -// Includes information necessary about a network for displaying the appropriate -// UI to the user. -struct NetworkInfo { - NetworkInfo(); - explicit NetworkInfo(const std::string& guid); - ~NetworkInfo(); - - bool operator==(const NetworkInfo& other) const; - bool operator!=(const NetworkInfo& other) const { return !(*this == other); } - - std::string guid; - std::u16string label; - std::u16string tooltip; - gfx::ImageSkia image; - bool disable = false; - bool secured = false; - bool connectable = false; - bool sim_locked = false; - // Only set for eSIM cellular networks. This is used to uniquely identity - // eSIM networks. - std::string sim_eid; - // Initialized in .cc file because full (non-forward) mojom headers are large. - chromeos::network_config::mojom::ConnectionStateType connection_state; - chromeos::network_config::mojom::NetworkType type; - chromeos::network_config::mojom::OncSource source; - // Used by cellular networks, for other network types, activation_status is - // set to a default value of kUnknown. - chromeos::network_config::mojom::ActivationStateType activation_state; - int battery_percentage = 0; - int signal_strength = 0; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_INFO_H_
diff --git a/ash/system/network/network_info_bubble.cc b/ash/system/network/network_info_bubble.cc index 306aa17..ced06b4 100644 --- a/ash/system/network/network_info_bubble.cc +++ b/ash/system/network/network_info_bubble.cc
@@ -58,8 +58,6 @@ views::View* anchor) : views::BubbleDialogDelegateView(anchor, views::BubbleBorder::TOP_RIGHT), delegate_(delegate) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); - SetButtons(ui::DIALOG_BUTTON_NONE); set_margins(gfx::Insets(kBubbleMargin)); SetArrow(views::BubbleBorder::NONE);
diff --git a/ash/system/network/network_list_header_view.cc b/ash/system/network/network_list_header_view.cc index 89c589a7..6af73e8 100644 --- a/ash/system/network/network_list_header_view.cc +++ b/ash/system/network/network_list_header_view.cc
@@ -26,8 +26,6 @@ } // namespace NetworkListHeaderView::NetworkListHeaderView(int label_id) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); - TrayPopupUtils::ConfigureAsStickyHeader(this); SetLayoutManager(std::make_unique<views::FillLayout>()); container_ = TrayPopupUtils::CreateSubHeaderRowView(/*start_visible=*/true);
diff --git a/ash/system/network/network_list_item_view.cc b/ash/system/network/network_list_item_view.cc index 46cc303..997185a 100644 --- a/ash/system/network/network_list_item_view.cc +++ b/ash/system/network/network_list_item_view.cc
@@ -20,9 +20,7 @@ } // namespace NetworkListItemView::NetworkListItemView(ViewClickListener* listener) - : HoverHighlightView(listener) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); -} + : HoverHighlightView(listener) {} NetworkListItemView::~NetworkListItemView() = default;
diff --git a/ash/system/network/network_list_item_view.h b/ash/system/network/network_list_item_view.h index 0073471..2229384f 100644 --- a/ash/system/network/network_list_item_view.h +++ b/ash/system/network/network_list_item_view.h
@@ -6,7 +6,6 @@ #define ASH_SYSTEM_NETWORK_NETWORK_LIST_ITEM_VIEW_H_ #include "ash/ash_export.h" -#include "ash/system/network/network_info.h" #include "ash/system/tray/hover_highlight_view.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/ash/system/network/network_list_mobile_header_view_impl.cc b/ash/system/network/network_list_mobile_header_view_impl.cc index 41237f4b..11a2808 100644 --- a/ash/system/network/network_list_mobile_header_view_impl.cc +++ b/ash/system/network/network_list_mobile_header_view_impl.cc
@@ -17,6 +17,7 @@ #include "ash/system/network/tray_network_state_model.h" #include "ash/system/tray/tray_popup_utils.h" #include "ash/system/tray/tri_view.h" +#include "base/i18n/rtl.h" #include "base/memory/weak_ptr.h" #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
diff --git a/ash/system/network/network_list_network_header_view.h b/ash/system/network/network_list_network_header_view.h index af7d5cfe..96ce610 100644 --- a/ash/system/network/network_list_network_header_view.h +++ b/ash/system/network/network_list_network_header_view.h
@@ -7,9 +7,9 @@ #include "ash/ash_export.h" #include "ash/system/network/network_list_header_view.h" -#include "ash/system/network/network_row_title_view.h" #include "ash/system/tray/tri_view.h" #include "base/memory/weak_ptr.h" +#include "chromeos/ui/vector_icons/vector_icons.h" #include "ui/views/controls/button/toggle_button.h" #include "ui/views/view.h"
diff --git a/ash/system/network/network_list_network_item_view.h b/ash/system/network/network_list_network_item_view.h index dc310217..0e2f388 100644 --- a/ash/system/network/network_list_network_item_view.h +++ b/ash/system/network/network_list_network_item_view.h
@@ -7,7 +7,6 @@ #include "ash/ash_export.h" #include "ash/system/network/network_icon_animation_observer.h" -#include "ash/system/network/network_info.h" #include "ash/system/network/network_list_item_view.h" #include "ash/system/tray/hover_highlight_view.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
diff --git a/ash/system/network/network_list_network_item_view_unittest.cc b/ash/system/network/network_list_network_item_view_unittest.cc index abc755c3..2d3257d 100644 --- a/ash/system/network/network_list_network_item_view_unittest.cc +++ b/ash/system/network/network_list_network_item_view_unittest.cc
@@ -14,7 +14,6 @@ #include "ash/style/ash_color_provider.h" #include "ash/system/network/fake_network_detailed_network_view.h" #include "ash/system/network/network_icon.h" -#include "ash/system/network/network_info.h" #include "ash/test/ash_test_base.h" #include "base/functional/bind.h" #include "base/i18n/number_formatting.h"
diff --git a/ash/system/network/network_list_view.cc b/ash/system/network/network_list_view.cc deleted file mode 100644 index ee4a2bd..0000000 --- a/ash/system/network/network_list_view.cc +++ /dev/null
@@ -1,850 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/network/network_list_view.h" - -#include <memory> -#include <utility> - -#include "ash/public/cpp/ash_view_ids.h" -#include "ash/resources/vector_icons/vector_icons.h" -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/style/ash_color_provider.h" -#include "ash/style/color_util.h" -#include "ash/system/model/system_tray_model.h" -#include "ash/system/network/network_icon.h" -#include "ash/system/network/network_icon_animation.h" -#include "ash/system/network/network_info.h" -#include "ash/system/network/network_section_header_view.h" -#include "ash/system/network/network_state_list_detailed_view.h" -#include "ash/system/network/network_utils.h" -#include "ash/system/network/tray_network_state_model.h" -#include "ash/system/power/power_status.h" -#include "ash/system/tray/hover_highlight_view.h" -#include "ash/system/tray/tray_info_label.h" -#include "ash/system/tray/tray_popup_utils.h" -#include "ash/system/tray/tray_utils.h" -#include "ash/system/tray/tri_view.h" -#include "base/functional/bind.h" -#include "base/i18n/number_formatting.h" -#include "base/strings/utf_string_conversions.h" -#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" -#include "components/device_event_log/device_event_log.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/views/accessibility/view_accessibility.h" -#include "ui/views/background.h" -#include "ui/views/border.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/controls/scroll_view.h" -#include "ui/views/controls/separator.h" - -namespace ash { - -namespace { - -using ::chromeos::network_config::IsInhibited; -using ::chromeos::network_config::NetworkTypeMatchesType; -using ::chromeos::network_config::StateIsConnected; -using ::chromeos::network_config::mojom::ActivationStateType; -using ::chromeos::network_config::mojom::ConnectionStateType; -using ::chromeos::network_config::mojom::DeviceStateType; -using ::chromeos::network_config::mojom::FilterType; -using ::chromeos::network_config::mojom::NetworkFilter; -using ::chromeos::network_config::mojom::NetworkStateProperties; -using ::chromeos::network_config::mojom::NetworkStatePropertiesPtr; -using ::chromeos::network_config::mojom::NetworkType; -using ::chromeos::network_config::mojom::OncSource; -using ::chromeos::network_config::mojom::ProxyMode; - -const int kMobileNetworkBatteryIconSize = 20; -const int kPowerStatusPaddingRight = 10; -const double kAlphaValueForInhibitedIconOpacity = 0.3; - -bool IsSecondaryUser() { - SessionControllerImpl* session_controller = - Shell::Get()->session_controller(); - return session_controller->IsActiveUserSessionStarted() && - !session_controller->IsUserPrimary(); -} - -SkColor GetIconColor() { - return AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kIconColorPrimary); -} - -bool IsManagedByPolicy(const NetworkInfo& info) { - return info.source == OncSource::kDevicePolicy || - info.source == OncSource::kUserPolicy; -} - -bool ShouldShowActivateCellularNetwork(const NetworkInfo& info) { - return NetworkTypeMatchesType(info.type, NetworkType::kCellular) && - info.activation_state == ActivationStateType::kNotActivated && - info.sim_eid.empty(); -} - -bool ShouldShowContactCarrier(const NetworkInfo& info) { - return NetworkTypeMatchesType(info.type, NetworkType::kCellular) && - info.activation_state == ActivationStateType::kNotActivated && - !info.sim_eid.empty(); -} - -gfx::ImageSkia GetNetworkImageForNetwork(const NetworkInfo& info) { - gfx::ImageSkia network_image; - if (NetworkTypeMatchesType(info.type, NetworkType::kMobile) && - info.connection_state == ConnectionStateType::kNotConnected) { - // Mobile icons which are not connecting or connected should display a small - // "X" icon superimposed so that it is clear that they are disconnected. - network_image = gfx::ImageSkiaOperations::CreateSuperimposedImage( - info.image, gfx::CreateVectorIcon(kNetworkMobileNotConnectedXIcon, - info.image.height(), GetIconColor())); - } else { - network_image = info.image; - } - - // When the network is disabled, its appearance should be grayed out to - // indicate users that these networks are unavailable. We must change the - // image before we add it to the view, and then alter the label and sub-label - // if they exist after it is added to the view. - if (info.disable) { - network_image = gfx::ImageSkiaOperations::CreateTransparentImage( - network_image, kAlphaValueForInhibitedIconOpacity); - } - return network_image; -} - -bool ShouldShowUnlockCellularNetwork(const NetworkInfo& info) { - return NetworkTypeMatchesType(info.type, NetworkType::kCellular) && - info.sim_locked; -} - -// returns 0 if there is no cellular subtext -int GetCellularNetworkSubText(const NetworkInfo& info) { - if (ShouldShowActivateCellularNetwork(info)) - return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_ACTIVATE; - if (ShouldShowContactCarrier(info)) - return IDS_ASH_STATUS_TRAY_NETWORK_UNAVAILABLE_SIM_NETWORK; - if (!ShouldShowUnlockCellularNetwork(info)) - return 0; - if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_UNLOCK; - return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SIGN_IN_TO_UNLOCK; -} - -// Returns color for cellular network item text label. -SkColor GetCellularNetworkPrimaryTextColor(const NetworkInfo& info) { - return AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary); -} - -// Returns color for cellular network item sub text label. -SkColor GetCellularNetworkSubTextColor(const NetworkInfo& info) { - return AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorWarning); -} - -// Updates the disabled network item's label text colors to grey if the item -// is disabled. -void UpdateDisabledListItemTextColor(HoverHighlightView* view, - const NetworkInfo& info) { - // The network row is disabled if blocked by policy, device is inhibited or - // when SIM is locked and user is not logged in. - if (!info.disable) { - return; - } - - if (view->text_label()) { - SkColor primary_text_color = view->text_label()->GetEnabledColor(); - view->text_label()->SetEnabledColor( - ColorUtil::GetDisabledColor(primary_text_color)); - } - if (view->sub_text_label()) { - SkColor sub_text_color = view->sub_text_label()->GetEnabledColor(); - view->sub_text_label()->SetEnabledColor( - ColorUtil::GetDisabledColor(sub_text_color)); - } -} - -void SetupCellularListItemWithSubtext(HoverHighlightView* view, - const NetworkInfo& info, - int cellular_subtext_message_id) { - if (view->text_label()) { - view->text_label()->SetEnabledColor( - GetCellularNetworkPrimaryTextColor(info)); - } - view->SetSubText(l10n_util::GetStringUTF16(cellular_subtext_message_id)); - view->sub_text_label()->SetEnabledColor(GetCellularNetworkSubTextColor(info)); -} - -bool ComputeNetworkDisabledProperty(const NetworkStatePropertiesPtr& network, - const NetworkInfo& info, - ActivationStateType activation_state, - bool inhibited) { - // If user is not logged in and SIM is locked disable the row. - if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted() && - ShouldShowUnlockCellularNetwork(info)) { - return info.sim_locked; - } - // If the device is inhibited or network is blocked by policy, the network - // row should be disabled. - return activation_state == ActivationStateType::kActivating || - network->prohibited_by_policy || inhibited; -} - -} // namespace - -// NetworkListView: - -NetworkListView::NetworkListView(DetailedViewDelegate* delegate, - LoginStatus login) - : NetworkStateListDetailedView(delegate, LIST_TYPE_NETWORK, login) {} - -NetworkListView::~NetworkListView() { - network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); -} - -void NetworkListView::UpdateNetworkList() { - CHECK(scroll_content()); - model()->cros_network_config()->GetNetworkStateList( - NetworkFilter::New(FilterType::kVisible, NetworkType::kAll, - chromeos::network_config::mojom::kNoLimit), - base::BindOnce(&NetworkListView::OnGetNetworkStateList, - weak_ptr_factory_.GetWeakPtr())); -} - -bool NetworkListView::IsNetworkEntry(views::View* view, - std::string* guid) const { - std::map<views::View*, std::string>::const_iterator found = - network_map_.find(view); - if (found == network_map_.end()) - return false; - *guid = found->second; - return true; -} - -const char* NetworkListView::GetClassName() const { - return "NetworkListView"; -} - -void NetworkListView::OnGetNetworkStateList( - std::vector<NetworkStatePropertiesPtr> networks) { - // |network_list_| contains all the info and is going to be cleared and - // recreated. Save them to |last_network_info_map_|. - last_network_info_map_.clear(); - for (auto& info : network_list_) - last_network_info_map_[info->guid] = std::move(info); - - bool animating = false; - network_list_.clear(); - vpn_connected_ = false; - wifi_has_networks_ = false; - mobile_has_networks_ = false; - tether_has_networks_ = false; - for (auto& network : networks) { - ConnectionStateType connection_state = network->connection_state; - if (network->type == NetworkType::kVPN) { - if (StateIsConnected(connection_state)) { - vpn_connected_ = true; - } - continue; - } - - auto info = std::make_unique<NetworkInfo>(network->guid); - bool inhibited = false; - ActivationStateType activation_state = ActivationStateType::kUnknown; - const chromeos::network_config::mojom::DeviceStateProperties* - cellular_device = model()->GetDevice(NetworkType::kCellular); - switch (network->type) { - case NetworkType::kCellular: - mobile_has_networks_ = true; - activation_state = - network->type_state->get_cellular()->activation_state; - info->activation_state = activation_state; - info->sim_locked = network->type_state->get_cellular()->sim_locked; - info->sim_eid = network->type_state->get_cellular()->eid; - - if (cellular_device && IsInhibited(cellular_device)) - inhibited = true; - // If cellular is not enabled, skip cellular networks with no service. - if (model()->GetDeviceState(NetworkType::kCellular) != - DeviceStateType::kEnabled && - activation_state == ActivationStateType::kNoService) { - continue; - } - break; - case NetworkType::kWiFi: - wifi_has_networks_ = true; - info->secured = network->type_state->get_wifi()->security != - chromeos::network_config::mojom::SecurityType::kNone; - break; - case NetworkType::kTether: - mobile_has_networks_ = true; - tether_has_networks_ = true; - info->battery_percentage = - network->type_state->get_tether()->battery_percentage; - break; - default: - break; - } - - info->label = network_icon::GetLabelForNetworkList(network.get()); - // |network_list_| only contains non virtual networks. - info->image = network_icon::GetImageForNonVirtualNetwork( - network.get(), network_icon::ICON_TYPE_LIST, false /* badge_vpn */); - - info->type = network->type; - info->disable = ComputeNetworkDisabledProperty(network, *info, - activation_state, inhibited); - - // If the device state is inhibited, we want to have the cellular network - // rows not connectable. - info->connectable = network->connectable && !inhibited && !info->sim_locked; - - if (network->prohibited_by_policy) { - info->tooltip = - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED); - } - - info->connection_state = connection_state; - - info->signal_strength = - chromeos::network_config::GetWirelessSignalStrength(network.get()); - - info->source = network->source; - - if (!animating && connection_state == ConnectionStateType::kConnecting) - animating = true; - network_list_.push_back(std::move(info)); - } - if (animating) - network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this); - else - network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this); - - UpdateNetworkListInternal(); -} - -void NetworkListView::UpdateNetworkListInternal() { - // Get the updated list entries. - needs_relayout_ = false; - network_map_.clear(); - std::unique_ptr<std::set<std::string>> new_guids = UpdateNetworkListEntries(); - - // Remove old children. - std::set<std::string> remove_guids; - for (const auto& iter : network_guid_map_) { - if (new_guids->find(iter.first) == new_guids->end()) { - remove_guids.insert(iter.first); - network_map_.erase(iter.second); - delete iter.second; - needs_relayout_ = true; - } - } - - for (const auto& remove_iter : remove_guids) - network_guid_map_.erase(remove_iter); - - if (!needs_relayout_) - return; - - views::View* selected_view = nullptr; - for (const auto& iter : network_guid_map_) { - // The within_bounds check is necessary when the network list goes beyond - // the visible area (i.e. scrolling) and the mouse is below the tray pop-up. - // The items not in view in the tray pop-up keep going down and have - // View::GetVisibility() == true but they are masked and not seen by the - // user. When the mouse is below the list where the item would be if the - // list continued downward, IsMouseHovered() is true and this will trigger - // an incorrect programmatic scroll if we don't stop it. The bounds check - // ensures the view is actually visible within the tray pop-up. - bool within_bounds = - this->GetBoundsInScreen().Intersects(iter.second->GetBoundsInScreen()); - if (within_bounds && iter.second->IsMouseHovered()) { - selected_view = iter.second; - break; - } - } - scroll_content()->SizeToPreferredSize(); - scroller()->Layout(); - if (selected_view) - scroll_content()->ScrollRectToVisible(selected_view->bounds()); -} - -std::unique_ptr<std::set<std::string>> -NetworkListView::UpdateNetworkListEntries() { - // Keep an index where the next child should be inserted. - size_t index = 0; - - const NetworkStateProperties* default_network = model()->default_network(); - bool using_proxy = - default_network && default_network->proxy_mode != ProxyMode::kDirect; - // Show a warning that the connection might be monitored if connected to a VPN - // or if the default network has a proxy installed. - if (vpn_connected_ || using_proxy) { - if (!connection_warning_) - connection_warning_ = CreateConnectionWarning(); - PlaceViewAtIndex(connection_warning_, index++); - } - - // First add Ethernet networks. - std::unique_ptr<std::set<std::string>> new_guids = - UpdateNetworkChildren(NetworkType::kEthernet, index); - index += new_guids->size(); - - if (ShouldMobileDataSectionBeShown()) { - if (!mobile_header_view_) { - RecordDetailedViewSection(DetailedViewSection::kMobileSection); - mobile_header_view_ = new MobileSectionHeaderView(); - } - - index = UpdateNetworkSectionHeader( - NetworkType::kMobile, false /* enabled */, index, mobile_header_view_, - &mobile_separator_view_); - - std::unique_ptr<std::set<std::string>> new_cellular_guids = - UpdateNetworkChildren(NetworkType::kMobile, index); - int mobile_status_message = - mobile_header_view_->UpdateToggleAndGetStatusMessage( - mobile_has_networks_, tether_has_networks_); - // |mobile_status_message| may be zero. Passing zero to UpdateInfoLabel - // clears the label. - UpdateInfoLabel(mobile_status_message, index, &mobile_status_message_); - if (mobile_status_message) - ++index; - index += new_cellular_guids->size(); - new_guids->insert(new_cellular_guids->begin(), new_cellular_guids->end()); - } else if (mobile_header_view_) { - scroll_content()->RemoveChildView(mobile_header_view_); - delete mobile_header_view_; - mobile_header_view_ = nullptr; - needs_relayout_ = true; - } - - if (!wifi_header_view_) { - RecordDetailedViewSection(DetailedViewSection::kWifiSection); - wifi_header_view_ = new WifiSectionHeaderView(); - } - - bool wifi_enabled = - model()->GetDeviceState(NetworkType::kWiFi) == DeviceStateType::kEnabled; - index = UpdateNetworkSectionHeader(NetworkType::kWiFi, wifi_enabled, index, - wifi_header_view_, &wifi_separator_view_); - - if (!wifi_enabled) { - UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED, index, - &wifi_status_message_); - return new_guids; - } - - bool should_clear_info_label = true; - if (!wifi_has_networks_) { - UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED, index, - &wifi_status_message_); - ++index; - should_clear_info_label = false; - } - - // Add Wi-Fi networks. - std::unique_ptr<std::set<std::string>> new_wifi_guids = - UpdateNetworkChildren(NetworkType::kWiFi, index); - index += new_wifi_guids->size(); - new_guids->insert(new_wifi_guids->begin(), new_wifi_guids->end()); - - // No networks or other messages (fallback). - if (index == 0) { - UpdateInfoLabel(IDS_ASH_STATUS_TRAY_NO_NETWORKS, index, - &wifi_status_message_); - } else if (should_clear_info_label) { - // Update the label to show nothing. - UpdateInfoLabel(0, index, &wifi_status_message_); - } - - return new_guids; -} - -bool NetworkListView::ShouldMobileDataSectionBeShown() { - // The section should always be shown if Cellular networks are available. - if (model()->GetDeviceState(NetworkType::kCellular) != - DeviceStateType::kUnavailable) { - return true; - } - - DeviceStateType tether_state = model()->GetDeviceState(NetworkType::kTether); - // Hide the section if both Cellular and Tether are UNAVAILABLE. - if (tether_state == DeviceStateType::kUnavailable) - return false; - - // Hide the section if Tether is PROHIBITED. - if (tether_state == DeviceStateType::kProhibited) - return false; - - // Secondary users cannot enable Bluetooth, and Tether is only UNINITIALIZED - // if Bluetooth is disabled. Hide the section in this case. - if (tether_state == DeviceStateType::kUninitialized && IsSecondaryUser()) - return false; - - return true; -} - -void NetworkListView::UpdateViewForNetwork(HoverHighlightView* view, - const NetworkInfo& info) { - view->Reset(); - view->AddIconAndLabel(GetNetworkImageForNetwork(info), info.label); - - int cellular_subtext_message_id = GetCellularNetworkSubText(info); - if (cellular_subtext_message_id) { - SetupCellularListItemWithSubtext(view, info, cellular_subtext_message_id); - } else { - if (StateIsConnected(info.connection_state)) { - SetupConnectedScrollListItem(view); - } else if (info.connection_state == ConnectionStateType::kConnecting) { - SetupConnectingScrollListItem(view); - } - } - UpdateDisabledListItemTextColor(view, info); - view->SetTooltipText(info.tooltip); - - // Add an additional icon to the right of the label for networks - // that require it (e.g. Tether, controlled by extension). - views::View* icon = CreatePowerStatusView(info); - if (icon) { - view->AddRightView(icon, views::CreateEmptyBorder(gfx::Insets::TLBR( - 0, 0, 0, kPowerStatusPaddingRight))); - } else { - icon = CreatePolicyView(info); - if (icon) - view->AddRightView(icon); - } - - view->SetAccessibleName(GenerateAccessibilityLabel(info)); - view->GetViewAccessibility().OverrideDescription( - GenerateAccessibilityDescription(info)); - - needs_relayout_ = true; -} - -std::u16string NetworkListView::GenerateAccessibilityLabel( - const NetworkInfo& info) { - if (CanNetworkConnect(info.connection_state, info.type, info.activation_state, - info.connectable, info.sim_eid)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_CONNECT, info.label); - } - - if (ShouldShowActivateCellularNetwork(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_ACTIVATE, info.label); - } - - if (ShouldShowContactCarrier(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_A11Y_UNAVAILABLE_SIM_NETWORK, info.label); - } - - return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_OPEN, - info.label); -} - -std::u16string NetworkListView::GenerateAccessibilityDescription( - const NetworkInfo& info) { - std::u16string connection_status; - if (StateIsConnected(info.connection_state) || - info.connection_state == ConnectionStateType::kConnecting) { - connection_status = l10n_util::GetStringUTF16( - StateIsConnected(info.connection_state) - ? IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED - : IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING); - } - - switch (info.type) { - case NetworkType::kEthernet: - if (!connection_status.empty()) { - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_ETHERNET_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS, - connection_status); - } - return connection_status; - } - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_ETHERNET_A11Y_DESC_MANAGED); - } - return info.label; - case NetworkType::kWiFi: { - std::u16string security_label = l10n_util::GetStringUTF16( - info.secured ? IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SECURED - : IDS_ASH_STATUS_TRAY_NETWORK_STATUS_UNSECURED); - if (!connection_status.empty()) { - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS, - security_label, connection_status, - base::FormatPercent(info.signal_strength)); - } - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS, - security_label, connection_status, - base::FormatPercent(info.signal_strength)); - } - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED, security_label, - base::FormatPercent(info.signal_strength)); - } - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC, security_label, - base::FormatPercent(info.signal_strength)); - } - case NetworkType::kCellular: - if (ShouldShowActivateCellularNetwork(info)) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_ACTIVATE); - } - if (ShouldShowContactCarrier(info)) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_UNAVAILABLE_SIM_NETWORK); - } - if (info.sim_locked) { - if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) { - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_UNLOCK); - } - return l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SIGN_IN_TO_UNLOCK); - } - if (!connection_status.empty()) { - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS, - connection_status, base::FormatPercent(info.signal_strength)); - } - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS, - connection_status, base::FormatPercent(info.signal_strength)); - } - if (IsManagedByPolicy(info)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_MANAGED, - base::FormatPercent(info.signal_strength)); - } - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC, - base::FormatPercent(info.signal_strength)); - case NetworkType::kTether: - if (!connection_status.empty()) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_TETHER_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS, - connection_status, base::FormatPercent(info.signal_strength), - base::FormatPercent(info.battery_percentage)); - } - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_TETHER_NETWORK_A11Y_DESC, - base::FormatPercent(info.signal_strength), - base::FormatPercent(info.battery_percentage)); - default: - return u""; - } -} - -views::View* NetworkListView::CreatePowerStatusView(const NetworkInfo& info) { - // Mobile can be Cellular or Tether. - if (!NetworkTypeMatchesType(info.type, NetworkType::kMobile)) - return nullptr; - - // Only return a battery icon for Tether network type. - if (info.type != NetworkType::kTether) - return nullptr; - - views::ImageView* icon = new views::ImageView; - const SkColor icon_color = GetIconColor(); - icon->SetPreferredSize(gfx::Size(kMenuIconSize, kMenuIconSize)); - icon->SetFlipCanvasOnPaintForRTLUI(true); - PowerStatus::BatteryImageInfo icon_info; - icon_info.charge_percent = info.battery_percentage; - icon->SetImage(PowerStatus::GetBatteryImage( - icon_info, kMobileNetworkBatteryIconSize, - ColorUtil::GetSecondToneColor(icon_color), icon_color)); - - // Show the numeric battery percentage on hover. - icon->SetTooltipText(base::FormatPercent(info.battery_percentage)); - - return icon; -} - -views::View* NetworkListView::CreatePolicyView(const NetworkInfo& info) { - // Check if the network is managed by policy. - OncSource source = info.source; - if (source != OncSource::kDevicePolicy && source != OncSource::kUserPolicy) - return nullptr; - - views::ImageView* controlled_icon = - TrayPopupUtils::CreateMainImageView(/*use_wide_layout=*/false); - controlled_icon->SetImage( - gfx::CreateVectorIcon(kSystemMenuBusinessIcon, GetIconColor())); - return controlled_icon; -} - -std::unique_ptr<std::set<std::string>> NetworkListView::UpdateNetworkChildren( - NetworkType type, - size_t index) { - std::unique_ptr<std::set<std::string>> new_guids(new std::set<std::string>); - for (const auto& info : network_list_) { - if (!NetworkTypeMatchesType(info->type, type)) - continue; - UpdateNetworkChild(index++, info.get()); - new_guids->insert(info->guid); - } - return new_guids; -} - -void NetworkListView::UpdateNetworkChild(size_t index, - const NetworkInfo* info) { - HoverHighlightView* network_view = nullptr; - NetworkGuidMap::const_iterator found = network_guid_map_.find(info->guid); - - // This value is used to determine whether at least one network of |type| type - // already existed prior to this method. - bool has_reordered_a_network = false; - - if (found == network_guid_map_.end()) { - network_view = new HoverHighlightView(this); - UpdateViewForNetwork(network_view, *info); - } else { - has_reordered_a_network = true; - network_view = found->second; - if (NeedUpdateViewForNetwork(*info)) - UpdateViewForNetwork(network_view, *info); - } - - // Only emit ethernet metric each time we show Ethernet section - // for the first time. We use |has_reordered_a_network| to determine - // if Ethernet networks already exist in network detailed list. - if (NetworkTypeMatchesType(info->type, NetworkType::kEthernet) && - !has_reordered_a_network) { - RecordDetailedViewSection(DetailedViewSection::kEthernetSection); - } - - PlaceViewAtIndex(network_view, index); - network_view->SetEnabled(!info->disable); - network_map_[network_view] = info->guid; - network_guid_map_[info->guid] = network_view; -} - -void NetworkListView::PlaceViewAtIndex(views::View* view, size_t index) { - if (view->parent() != scroll_content()) { - scroll_content()->AddChildViewAt(view, index); - } else if (index > 0 && index < scroll_content()->children().size() && - scroll_content()->children()[index] == view) { - // ReorderChildView() would no-op in this case, but we still want to avoid - // setting |needs_relayout_|. - return; - } else { - scroll_content()->ReorderChildView(view, index); - } - needs_relayout_ = true; -} - -void NetworkListView::UpdateInfoLabel(int message_id, - size_t insertion_index, - TrayInfoLabel** info_label_ptr) { - TrayInfoLabel* info_label = *info_label_ptr; - if (!message_id) { - if (info_label) { - needs_relayout_ = true; - delete info_label; - *info_label_ptr = nullptr; - } - return; - } - if (!info_label) - info_label = new TrayInfoLabel(message_id); - else - info_label->Update(message_id); - - PlaceViewAtIndex(info_label, insertion_index); - *info_label_ptr = info_label; -} - -size_t NetworkListView::UpdateNetworkSectionHeader( - chromeos::network_config::mojom::NetworkType type, - bool enabled, - size_t child_index, - NetworkSectionHeaderView* view, - views::Separator** separator_view) { - // Show or hide a separator above the header. The separator should only be - // visible when the header row is not at the top of the list. - if (child_index > 0) { - if (!*separator_view) - *separator_view = TrayPopupUtils::CreateListSubHeaderSeparator(); - PlaceViewAtIndex(*separator_view, child_index++); - } else { - if (*separator_view) - delete *separator_view; - *separator_view = nullptr; - } - - // Mobile updates its toggle state independently. - if (!NetworkTypeMatchesType(type, NetworkType::kMobile)) - view->SetToggleState(true /* toggle_enabled */, enabled /* is_on */); - PlaceViewAtIndex(view, child_index++); - return child_index; -} - -void NetworkListView::NetworkIconChanged() { - Update(); -} - -bool NetworkListView::NeedUpdateViewForNetwork(const NetworkInfo& info) const { - NetworkInfoMap::const_iterator found = last_network_info_map_.find(info.guid); - if (found == last_network_info_map_.end()) { - // If we cannot find |info| in |last_network_info_map_|, just return true - // since this is a new network so we have nothing to compare. - return true; - } else { - return *found->second != info; - } -} - -TriView* NetworkListView::CreateConnectionWarning() { - // Set up layout and apply sticky row property. - TriView* connection_warning = TrayPopupUtils::CreateDefaultRowView( - /*use_wide_layout=*/false); - TrayPopupUtils::ConfigureAsStickyHeader(connection_warning); - - // Set 'info' icon on left side. - views::ImageView* image_view = - TrayPopupUtils::CreateMainImageView(/*use_wide_layout=*/false); - image_view->SetImage( - gfx::CreateVectorIcon(kSystemMenuInfoIcon, GetIconColor())); - image_view->SetBackground(views::CreateSolidBackground(SK_ColorTRANSPARENT)); - connection_warning->AddView(TriView::Container::START, image_view); - - // Set message label in middle of row. - views::Label* label = TrayPopupUtils::CreateDefaultLabel(); - label->SetText( - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_MONITORED_WARNING)); - label->SetBackground(views::CreateSolidBackground(SK_ColorTRANSPARENT)); - label->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - TrayPopupUtils::SetLabelFontList( - label, TrayPopupUtils::FontStyle::kDetailedViewLabel); - - connection_warning->AddView(TriView::Container::CENTER, label); - connection_warning->SetContainerBorder( - TriView::Container::CENTER, views::CreateEmptyBorder(gfx::Insets::TLBR( - 0, 0, 0, kTrayPopupLabelRightPadding))); - - // Nothing to the right of the text. - connection_warning->SetContainerVisible(TriView::Container::END, false); - return connection_warning; -} - -} // namespace ash
diff --git a/ash/system/network/network_list_view.h b/ash/system/network/network_list_view.h deleted file mode 100644 index bbbb244..0000000 --- a/ash/system/network/network_list_view.h +++ /dev/null
@@ -1,170 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_NETWORK_NETWORK_LIST_VIEW_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_LIST_VIEW_H_ - -#include <map> -#include <memory> -#include <set> -#include <string> -#include <vector> - -#include "ash/system/network/network_icon_animation_observer.h" -#include "ash/system/network/network_info.h" -#include "ash/system/network/network_state_list_detailed_view.h" -#include "base/memory/weak_ptr.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" -#include "chromeos/services/network_config/public/mojom/network_types.mojom-forward.h" - -namespace views { -class Separator; -class View; -} // namespace views - -namespace ash { - -class HoverHighlightView; -class NetworkSectionHeaderView; -class MobileSectionHeaderView; -class TrayInfoLabel; -class TriView; -class WifiSectionHeaderView; - -// A list of available networks of a given type. This class is used for all -// network types except VPNs. For VPNs, see the |VPNList| class. -class NetworkListView : public NetworkStateListDetailedView, - public network_icon::AnimationObserver { - public: - NetworkListView(DetailedViewDelegate* delegate, LoginStatus login); - - NetworkListView(const NetworkListView&) = delete; - NetworkListView& operator=(const NetworkListView&) = delete; - - ~NetworkListView() override; - - // NetworkStateListDetailedView: - void UpdateNetworkList() override; - bool IsNetworkEntry(views::View* view, std::string* guid) const override; - - // views::View: - const char* GetClassName() const override; - - private: - void OnGetNetworkStateList( - std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr> - networks); - - // Refreshes a list of child views, updates |network_map_| and - // |network_guid_map_| and performs layout making sure selected view if any is - // scrolled into view. - void UpdateNetworkListInternal(); - - // Adds new or updates existing child views including header row and messages. - // Returns a set of guids for the added network connections. - std::unique_ptr<std::set<std::string>> UpdateNetworkListEntries(); - - bool ShouldMobileDataSectionBeShown(); - - // Creates the view which displays a warning message, if a VPN or proxy is - // being used. - TriView* CreateConnectionWarning(); - - // Updates |view| with the information in |info|. - void UpdateViewForNetwork(HoverHighlightView* view, const NetworkInfo& info); - - // Creates a battery icon next to the name of Tether networks indicating - // the battery percentage of the mobile device that is being used as a - // hotspot. - views::View* CreatePowerStatusView(const NetworkInfo& info); - - // Creates a policy icon next to the name of managed networks indicating - // that the network is managed by policy. Returns |nullptr| if the network is - // not managed by policy. - views::View* CreatePolicyView(const NetworkInfo& info); - - // Adds or updates child views representing the network connections when - // |is_wifi| is matching the attribute of a network connection starting at - // |child_index|. Returns a set of guids for the added network - // connections. - std::unique_ptr<std::set<std::string>> UpdateNetworkChildren( - chromeos::network_config::mojom::NetworkType type, - size_t child_index); - void UpdateNetworkChild(size_t index, const NetworkInfo* info); - - // Reorders children of |scroll_content()| as necessary placing |view| at - // |index|. - void PlaceViewAtIndex(views::View* view, size_t index); - - // Creates an info label with text specified by |message_id| and adds it to - // |scroll_content()| if necessary or updates the text and reorders the - // |scroll_content()| placing the info label at |insertion_index|. When - // |message_id| is zero removes the |*info_label_ptr| from the - // |scroll_content()| and destroys it. |info_label_ptr| is an in/out parameter - // and is only modified if the info label is created or destroyed. - void UpdateInfoLabel(int message_id, - size_t insertion_index, - TrayInfoLabel** info_label_ptr); - - // Updates a cellular/Wi-Fi header row |view| and reorders the - // |scroll_content()| placing the |view| at |child_index|. Returns the index - // where the next child should be inserted, i.e., the index directly after the - // last inserted child. - size_t UpdateNetworkSectionHeader( - chromeos::network_config::mojom::NetworkType type, - bool enabled, - size_t child_index, - NetworkSectionHeaderView* view, - views::Separator** separator_view); - - // network_icon::AnimationObserver: - void NetworkIconChanged() override; - - // Returns true if the info should be updated to the view for network, - // otherwise false. - bool NeedUpdateViewForNetwork(const NetworkInfo& info) const; - - // Creates an accessibility label for given network. - std::u16string GenerateAccessibilityLabel(const NetworkInfo& info); - - // Creates an accessibility description for the given network that includes - // all details that are shown in the ui. - std::u16string GenerateAccessibilityDescription(const NetworkInfo& info); - - bool needs_relayout_ = false; - - // Owned by the views heirarchy. - TrayInfoLabel* mobile_status_message_ = nullptr; - TrayInfoLabel* wifi_status_message_ = nullptr; - MobileSectionHeaderView* mobile_header_view_ = nullptr; - WifiSectionHeaderView* wifi_header_view_ = nullptr; - views::Separator* mobile_separator_view_ = nullptr; - views::Separator* wifi_separator_view_ = nullptr; - TriView* connection_warning_ = nullptr; - - bool vpn_connected_ = false; - bool wifi_has_networks_ = false; - bool tether_has_networks_ = false; - bool mobile_has_networks_ = false; - - // An owned list of network info. - std::vector<std::unique_ptr<NetworkInfo>> network_list_; - - using NetworkMap = std::map<views::View*, std::string>; - NetworkMap network_map_; - - // A map of network guids to their view. - using NetworkGuidMap = std::map<std::string, HoverHighlightView*>; - NetworkGuidMap network_guid_map_; - - // Save a map of network guids to their infos against current |network_list_|. - using NetworkInfoMap = std::map<std::string, std::unique_ptr<NetworkInfo>>; - NetworkInfoMap last_network_info_map_; - - base::WeakPtrFactory<NetworkListView> weak_ptr_factory_{this}; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_LIST_VIEW_H_
diff --git a/ash/system/network/network_list_view_controller_impl.cc b/ash/system/network/network_list_view_controller_impl.cc index eb9405a..06b3071 100644 --- a/ash/system/network/network_list_view_controller_impl.cc +++ b/ash/system/network/network_list_view_controller_impl.cc
@@ -133,7 +133,6 @@ NetworkDetailedNetworkView* network_detailed_network_view) : model_(Shell::Get()->system_tray_model()->network_state_model()), network_detailed_network_view_(network_detailed_network_view) { - DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled()); DCHECK(network_detailed_network_view_); Shell::Get()->system_tray_model()->network_state_model()->AddObserver(this);
diff --git a/ash/system/network/network_row_title_view.cc b/ash/system/network/network_row_title_view.cc deleted file mode 100644 index 1e55796..0000000 --- a/ash/system/network/network_row_title_view.cc +++ /dev/null
@@ -1,44 +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. - -#include "ash/system/network/network_row_title_view.h" - -#include <string> - -#include "ash/style/ash_color_provider.h" -#include "ash/system/tray/tray_popup_utils.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/font.h" -#include "ui/gfx/font_list.h" -#include "ui/views/layout/box_layout.h" - -namespace ash { - -namespace { - -const int kLineHeight = 20; - -} // namespace - -NetworkRowTitleView::NetworkRowTitleView(int title_message_id) - : title_(TrayPopupUtils::CreateDefaultLabel()) { - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - - title_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - TrayPopupUtils::SetLabelFontList(title_, - TrayPopupUtils::FontStyle::kSubHeader); - title_->SetLineHeight(kLineHeight); - title_->SetText(l10n_util::GetStringUTF16(title_message_id)); - AddChildView(title_); -} - -NetworkRowTitleView::~NetworkRowTitleView() = default; - -const char* NetworkRowTitleView::GetClassName() const { - return "NetworkRowTitleView"; -} - -} // namespace ash
diff --git a/ash/system/network/network_row_title_view.h b/ash/system/network/network_row_title_view.h deleted file mode 100644 index 2e84d02a..0000000 --- a/ash/system/network/network_row_title_view.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_NETWORK_NETWORK_ROW_TITLE_VIEW_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_ROW_TITLE_VIEW_H_ - -#include "ash/ash_export.h" -#include "ui/views/controls/label.h" - -namespace ash { - -// Title row for the network section of quick settings, which displays the name -// of a network type (e.g., Wi-Fi or Mobile data). -class ASH_EXPORT NetworkRowTitleView : public views::View { - public: - explicit NetworkRowTitleView(int title_message_id); - - NetworkRowTitleView(const NetworkRowTitleView&) = delete; - NetworkRowTitleView& operator=(const NetworkRowTitleView&) = delete; - - ~NetworkRowTitleView() override; - - // views::View: - const char* GetClassName() const override; - - private: - views::Label* const title_; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_ROW_TITLE_VIEW_H_
diff --git a/ash/system/network/network_section_header_view.cc b/ash/system/network/network_section_header_view.cc deleted file mode 100644 index 4aa1a3a..0000000 --- a/ash/system/network/network_section_header_view.cc +++ /dev/null
@@ -1,503 +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 "ash/system/network/network_section_header_view.h" - -#include "ash/public/cpp/bluetooth_config_service.h" -#include "ash/public/cpp/system_tray_client.h" -#include "ash/resources/vector_icons/vector_icons.h" -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/style/icon_button.h" -#include "ash/system/model/system_tray_model.h" -#include "ash/system/network/network_utils.h" -#include "ash/system/network/tray_network_state_model.h" -#include "ash/system/tray/tray_toggle_button.h" -#include "base/functional/bind.h" -#include "base/metrics/user_metrics.h" -#include "chromeos/ash/components/dbus/hermes/hermes_manager_client.h" -#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" -#include "chromeos/strings/grit/chromeos_strings.h" -#include "components/onc/onc_constants.h" -#include "components/vector_icons/vector_icons.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/controls/image_view.h" - -namespace ash { - -namespace { - -using ::chromeos::network_config::IsInhibited; -using ::chromeos::network_config::mojom::DeviceStateProperties; -using ::chromeos::network_config::mojom::DeviceStateType; -using ::chromeos::network_config::mojom::FilterType; -using ::chromeos::network_config::mojom::GlobalPolicy; -using ::chromeos::network_config::mojom::NetworkFilter; -using ::chromeos::network_config::mojom::NetworkStatePropertiesPtr; -using ::chromeos::network_config::mojom::NetworkType; - -const int64_t kBluetoothTimeoutDelaySeconds = 2; - -bool IsCellularDeviceInhibited() { - const DeviceStateProperties* cellular_device = - Shell::Get()->system_tray_model()->network_state_model()->GetDevice( - NetworkType::kCellular); - if (!cellular_device) - return false; - return cellular_device->inhibit_reason != - chromeos::network_config::mojom::InhibitReason::kNotInhibited; -} - -bool IsCellularInhibited() { - const DeviceStateProperties* cellular_device = - Shell::Get()->system_tray_model()->network_state_model()->GetDevice( - NetworkType::kCellular); - return IsInhibited(cellular_device); -} - -void ShowCellularSettings() { - Shell::Get() - ->system_tray_model() - ->network_state_model() - ->cros_network_config() - ->GetNetworkStateList( - NetworkFilter::New(FilterType::kVisible, NetworkType::kCellular, - /*limit=*/1), - base::BindOnce([](std::vector<NetworkStatePropertiesPtr> networks) { - std::string guid; - if (networks.size() > 0) - guid = networks[0]->guid; - Shell::Get()->system_tray_model()->client()->ShowNetworkSettings( - guid); - })); -} - -bool IsSecondaryUser() { - SessionControllerImpl* session_controller = - Shell::Get()->session_controller(); - return session_controller->IsActiveUserSessionStarted() && - !session_controller->IsUserPrimary(); -} - -bool IsESimSupported() { - const DeviceStateProperties* cellular_device = - Shell::Get()->system_tray_model()->network_state_model()->GetDevice( - NetworkType::kCellular); - - if (!cellular_device || !cellular_device->sim_infos) - return false; - - // Check both the SIM slot infos and the number of EUICCs because the former - // comes from Shill and the latter from Hermes, and so there may be instances - // where one may be true while they other isn't. - if (HermesManagerClient::Get()->GetAvailableEuiccs().empty()) - return false; - - for (const auto& sim_info : *cellular_device->sim_infos) { - if (!sim_info->eid.empty()) - return true; - } - return false; -} - -int GetAddESimTooltipMessageId() { - const DeviceStateProperties* cellular_device = - Shell::Get()->system_tray_model()->network_state_model()->GetDevice( - NetworkType::kCellular); - - DCHECK(cellular_device); - - switch (cellular_device->inhibit_reason) { - case chromeos::network_config::mojom::InhibitReason::kInstallingProfile: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_INSTALLING_PROFILE; - case chromeos::network_config::mojom::InhibitReason::kRenamingProfile: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RENAMING_PROFILE; - case chromeos::network_config::mojom::InhibitReason::kRemovingProfile: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REMOVING_PROFILE; - case chromeos::network_config::mojom::InhibitReason::kConnectingToProfile: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_CONNECTING_TO_PROFILE; - case chromeos::network_config::mojom::InhibitReason::kRefreshingProfileList: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REFRESHING_PROFILE_LIST; - case chromeos::network_config::mojom::InhibitReason::kNotInhibited: - return IDS_ASH_STATUS_TRAY_ADD_CELLULAR_LABEL; - case chromeos::network_config::mojom::InhibitReason::kResettingEuiccMemory: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RESETTING_ESIM; - case chromeos::network_config::mojom::InhibitReason::kDisablingProfile: - return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_DISABLING_PROFILE; - } -} - -} // namespace - -NetworkSectionHeaderView::NetworkSectionHeaderView(int title_id) - : title_id_(title_id), - model_(Shell::Get()->system_tray_model()->network_state_model()) {} - -void NetworkSectionHeaderView::Init(bool enabled) { - InitializeLayout(); - AddExtraButtons(enabled); - AddToggleButton(enabled); -} - -void NetworkSectionHeaderView::AddExtraButtons(bool enabled) {} - -void NetworkSectionHeaderView::SetToggleVisibility(bool visible) { - toggle_->SetVisible(visible); -} - -void NetworkSectionHeaderView::SetToggleState(bool toggle_enabled, bool is_on) { - toggle_->SetEnabled(toggle_enabled); - toggle_->SetAcceptsEvents(toggle_enabled); - toggle_->AnimateIsOn(is_on); -} - -const char* NetworkSectionHeaderView::GetClassName() const { - return "NetworkSectionHeaderView"; -} - -int NetworkSectionHeaderView::GetHeightForWidth(int width) const { - // Make row height fixed avoiding layout manager adjustments. - return GetPreferredSize().height(); -} - -void NetworkSectionHeaderView::InitializeLayout() { - TrayPopupUtils::ConfigureAsStickyHeader(this); - SetLayoutManager(std::make_unique<views::FillLayout>()); - container_ = TrayPopupUtils::CreateSubHeaderRowView(true); - container_->AddView( - TriView::Container::START, - TrayPopupUtils::CreateMainImageView(/*use_wide_layout=*/false)); - AddChildView(container_); - - network_row_title_view_ = new NetworkRowTitleView(title_id_); - container_->AddView(TriView::Container::CENTER, network_row_title_view_); -} - -void NetworkSectionHeaderView::AddToggleButton(bool enabled) { - toggle_ = new TrayToggleButton( - base::BindRepeating(&NetworkSectionHeaderView::ToggleButtonPressed, - base::Unretained(this)), - title_id_); - toggle_->SetIsOn(enabled); - container_->AddView(TriView::Container::END, toggle_); -} - -void NetworkSectionHeaderView::ToggleButtonPressed() { - // In the event of frequent clicks, helps to prevent a toggle button state - // from becoming inconsistent with the async operation of enabling / - // disabling of mobile radio. The toggle will get unlocked in the next - // call to NetworkListView::Update(). Note that we don't disable/enable - // because that would clear focus. - toggle_->SetAcceptsEvents(false); - OnToggleToggled(toggle_->GetIsOn()); -} - -MobileSectionHeaderView::MobileSectionHeaderView() - : NetworkSectionHeaderView(IDS_ASH_STATUS_TRAY_NETWORK_MOBILE) { - bool initially_enabled = model()->GetDeviceState(NetworkType::kCellular) == - DeviceStateType::kEnabled || - model()->GetDeviceState(NetworkType::kTether) == - DeviceStateType::kEnabled; - NetworkSectionHeaderView::Init(initially_enabled); - model()->AddObserver(this); - GetBluetoothConfigService( - remote_cros_bluetooth_config_.BindNewPipeAndPassReceiver()); -} - -MobileSectionHeaderView::~MobileSectionHeaderView() { - model()->RemoveObserver(this); -} - -const char* MobileSectionHeaderView::GetClassName() const { - return "MobileSectionHeaderView"; -} - -int MobileSectionHeaderView::UpdateToggleAndGetStatusMessage( - bool mobile_has_networks, - bool tether_has_networks) { - DeviceStateType cellular_state = - model()->GetDeviceState(NetworkType::kCellular); - DeviceStateType tether_state = model()->GetDeviceState(NetworkType::kTether); - - bool default_toggle_enabled = !IsSecondaryUser(); - - // If Cellular is available, toggle state and status message reflect Cellular. - if (cellular_state != DeviceStateType::kUnavailable) { - if (cellular_state == DeviceStateType::kUninitialized) { - SetToggleVisibility(false); - return IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR; - } - - if (IsCellularDeviceInhibited()) { - // When a device is inhibited, it cannot process any new operations. Thus, - // keep the toggle on to show users that the device is active, but set it - // to be disabled to make it clear that users cannot update it until it - // becomes uninhibited. - SetToggleVisibility(true); - SetToggleState(false /* toggle_enabled */, true /* is_on */); - return 0; - } - - bool toggle_enabled = default_toggle_enabled && - (cellular_state == DeviceStateType::kEnabled || - cellular_state == DeviceStateType::kDisabled); - bool cellular_enabled = cellular_state == DeviceStateType::kEnabled; - SetToggleVisibility(true); - SetToggleState(toggle_enabled, cellular_enabled); - if (cellular_state == DeviceStateType::kDisabling) { - return IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLING; - } - - if (cellular_enabled) { - if (mobile_has_networks) - return 0; - return IDS_ASH_STATUS_TRAY_NO_MOBILE_NETWORKS; - } - return IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED; - } - - // When Cellular is not available, always show the toggle. - SetToggleVisibility(true); - - // Tether is also unavailable (edge case). - if (tether_state == DeviceStateType::kUnavailable) { - SetToggleState(false /* toggle_enabled */, false /* is_on */); - return IDS_ASH_STATUS_TRAY_NETWORK_MOBILE_DISABLED; - } - - // Otherwise, toggle state and status message reflect Tether. - if (tether_state == DeviceStateType::kUninitialized) { - if (waiting_for_tether_initialize_) { - SetToggleState(false /* toggle_enabled */, true /* is_on */); - // "Initializing...". TODO(stevenjb): Rename the string to _MOBILE. - return IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR; - } else { - SetToggleState(default_toggle_enabled, false /* is_on */); - return IDS_ASH_STATUS_TRAY_ENABLING_MOBILE_ENABLES_BLUETOOTH; - } - } - - bool tether_enabled = tether_state == DeviceStateType::kEnabled; - - if (waiting_for_tether_initialize_) { - waiting_for_tether_initialize_ = false; - enable_bluetooth_timer_.Stop(); - if (!tether_enabled) { - // We enabled Bluetooth so Tether is now initialized, but it was not - // enabled so enable it. - model()->SetNetworkTypeEnabledState(NetworkType::kTether, true); - SetToggleState(default_toggle_enabled, true /* is_on */); - // "Initializing...". TODO(stevenjb): Rename the string to _MOBILE. - return IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR; - } - } - - // Ensure that the toggle state and status message match the tether state. - SetToggleState(default_toggle_enabled, tether_enabled /* is_on */); - if (tether_enabled && !tether_has_networks) - return IDS_ASH_STATUS_TRAY_NO_MOBILE_DEVICES_FOUND; - return 0; -} - -void MobileSectionHeaderView::OnToggleToggled(bool is_on) { - RecordNetworkTypeToggled(NetworkType::kMobile, is_on); - DeviceStateType cellular_state = - model()->GetDeviceState(NetworkType::kCellular); - - // When Cellular is available, the toggle controls Cellular enabled state. - // (Tether may be enabled by turning on Bluetooth and turning on - // 'Get data connection' in the Settings > Mobile data subpage). - if (cellular_state != DeviceStateType::kUnavailable) { - if (is_on && IsCellularInhibited()) { - ShowCellularSettings(); - return; - } - model()->SetNetworkTypeEnabledState(NetworkType::kCellular, is_on); - return; - } - - DeviceStateType tether_state = model()->GetDeviceState(NetworkType::kTether); - - // Tether is also unavailable (edge case). - if (tether_state == DeviceStateType::kUnavailable) - return; - - // If Tether is available but uninitialized, we expect Bluetooth to be off. - // Enable Bluetooth so that Tether will be initialized. Ignore edge cases - // (e.g. Bluetooth was disabled from a different UI). - if (tether_state == DeviceStateType::kUninitialized) { - if (is_on && !waiting_for_tether_initialize_) - EnableBluetooth(); - return; - } - - // Otherwise the toggle controls the Tether enabled state. - model()->SetNetworkTypeEnabledState(NetworkType::kTether, is_on); -} - -void MobileSectionHeaderView::AddExtraButtons(bool enabled) { - // The button navigates to Settings, only add it if this can occur. - if (!TrayPopupUtils::CanOpenWebUISettings()) - return; - - // The button opens the eSIM setup flow, and should only be added if the - // device is eSIM-capable. - if (!IsESimSupported()) { - return; - } - - can_add_esim_button_be_enabled_ = enabled; - const gfx::VectorIcon& icon = base::i18n::IsRTL() ? kAddCellularNetworkRtlIcon - : kAddCellularNetworkIcon; - add_esim_button_ = new IconButton( - base::BindRepeating(&MobileSectionHeaderView::AddCellularButtonPressed, - base::Unretained(this)), - IconButton::Type::kMedium, &icon, GetAddESimTooltipMessageId()); - add_esim_button_->SetEnabled(enabled && !IsCellularDeviceInhibited()); - container()->AddView(TriView::Container::END, add_esim_button_); - UpdateAddESimButtonVisibility(); -} - -void MobileSectionHeaderView::DeviceStateListChanged() { - if (!add_esim_button_) - return; - - if (!IsESimSupported()) { - add_esim_button_->SetVisible(/*visible=*/false); - return; - } - - add_esim_button_->SetEnabled(can_add_esim_button_be_enabled_ && - !IsCellularDeviceInhibited()); - add_esim_button_->SetTooltipText( - l10n_util::GetStringUTF16(GetAddESimTooltipMessageId())); -} - -void MobileSectionHeaderView::GlobalPolicyChanged() { - UpdateAddESimButtonVisibility(); -} - -void MobileSectionHeaderView::UpdateAddESimButtonVisibility() { - if (!add_esim_button_) { - return; - } - - const GlobalPolicy* global_policy = model()->global_policy(); - - // Adding new cellular networks is disallowed when only policy cellular - // networks are allowed by admin. - if (!global_policy || global_policy->allow_only_policy_cellular_networks) { - add_esim_button_->SetVisible(/*visible=*/false); - return; - } - - add_esim_button_->SetVisible(/*visible=*/true); -} - -void MobileSectionHeaderView::AddCellularButtonPressed() { - Shell::Get()->system_tray_model()->client()->ShowNetworkCreate( - ::onc::network_type::kCellular); -} - -void MobileSectionHeaderView::EnableBluetooth() { - DCHECK(!waiting_for_tether_initialize_); - remote_cros_bluetooth_config_->SetBluetoothEnabledState(true); - waiting_for_tether_initialize_ = true; - enable_bluetooth_timer_.Start( - FROM_HERE, base::Seconds(kBluetoothTimeoutDelaySeconds), - base::BindOnce(&MobileSectionHeaderView::OnEnableBluetoothTimeout, - weak_ptr_factory_.GetWeakPtr())); -} - -void MobileSectionHeaderView::OnEnableBluetoothTimeout() { - DCHECK(waiting_for_tether_initialize_); - waiting_for_tether_initialize_ = false; - SetToggleState(true /* toggle_enabled */, false /* is_on */); - - LOG(ERROR) << "Error enabling Bluetooth. Cannot enable Mobile data."; -} - -WifiSectionHeaderView::WifiSectionHeaderView() - : NetworkSectionHeaderView(IDS_ASH_STATUS_TRAY_NETWORK_WIFI) { - bool enabled = - model()->GetDeviceState(NetworkType::kWiFi) == DeviceStateType::kEnabled; - NetworkSectionHeaderView::Init(enabled); - model()->AddObserver(this); -} - -WifiSectionHeaderView::~WifiSectionHeaderView() { - model()->RemoveObserver(this); -} - -void WifiSectionHeaderView::DeviceStateListChanged() { - UpdateJoinButtonVisibility(); -} - -void WifiSectionHeaderView::GlobalPolicyChanged() { - UpdateJoinButtonVisibility(); -} - -void WifiSectionHeaderView::SetToggleState(bool toggle_enabled, bool is_on) { - join_button_->SetEnabled(toggle_enabled && is_on); - NetworkSectionHeaderView::SetToggleState(toggle_enabled, is_on); -} - -const char* WifiSectionHeaderView::GetClassName() const { - return "WifiSectionHeaderView"; -} - -void WifiSectionHeaderView::OnToggleToggled(bool is_on) { - RecordNetworkTypeToggled(NetworkType::kWiFi, is_on); - model()->SetNetworkTypeEnabledState(NetworkType::kWiFi, is_on); -} - -void WifiSectionHeaderView::AddExtraButtons(bool enabled) { - auto* join_button = new IconButton( - base::BindRepeating(&WifiSectionHeaderView::JoinButtonPressed, - base::Unretained(this)), - IconButton::Type::kMedium, &vector_icons::kWifiAddIcon, - IDS_ASH_STATUS_TRAY_OTHER_WIFI); - join_button->SetEnabled(enabled); - container()->AddView(TriView::Container::END, join_button); - join_button_ = join_button; - UpdateJoinButtonVisibility(); -} - -void WifiSectionHeaderView::UpdateJoinButtonVisibility() { - if (!join_button_) { - return; - } - - const DeviceStateProperties* wifi_device = - model()->GetDevice(NetworkType::kWiFi); - if (!wifi_device) { - join_button_->SetVisible(/*visible=*/false); - return; - } - - const GlobalPolicy* global_policy = model()->global_policy(); - - // Adding new network config is disallowed when only policy wifi networks - // are allowed by admin or managed networks are available and corresponding - // settings is enabled. - if (!global_policy || - global_policy->allow_only_policy_wifi_networks_to_connect || - (global_policy->allow_only_policy_wifi_networks_to_connect_if_available && - wifi_device->managed_network_available)) { - join_button_->SetVisible(/*visible=*/false); - return; - } - - join_button_->SetVisible(/*visible=*/true); -} - -void WifiSectionHeaderView::JoinButtonPressed() { - base::RecordAction(base::UserMetricsAction("StatusArea_Network_JoinOther")); - Shell::Get()->system_tray_model()->client()->ShowNetworkCreate( - ::onc::network_type::kWiFi); -} - -} // namespace ash
diff --git a/ash/system/network/network_section_header_view.h b/ash/system/network/network_section_header_view.h deleted file mode 100644 index 46bcdb6..0000000 --- a/ash/system/network/network_section_header_view.h +++ /dev/null
@@ -1,184 +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 ASH_SYSTEM_NETWORK_NETWORK_SECTION_HEADER_VIEW_H_ -#define ASH_SYSTEM_NETWORK_NETWORK_SECTION_HEADER_VIEW_H_ - -#include "ash/system/network/network_row_title_view.h" -#include "ash/system/network/tray_network_state_observer.h" -#include "ash/system/tray/tray_popup_utils.h" -#include "ash/system/tray/tri_view.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h" -#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "ui/views/controls/button/toggle_button.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/view.h" - -namespace ash { - -class IconButton; -class TrayNetworkStateModel; - -// A header row for sections in network detailed view which contains a title and -// a toggle button to turn on/off the section. Subclasses are given the -// opportunity to add extra buttons before the toggle button is added. -class NetworkSectionHeaderView : public views::View { - public: - explicit NetworkSectionHeaderView(int title_id); - - NetworkSectionHeaderView(const NetworkSectionHeaderView&) = delete; - NetworkSectionHeaderView& operator=(const NetworkSectionHeaderView&) = delete; - - ~NetworkSectionHeaderView() override = default; - - // Modify visibility of section toggle - void SetToggleVisibility(bool visible); - - // Modify enabled/disabled and on/off state of toggle. - virtual void SetToggleState(bool toggle_enabled, bool is_on); - - // views::View: - const char* GetClassName() const override; - - protected: - void Init(bool enabled); - - // This is called before the toggle button is added to give subclasses an - // opportunity to add more buttons before the toggle button. Subclasses can - // add buttons to container() using AddChildView(). - virtual void AddExtraButtons(bool enabled); - - // Called when |toggle_| is clicked and toggled. Subclasses can override to - // enabled/disable their respective technology, for example. - virtual void OnToggleToggled(bool is_on) = 0; - - TrayNetworkStateModel* model() { return model_; } - TriView* container() const { return container_; } - - // views::View: - int GetHeightForWidth(int width) const override; - - private: - void InitializeLayout(); - void AddToggleButton(bool enabled); - - void ToggleButtonPressed(); - - // Resource ID for the string to use as the title of the section and for the - // accessible text on the section header toggle button. - const int title_id_; - - TrayNetworkStateModel* model_; - - // View containing header row views, including title, toggle, and extra - // buttons. - TriView* container_ = nullptr; - - // View containing the header row view. Is a child of the CENTER of - // |container_|. - NetworkRowTitleView* network_row_title_view_ = nullptr; - - // ToggleButton to toggle section on or off. - views::ToggleButton* toggle_ = nullptr; -}; - -// "Mobile Data" header row. Mobile Data reflects both Cellular state and -// Tether state. When both technologies are available, Cellular state takes -// precedence over Tether (but in some cases Tether state may be shown). -class MobileSectionHeaderView : public NetworkSectionHeaderView, - public TrayNetworkStateObserver { - public: - MobileSectionHeaderView(); - - MobileSectionHeaderView(const MobileSectionHeaderView&) = delete; - MobileSectionHeaderView& operator=(const MobileSectionHeaderView&) = delete; - - ~MobileSectionHeaderView() override; - - // Updates mobile toggle state and returns the id of the status message - // that should be shown while connecting to a network. Returns zero when no - // message should be shown. - int UpdateToggleAndGetStatusMessage(bool mobile_has_networks, - bool tether_has_networks); - - // views::View: - const char* GetClassName() const override; - - private: - // NetworkListView::NetworkSectionHeaderView: - void OnToggleToggled(bool is_on) override; - void AddExtraButtons(bool enabled) override; - - // TrayNetworkStateObserver: - void DeviceStateListChanged() override; - void GlobalPolicyChanged() override; - - void UpdateAddESimButtonVisibility(); - - void AddCellularButtonPressed(); - - // When Tether is disabled because Bluetooth is off, then enabling Bluetooth - // will enable Tether. If enabling Bluetooth takes longer than some timeout - // period, it is assumed that there was an error. In that case, Tether will - // remain uninitialized and Mobile Data will remain toggled off. - void EnableBluetooth(); - void OnEnableBluetoothTimeout(); - - bool waiting_for_tether_initialize_ = false; - base::OneShotTimer enable_bluetooth_timer_; - - // Button that navigates to the Settings mobile data subpage with the eSIM - // setup dialog open. This is null when the device is not eSIM-capable. - IconButton* add_esim_button_ = nullptr; - - // Indicates whether add_esim_button_ should be enabled when the device is - // not inhibited. - bool can_add_esim_button_be_enabled_ = false; - - // CrosBluetoothConfig remote that is only bound if the Bluetooth - // Revamp flag is enabled. - mojo::Remote<bluetooth_config::mojom::CrosBluetoothConfig> - remote_cros_bluetooth_config_; - - base::WeakPtrFactory<MobileSectionHeaderView> weak_ptr_factory_{this}; -}; - -class WifiSectionHeaderView : public NetworkSectionHeaderView, - public TrayNetworkStateObserver { - public: - WifiSectionHeaderView(); - - WifiSectionHeaderView(const WifiSectionHeaderView&) = delete; - WifiSectionHeaderView& operator=(const WifiSectionHeaderView&) = delete; - - ~WifiSectionHeaderView() override; - - // NetworkSectionHeaderView: - void SetToggleState(bool toggle_enabled, bool is_on) override; - - // views::View: - const char* GetClassName() const override; - - private: - // TrayNetworkStateObserver: - void DeviceStateListChanged() override; - void GlobalPolicyChanged() override; - - // NetworkSectionHeaderView: - void OnToggleToggled(bool is_on) override; - void AddExtraButtons(bool enabled) override; - void UpdateJoinButtonVisibility(); - - void JoinButtonPressed(); - - // A button to invoke "Join Wi-Fi network" dialog. - IconButton* join_button_ = nullptr; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_NETWORK_SECTION_HEADER_VIEW_H_
diff --git a/ash/system/network/unified_network_detailed_view_controller.cc b/ash/system/network/unified_network_detailed_view_controller.cc deleted file mode 100644 index 8380dbb1..0000000 --- a/ash/system/network/unified_network_detailed_view_controller.cc +++ /dev/null
@@ -1,43 +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 "ash/system/network/unified_network_detailed_view_controller.h" - -#include <memory> - -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/system/network/network_list_view.h" -#include "ash/system/tray/detailed_view_delegate.h" -#include "ui/base/l10n/l10n_util.h" - -namespace ash { - -UnifiedNetworkDetailedViewController::UnifiedNetworkDetailedViewController( - UnifiedSystemTrayController* tray_controller) - : detailed_view_delegate_( - std::make_unique<DetailedViewDelegate>(tray_controller)) { -} - -UnifiedNetworkDetailedViewController::~UnifiedNetworkDetailedViewController() = - default; - -std::unique_ptr<views::View> -UnifiedNetworkDetailedViewController::CreateView() { - DCHECK(!view_); - auto view = std::make_unique<NetworkListView>( - detailed_view_delegate_.get(), - Shell::Get()->session_controller()->login_status()); - view_ = view.get(); - view_->Init(); - return view; -} - -std::u16string UnifiedNetworkDetailedViewController::GetAccessibleName() const { - return l10n_util::GetStringUTF16( - IDS_ASH_QUICK_SETTINGS_BUBBLE_NETWORK_SETTINGS_ACCESSIBLE_DESCRIPTION); -} - -} // namespace ash
diff --git a/ash/system/network/unified_network_detailed_view_controller.h b/ash/system/network/unified_network_detailed_view_controller.h deleted file mode 100644 index 87af57e..0000000 --- a/ash/system/network/unified_network_detailed_view_controller.h +++ /dev/null
@@ -1,43 +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 ASH_SYSTEM_NETWORK_UNIFIED_NETWORK_DETAILED_VIEW_CONTROLLER_H_ -#define ASH_SYSTEM_NETWORK_UNIFIED_NETWORK_DETAILED_VIEW_CONTROLLER_H_ - -#include <memory> - -#include "ash/system/unified/detailed_view_controller.h" - -namespace ash { - -class DetailedViewDelegate; -class NetworkListView; -class UnifiedSystemTrayController; - -// Controller of Network detailed view in UnifiedSystemTray. -class UnifiedNetworkDetailedViewController : public DetailedViewController { - public: - explicit UnifiedNetworkDetailedViewController( - UnifiedSystemTrayController* tray_controller); - - UnifiedNetworkDetailedViewController( - const UnifiedNetworkDetailedViewController&) = delete; - UnifiedNetworkDetailedViewController& operator=( - const UnifiedNetworkDetailedViewController&) = delete; - - ~UnifiedNetworkDetailedViewController() override; - - // DetailedViewController: - std::unique_ptr<views::View> CreateView() override; - std::u16string GetAccessibleName() const override; - - private: - const std::unique_ptr<DetailedViewDelegate> detailed_view_delegate_; - - NetworkListView* view_ = nullptr; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_NETWORK_UNIFIED_NETWORK_DETAILED_VIEW_CONTROLLER_H_
diff --git a/ash/system/power/power_event_observer.cc b/ash/system/power/power_event_observer.cc index 760aa1cf..a199f6b1b 100644 --- a/ash/system/power/power_event_observer.cc +++ b/ash/system/power/power_event_observer.cc
@@ -341,7 +341,8 @@ // to launch the resume image. Dismiss the lock screen here to avoid making // them log in twice. if (proto.deepest_state() == - power_manager::SuspendDone_SuspendState_TO_DISK) { + power_manager::SuspendDone_SuspendState_TO_DISK && + Shell::Get()->session_controller()->IsScreenLocked()) { Shell::Get()->session_controller()->HideLockScreen(); } }
diff --git a/ash/system/power/power_event_observer_unittest.cc b/ash/system/power/power_event_observer_unittest.cc index 98fe3eb..dc45837b 100644 --- a/ash/system/power/power_event_observer_unittest.cc +++ b/ash/system/power/power_event_observer_unittest.cc
@@ -404,6 +404,31 @@ EXPECT_FALSE(GetLockedState()); } +// Verifies that hibernate suspend and resume does not attempt to hide the lock +// screen if the session does not get locked during suspend. +TEST_F(PowerEventObserverTest, HibernateWithUnlockedScreen) { + SetCanLockScreen(false); + SetShouldLockScreenAutomatically(false); + + // Suspend, and verify screen does not get locked. + observer_->SuspendImminent(power_manager::SuspendImminent_Reason_OTHER); + ASSERT_FALSE(GetLockedState()); + + power_manager::SuspendDone suspend_done = power_manager::SuspendDone(); + suspend_done.set_deepest_state( + power_manager::SuspendDone_SuspendState_TO_DISK); + observer_->SuspendDoneEx(suspend_done); + // Verify that screen lock hide was not requested in response to session + // resume. Unlock animation runs in two stages - first fades the lock screen + // UI out, and then fades the in-session UI in. The second stage runs in + // response to sessions state change, which is not expected in case session is + // not locked in the first place. Running the first stage of unlock animation + // may leave UI in incorrect state - for example, shelf would remain fully + // transparent. See https::/b/262315987. + EXPECT_EQ(0, GetSessionControllerClient()->request_hide_lock_screen_count()); + EXPECT_FALSE(GetLockedState()); +} + // Tests that displays will not be considered ready to suspend until the // animated wallpaper change finishes (if the wallpaper is being animated to // another wallpaper after the screen is locked).
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc index 3c6b33a..557a8c7 100644 --- a/ash/system/status_area_widget_unittest.cc +++ b/ash/system/status_area_widget_unittest.cc
@@ -599,6 +599,9 @@ EXPECT_FALSE(ime_menu_->GetVisible()); EXPECT_FALSE(virtual_keyboard_->GetVisible()); EXPECT_TRUE(palette_->GetVisible()); + // We should also check the opacity to make sure the tray isn't visible with + // zero opacity; see b/265165818. + EXPECT_EQ(palette_->layer()->opacity(), 1); } TEST_F(StatusAreaWidgetCollapseStateTest, TrayHiddenWhileCollapsed) {
diff --git a/ash/system/time/calendar_event_list_item_view_jelly.cc b/ash/system/time/calendar_event_list_item_view_jelly.cc index ab8e25e..4ef6cb4 100644 --- a/ash/system/time/calendar_event_list_item_view_jelly.cc +++ b/ash/system/time/calendar_event_list_item_view_jelly.cc
@@ -211,7 +211,7 @@ bool CalendarEventListItemViewJelly::PerformAction(const ui::Event& event) { DCHECK(event_url_.is_empty() || event_url_.is_valid()); - calendar_metrics::RecordEventListItemActivated(event); + calendar_view_controller_->RecordEventListItemActivated(event); calendar_view_controller_->OnCalendarEventWillLaunch(); GURL finalized_url;
diff --git a/ash/system/time/calendar_event_list_view_unittest.cc b/ash/system/time/calendar_event_list_view_unittest.cc index 6e709f2..841a354 100644 --- a/ash/system/time/calendar_event_list_view_unittest.cc +++ b/ash/system/time/calendar_event_list_view_unittest.cc
@@ -198,6 +198,7 @@ histogram_tester.ExpectTotalCount( "Ash.Calendar.UserJourneyTime.EventLaunched", 1); + histogram_tester.ExpectTotalCount("Ash.Calendar.EventListItem.Activated", 1); } TEST_F(CalendarViewEventListViewTest, CheckTimeFormat) {
diff --git a/ash/system/time/calendar_metrics.cc b/ash/system/time/calendar_metrics.cc index 91c988b..7a56715f 100644 --- a/ash/system/time/calendar_metrics.cc +++ b/ash/system/time/calendar_metrics.cc
@@ -33,6 +33,10 @@ constexpr char kCalendarScrollSource[] = "Ash.Calendar.ScrollSource"; constexpr char kCalendarKeyboardNavigation[] = "Ash.Calendar.KeyboardNavigation"; +constexpr char kCalendarEventListItemInUpNextPressed[] = + "Ash.Calendar.UpNextView.EventListItem.Pressed"; +constexpr char kCalendarUpNextEventDisplayedCount[] = + "Ash.Calendar.UpNextView.EventDisplayedCount"; } // namespace @@ -114,6 +118,15 @@ base::UmaHistogramEnumeration(kCalendarKeyboardNavigation, key_source); } +void RecordEventListItemInUpNextLaunched(const ui::Event& event) { + base::UmaHistogramEnumeration(kCalendarEventListItemInUpNextPressed, + GetEventType(event)); +} + +void RecordUpNextEventCount(const int event_count) { + base::UmaHistogramCounts100(kCalendarUpNextEventDisplayedCount, event_count); +} + } // namespace calendar_metrics } // namespace ash
diff --git a/ash/system/time/calendar_metrics.h b/ash/system/time/calendar_metrics.h index 12e4fe6..daa245b5 100644 --- a/ash/system/time/calendar_metrics.h +++ b/ash/system/time/calendar_metrics.h
@@ -96,6 +96,10 @@ void RecordCalendarKeyboardNavigation( const CalendarKeyboardNavigationSource key_source); +void RecordEventListItemInUpNextLaunched(const ui::Event& event); + +void RecordUpNextEventCount(const int event_count); + } // namespace calendar_metrics } // namespace ash
diff --git a/ash/system/time/calendar_up_next_view.cc b/ash/system/time/calendar_up_next_view.cc index bc636f1..eb5566f 100644 --- a/ash/system/time/calendar_up_next_view.cc +++ b/ash/system/time/calendar_up_next_view.cc
@@ -12,6 +12,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/icon_button.h" #include "ash/system/time/calendar_event_list_item_view_jelly.h" +#include "ash/system/time/calendar_metrics.h" #include "ash/system/time/calendar_up_next_view_background_painter.h" #include "ash/system/time/calendar_utils.h" #include "ui/base/l10n/l10n_util.h" @@ -236,6 +237,8 @@ views::BoxLayout* content_layout_manager) { content_view_->RemoveAllChildViews(); + calendar_metrics::RecordUpNextEventCount(events.size()); + const auto now = base::Time::NowFromSystemTime(); const auto [selected_date_midnight, selected_date_midnight_utc] = calendar_utils::GetMidnight(now);
diff --git a/ash/system/time/calendar_up_next_view_unittest.cc b/ash/system/time/calendar_up_next_view_unittest.cc index b37e007a..3b8d6c1d 100644 --- a/ash/system/time/calendar_up_next_view_unittest.cc +++ b/ash/system/time/calendar_up_next_view_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/system/tray/tray_constants.h" #include "ash/test/ash_test_base.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" #include "ui/views/controls/label.h" #include "ui/views/controls/scroll_view.h" @@ -446,6 +447,62 @@ EXPECT_TRUE(called); } +TEST_F(CalendarUpNextViewTest, ShouldTrackLaunchingFromEventListItem) { + // Set time override. + base::subtle::ScopedTimeClockOverrides time_override( + []() { return base::subtle::TimeNowIgnoringOverride().LocalMidnight(); }, + nullptr, nullptr); + + // Add an upcoming event. + std::list<std::unique_ptr<google_apis::calendar::CalendarEvent>> events; + auto event_in_ten_mins_start_time = + base::subtle::TimeNowIgnoringOverride().LocalMidnight() + + base::Minutes(10); + auto event_in_ten_mins_end_time = + base::subtle::TimeNowIgnoringOverride().LocalMidnight() + base::Hours(1); + events.push_back( + CreateEvent(event_in_ten_mins_start_time, event_in_ten_mins_end_time)); + + auto histogram_tester = std::make_unique<base::HistogramTester>(); + CreateUpNextView(std::move(events)); + + EXPECT_EQ(GetContentsView()->children().size(), size_t(1)); + + // Click event inside the scrollview contents. + LeftClickOn(GetContentsView()->children()[0]); + + histogram_tester->ExpectTotalCount( + "Ash.Calendar.UpNextView.EventListItem.Pressed", 1); +} + +TEST_F(CalendarUpNextViewTest, ShouldTrackEventDisplayedCount) { + // Set time override. + base::subtle::ScopedTimeClockOverrides time_override( + []() { return base::subtle::TimeNowIgnoringOverride().LocalMidnight(); }, + nullptr, nullptr); + + // Add 5 upcoming events. + const int event_count = 5; + std::list<std::unique_ptr<google_apis::calendar::CalendarEvent>> events; + auto event_in_ten_mins_start_time = + base::subtle::TimeNowIgnoringOverride().LocalMidnight() + + base::Minutes(10); + auto event_in_ten_mins_end_time = + base::subtle::TimeNowIgnoringOverride().LocalMidnight() + base::Hours(1); + for (int i = 0; i < event_count; ++i) { + events.push_back( + CreateEvent(event_in_ten_mins_start_time, event_in_ten_mins_end_time)); + } + + auto histogram_tester = std::make_unique<base::HistogramTester>(); + CreateUpNextView(std::move(events)); + + EXPECT_EQ(GetContentsView()->children().size(), size_t(event_count)); + + histogram_tester->ExpectBucketCount( + "Ash.Calendar.UpNextView.EventDisplayedCount", event_count, 1); +} + class CalendarUpNextViewAnimationTest : public CalendarUpNextViewTest { public: CalendarUpNextViewAnimationTest()
diff --git a/ash/system/time/calendar_view_controller.cc b/ash/system/time/calendar_view_controller.cc index b71cc6c5..1bef007 100644 --- a/ash/system/time/calendar_view_controller.cc +++ b/ash/system/time/calendar_view_controller.cc
@@ -214,6 +214,19 @@ is_event_list_showing_ = false; } +void CalendarViewController::RecordEventListItemActivated( + const ui::Event& event) { + // The EventListItemView is used by both the event list view and the up next + // view. So if the event list view is not showing, then it's in the up next + // view. + if (is_event_list_showing_) { + calendar_metrics::RecordEventListItemActivated(event); + return; + } + + calendar_metrics::RecordEventListItemInUpNextLaunched(event); +} + void CalendarViewController::OnCalendarEventWillLaunch() { UmaHistogramMediumTimes("Ash.Calendar.UserJourneyTime.EventLaunched", base::TimeTicks::Now() - calendar_open_time_);
diff --git a/ash/system/time/calendar_view_controller.h b/ash/system/time/calendar_view_controller.h index 642ded5..dc0337d 100644 --- a/ash/system/time/calendar_view_controller.h +++ b/ash/system/time/calendar_view_controller.h
@@ -18,6 +18,7 @@ #include "google_apis/calendar/calendar_api_response_types.h" #include "google_apis/common/api_error_codes.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/events/event.h" namespace ash { @@ -70,6 +71,12 @@ // Gets called when the `CalendarEventListView` is closed. void OnEventListClosed(); + // Records the event list item being pressed on and the type of event. + // Captures whether it was from the `CalendarEventListView` or implicitly the + // `CalendarUpNextView` (the only other place the `CalendarEventListItemView` + // is used currently). + void RecordEventListItemActivated(const ui::Event& event); + // Called when a calendar event is about to launch. Used to record metrics. void OnCalendarEventWillLaunch();
diff --git a/ash/system/tray/system_nudge_controller.cc b/ash/system/tray/system_nudge_controller.cc index 690b8d92..df78e60 100644 --- a/ash/system/tray/system_nudge_controller.cc +++ b/ash/system/tray/system_nudge_controller.cc
@@ -92,7 +92,7 @@ return catalog_name == registry_entry.first; }); - // Don't record "TimeToAction" metric if the nudge hasn't been shown. + // Don't record "TimeToAction" metric if the nudge hasn't been shown before. if (it == std::end(nudge_registry)) return;
diff --git a/ash/system/tray/system_nudge_controller.h b/ash/system/tray/system_nudge_controller.h index 85223ece..d3e5c17 100644 --- a/ash/system/tray/system_nudge_controller.h +++ b/ash/system/tray/system_nudge_controller.h
@@ -30,7 +30,8 @@ virtual ~SystemNudgeController(); // Records Nudge "TimeToAction" metric, which tracks the time from when a - // nudge was shown to when the action the nudge informs of was performed. + // nudge was shown to when the nudge's suggested action was performed. + // The metric is not recorded if the nudge hasn't been shown before. static void RecordNudgeAction(NudgeCatalogName catalog_name); // Shows the nudge widget.
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index da82121..42d6239 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -312,7 +312,14 @@ visible_preferred_ ? "Ash.StatusArea.TrayBackgroundView.Shown" : "Ash.StatusArea.TrayBackgroundView.Hidden", catalog_name_); - StartVisibilityAnimation(GetEffectiveVisibility()); + + // Calling `StartVisibilityAnimation(GetEffectiveVisibility())` doesn't work + // for the case of a collapsed status area (see b/265165818). Passing + // `visible_preferred_` is better, but also means that animations happen for + // all trays, even those that would show/hide in the "hidden" part of a + // collapsed status area (but note that those animations are not visible until + // the status area is expanded). + StartVisibilityAnimation(visible_preferred_); // We need to update which trays overflow after showing or hiding a tray. // If the hide animation is still playing, we do the `UpdateStatusArea(bool
diff --git a/ash/system/unified/feature_tiles_container_view.cc b/ash/system/unified/feature_tiles_container_view.cc index 2f69586..6030e86 100644 --- a/ash/system/unified/feature_tiles_container_view.cc +++ b/ash/system/unified/feature_tiles_container_view.cc
@@ -221,6 +221,43 @@ event.type()); } +void FeatureTilesContainerView::Layout() { + views::View::Layout(); + + // `SelectedPageChanged` is called in order to recalculate the bounds of the + // page we're currently in. + SelectedPageChanged(0, pagination_model_->selected_page()); +} + +void FeatureTilesContainerView::AddedToWidget() { + GetFocusManager()->AddFocusChangeListener(this); +} + +void FeatureTilesContainerView::RemovedFromWidget() { + GetFocusManager()->RemoveFocusChangeListener(this); +} + +void FeatureTilesContainerView::OnWillChangeFocus(views::View* before, + views::View* now) {} + +void FeatureTilesContainerView::OnDidChangeFocus(views::View* before, + views::View* now) { + if (!now || !views::IsViewClass<FeatureTile>(now)) { + return; + } + + auto* current_page = now->parent()->parent(); + DCHECK(views::IsViewClass<PageContainer>(current_page)); + auto page_index = GetIndexOf(current_page); + if (!page_index.has_value()) { + return; + } + if (pagination_model_->selected_page() != + static_cast<int>(page_index.value())) { + pagination_model_->SelectPage(page_index.value(), false /*animate*/); + } +} + int FeatureTilesContainerView::CalculateRowsFromHeight(int height) { int row_height = kRowContainerSize.height();
diff --git a/ash/system/unified/feature_tiles_container_view.h b/ash/system/unified/feature_tiles_container_view.h index fd6da601..eaa8dfb 100644 --- a/ash/system/unified/feature_tiles_container_view.h +++ b/ash/system/unified/feature_tiles_container_view.h
@@ -8,6 +8,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/pagination/pagination_model_observer.h" #include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/focus/focus_manager.h" #include "ui/views/view.h" namespace ash { @@ -20,7 +21,8 @@ // It can place buttons in a 1x2 to 4x2 grid given the available height. // Implements pagination to be able to show all visible FeatureTiles. class ASH_EXPORT FeatureTilesContainerView : public views::View, - public PaginationModelObserver { + public PaginationModelObserver, + public views::FocusChangeListener { public: METADATA_HEADER(FeatureTilesContainerView); @@ -54,6 +56,13 @@ void OnGestureEvent(ui::GestureEvent* event) override; void OnScrollEvent(ui::ScrollEvent* event) override; bool OnMouseWheel(const ui::MouseWheelEvent& event) override; + void Layout() override; + void AddedToWidget() override; + void RemovedFromWidget() override; + + // views::FocusChangeListener: + void OnWillChangeFocus(views::View* before, views::View* now) override; + void OnDidChangeFocus(views::View* before, views::View* now) override; int displayable_rows() const { return displayable_rows_; }
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc index 2ed050f..1cbda38 100644 --- a/ash/system/unified/unified_system_tray_controller.cc +++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -40,8 +40,6 @@ #include "ash/system/nearby_share/nearby_share_feature_pod_controller.h" #include "ash/system/network/network_detailed_view_controller.h" #include "ash/system/network/network_feature_pod_controller.h" -#include "ash/system/network/network_feature_pod_controller_legacy.h" -#include "ash/system/network/unified_network_detailed_view_controller.h" #include "ash/system/network/unified_vpn_detailed_view_controller.h" #include "ash/system/network/vpn_feature_pod_controller.h" #include "ash/system/night_light/night_light_feature_pod_controller.h" @@ -444,12 +442,7 @@ base::RecordAction(base::UserMetricsAction("StatusArea_Network_Detailed")); - if (ash::features::IsQuickSettingsNetworkRevampEnabled()) { - ShowDetailedView(std::make_unique<NetworkDetailedViewController>(this)); - } else { - ShowDetailedView( - std::make_unique<UnifiedNetworkDetailedViewController>(this)); - } + ShowDetailedView(std::make_unique<NetworkDetailedViewController>(this)); } void UnifiedSystemTrayController::ShowBluetoothDetailedView() { @@ -646,13 +639,7 @@ } void UnifiedSystemTrayController::InitFeaturePods() { - if (ash::features::IsQuickSettingsNetworkRevampEnabled()) { - AddFeaturePodItem(std::make_unique<NetworkFeaturePodController>(this)); - } else { - AddFeaturePodItem( - std::make_unique<NetworkFeaturePodControllerLegacy>(this)); - } - + AddFeaturePodItem(std::make_unique<NetworkFeaturePodController>(this)); AddFeaturePodItem(std::make_unique<BluetoothFeaturePodController>(this)); AddFeaturePodItem(std::make_unique<AccessibilityFeaturePodController>(this)); AddFeaturePodItem(std::make_unique<QuietModeFeaturePodController>(this));
diff --git a/ash/system/video_conference/fake_video_conference_tray_controller.cc b/ash/system/video_conference/fake_video_conference_tray_controller.cc index 3671f7f..de79023 100644 --- a/ash/system/video_conference/fake_video_conference_tray_controller.cc +++ b/ash/system/video_conference/fake_video_conference_tray_controller.cc
@@ -4,9 +4,12 @@ #include "ash/system/video_conference/fake_video_conference_tray_controller.h" +#include <vector> + #include "ash/system/video_conference/effects/fake_video_conference_effects.h" #include "ash/system/video_conference/video_conference_tray_controller.h" #include "base/functional/callback.h" +#include "base/strings/utf_string_conversions.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" #include "chromeos/crosapi/mojom/video_conference.mojom.h" #include "media/capture/video/chromeos/mojom/cros_camera_service.mojom-shared.h" @@ -63,6 +66,12 @@ app_to_launch_state_[id] = true; } +void FakeVideoConferenceTrayController::HandleDeviceUsedWhileDisabled( + crosapi::mojom::VideoConferenceMediaDevice device, + const std::u16string& app_name) { + device_used_while_disabled_records_.emplace_back(device, app_name); +} + void FakeVideoConferenceTrayController::AddMediaApp( crosapi::mojom::VideoConferenceMediaAppInfoPtr media_app) { media_apps_.push_back(std::move(media_app));
diff --git a/ash/system/video_conference/fake_video_conference_tray_controller.h b/ash/system/video_conference/fake_video_conference_tray_controller.h index e2133ab..e113c02 100644 --- a/ash/system/video_conference/fake_video_conference_tray_controller.h +++ b/ash/system/video_conference/fake_video_conference_tray_controller.h
@@ -5,6 +5,9 @@ #ifndef ASH_SYSTEM_VIDEO_CONFERENCE_FAKE_VIDEO_CONFERENCE_TRAY_CONTROLLER_H_ #define ASH_SYSTEM_VIDEO_CONFERENCE_FAKE_VIDEO_CONFERENCE_TRAY_CONTROLLER_H_ +#include <utility> +#include <vector> + #include "ash/ash_export.h" #include "ash/system/video_conference/video_conference_tray_controller.h" #include "base/gtest_prod_util.h" @@ -38,6 +41,9 @@ void SetMicrophoneMuted(bool muted) override; void GetMediaApps(base::OnceCallback<void(MediaApps)> ui_callback) override; void ReturnToApp(const base::UnguessableToken& id) override; + void HandleDeviceUsedWhileDisabled( + crosapi::mojom::VideoConferenceMediaDevice device, + const std::u16string& app_name) override; // Adds or clears media app(s) in `media_apps_`. void AddMediaApp(crosapi::mojom::VideoConferenceMediaAppInfoPtr media_app); @@ -45,9 +51,16 @@ bool camera_muted() { return camera_muted_; } bool microphone_muted() { return microphone_muted_; } + const std::vector< + std::pair<crosapi::mojom::VideoConferenceMediaDevice, std::u16string>>& + device_used_while_disabled_records() { + return device_used_while_disabled_records_; + } private: FRIEND_TEST_ALL_PREFIXES(video_conference::ReturnToAppPanelTest, ReturnToApp); + FRIEND_TEST_ALL_PREFIXES(VideoConferenceAppServiceClientTest, + HandleDeviceUsedWhileDisabled); // A vector containing all currently running media apps. Used for testing. MediaApps media_apps_; @@ -56,6 +69,11 @@ bool camera_muted_ = false; bool microphone_muted_ = false; + // Records calls of the HandleDeviceUsedWhileDisabled for testing. + std::vector< + std::pair<crosapi::mojom::VideoConferenceMediaDevice, std::u16string>> + device_used_while_disabled_records_; + // A mapping from the media app's id to its launch state (whether the app is // launched and brought to the foreground). std::map<base::UnguessableToken, bool> app_to_launch_state_;
diff --git a/ash/system/video_conference/video_conference_tray_controller.h b/ash/system/video_conference/video_conference_tray_controller.h index a3a1a7c..a085d0b 100644 --- a/ash/system/video_conference/video_conference_tray_controller.h +++ b/ash/system/video_conference/video_conference_tray_controller.h
@@ -88,7 +88,7 @@ void UpdateWithMediaState(VideoConferenceMediaState state); // Handles device usage from a VC app while the device is system disabled. - void HandleDeviceUsedWhileDisabled( + virtual void HandleDeviceUsedWhileDisabled( crosapi::mojom::VideoConferenceMediaDevice device, const std::u16string& app_name);
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc index 9313d6e..386a4aed 100644 --- a/ash/wallpaper/wallpaper_controller_impl.cc +++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -581,9 +581,6 @@ {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) { DCHECK(!color_profiles_.empty()); - calculated_colors_ = WallpaperCalculatedColors( - std::vector<SkColor>(color_profiles_.size(), kInvalidWallpaperColor), - kInvalidWallpaperColor); Shell::Get()->window_tree_host_manager()->AddObserver(this); Shell::Get()->AddShellObserver(this); theme_observation_.Observe(ui::NativeTheme::GetInstanceForNativeUi()); @@ -629,14 +626,19 @@ SkColor WallpaperControllerImpl::GetProminentColor( ColorProfile color_profile) const { + if (!calculated_colors_) { + return kInvalidWallpaperColor; + } + ColorProfileType type = GetColorProfileType(color_profile); size_t index = static_cast<size_t>(type); - DCHECK_LT(index, calculated_colors_.prominent_colors.size()); - return calculated_colors_.prominent_colors[index]; + DCHECK_LT(index, calculated_colors_->prominent_colors.size()); + return calculated_colors_->prominent_colors[index]; } SkColor WallpaperControllerImpl::GetKMeanColor() const { - return calculated_colors_.k_mean_color; + return calculated_colors_ ? calculated_colors_->k_mean_color + : kInvalidWallpaperColor; } gfx::ImageSkia WallpaperControllerImpl::GetWallpaper() const { @@ -1621,18 +1623,18 @@ } void WallpaperControllerImpl::OnColorCalculationComplete( + const WallpaperInfo& info, const WallpaperCalculatedColors& wallpaper_calculated_colors) { - const AccountId account_id = GetActiveAccountId(); + // Since we delete `color_calculator_` in `ShowWallpaperImage()`, + // `current_wallpaper_` should always be the same as the wallpaper for which + // color computation has been completed in production. + DCHECK(current_wallpaper_->wallpaper_info().MatchesAsset(info)); // Use |WallpaperInfo::location| as the key for storing |prominent_colors_| in // the |kWallpaperColors| pref. - // TODO(crbug.com/787134): The |prominent_colors_| of wallpapers with empty - // location should be cached as well. - // TODO(skau): This does not guarantee that the current wallpaper is the same - // wallpaper for which the colors were calculated. pref_manager_->CacheProminentColors( - account_id, wallpaper_calculated_colors.prominent_colors); - pref_manager_->CacheKMeanColor(account_id, + info.location, wallpaper_calculated_colors.prominent_colors); + pref_manager_->CacheKMeanColor(info.location, wallpaper_calculated_colors.k_mean_color); SetCalculatedColors(wallpaper_calculated_colors); @@ -2584,6 +2586,8 @@ void WallpaperControllerImpl::SetCalculatedColors( const WallpaperCalculatedColors& calculated_colors) { + // Observers should be notified if this is the first call to + // `SetCalculatedColors` no matter what. if (calculated_colors == calculated_colors_) { return; } @@ -2627,9 +2631,9 @@ color_calculator_ = std::make_unique<WallpaperColorCalculator>( GetWallpaper(), color_profiles_); - if (!color_calculator_->StartCalculation( - base::BindOnce(&WallpaperControllerImpl::OnColorCalculationComplete, - weak_factory_.GetWeakPtr()))) { + if (!color_calculator_->StartCalculation(base::BindOnce( + &WallpaperControllerImpl::OnColorCalculationComplete, + weak_factory_.GetWeakPtr(), current_wallpaper_->wallpaper_info()))) { ResetCalculatedColors(); } }
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h index a1b22eb..855ce9e 100644 --- a/ash/wallpaper/wallpaper_controller_impl.h +++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -129,7 +129,9 @@ // Returns the k mean color of the current wallpaper. SkColor GetKMeanColor() const; - const WallpaperCalculatedColors& calculated_colors() const { + // Returns the set of calculated colors. If the colors have not yet been + // calculated yet, returns an empty object. + const absl::optional<WallpaperCalculatedColors>& calculated_colors() const { return calculated_colors_; } @@ -626,8 +628,11 @@ // If an existing calculation is in progress it is destroyed. void CalculateWallpaperColors(); - // Callback to handle the completed color computation. - void OnColorCalculationComplete(const WallpaperCalculatedColors& colors); + // Callback to handle the completed color computation for the wallpaper + // matching `info`. Caches `colors` locally and saves the result to local + // state. + void OnColorCalculationComplete(const WallpaperInfo& info, + const WallpaperCalculatedColors& colors); // Returns false when the color extraction algorithm shouldn't be run based on // system state (e.g. wallpaper image, SessionState, etc.). @@ -787,8 +792,8 @@ std::unique_ptr<OnlineWallpaperVariantInfoFetcher> variant_info_fetcher_; // The calculated colors extracted from the current wallpaper. - // kInvalidWallpaperColor is used by default or if extracting colors fails. - WallpaperCalculatedColors calculated_colors_; + // Empty state is used to denote when colors have not yet been calculated. + absl::optional<WallpaperCalculatedColors> calculated_colors_; // Caches the color profiles that need to do wallpaper color extracting. const std::vector<color_utils::ColorProfile> color_profiles_;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index 9414fd8..360f01d 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -314,9 +314,28 @@ controller_->RemoveObserver(this); } + void SetOnResizeCallback(base::RepeatingClosure callback) { + resize_callback_ = callback; + } + + void SetOnColorsCalculatedCallback(base::RepeatingClosure callback) { + colors_calculated_callback_ = callback; + } + // WallpaperControllerObserver void OnWallpaperChanged() override { ++wallpaper_changed_count_; } - void OnWallpaperColorsChanged() override { ++colors_changed_count_; } + void OnWallpaperResized() override { + if (resize_callback_) { + resize_callback_.Run(); + } + } + void OnWallpaperColorsChanged() override { + ++colors_changed_count_; + + if (colors_calculated_callback_) { + colors_calculated_callback_.Run(); + } + } void OnWallpaperBlurChanged() override { ++blur_changed_count_; } void OnFirstWallpaperShown() override { ++first_shown_count_; } void OnWallpaperPreviewStarted() override { @@ -336,6 +355,10 @@ private: WallpaperController* controller_; + + base::RepeatingClosure resize_callback_; + base::RepeatingClosure colors_calculated_callback_; + int colors_changed_count_ = 0; int blur_changed_count_ = 0; int first_shown_count_ = 0; @@ -1033,6 +1056,54 @@ EXPECT_FALSE(ShouldCalculateColors()); } +TEST_F(WallpaperControllerTest, ColorsCalculatedForMostRecentWallpaper) { + TestWallpaperControllerObserver observer(controller_); + // Total size of image must be greater than 100 pixels to trigger the async + // codepath (and any potential cancellation). + const int dimension = 20; + + // Activate so we calculate colors. + SetSessionState(SessionState::ACTIVE); + + base::RunLoop run_loop; + observer.SetOnResizeCallback(run_loop.QuitClosure()); + // Sets the wallpaper to magenta. + const gfx::ImageSkia old_image = + CreateImage(dimension, dimension, kWallpaperColor); + WallpaperInfo old_info = CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH); + old_info.location = "old"; + controller_->ShowWallpaperImage(old_image, old_info, + /*preview_mode=*/false, + /*always_on_top=*/false); + // Run the controller until resize completes for the first wallpaper and + // color calculation starts. + run_loop.Run(); + observer.SetOnResizeCallback(base::NullCallback()); + + base::RunLoop colors_loop; + observer.SetOnColorsCalculatedCallback(colors_loop.QuitClosure()); + + // Immediately switch the wallpaper color to blue. + const gfx::ImageSkia image = CreateImage(dimension, dimension, SK_ColorBLUE); + WallpaperInfo info = CreateWallpaperInfo(WALLPAPER_LAYOUT_STRETCH); + // Set location to somethind different than in `old_info`. + info.location = "new"; + + controller_->ShowWallpaperImage(image, info, + /*preview_mode=*/false, + /*always_on_top=*/false); + + // Run until we get a notification of colors changed. + colors_loop.Run(); + + // There should only be one color change event if we interrupted the first + // attempt. + EXPECT_EQ(observer.colors_changed_count(), 1); + EXPECT_EQ(controller_->calculated_colors()->k_mean_color, SK_ColorBLUE); + EXPECT_FALSE(pref_manager_->GetCachedKMeanColor("old")); + EXPECT_TRUE(pref_manager_->GetCachedKMeanColor("new")); +} + TEST_F(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) { TestWallpaperControllerObserver observer(controller_); EXPECT_EQ(0, observer.colors_changed_count()); @@ -1057,9 +1128,9 @@ const std::vector<SkColor> prominent_colors = {SK_ColorGREEN, SK_ColorRED, SK_ColorBLUE, SK_ColorWHITE, SK_ColorWHITE, SK_ColorWHITE}; - pref_manager_->CacheProminentColors(kAccountId1, prominent_colors); + pref_manager_->CacheProminentColors(relative_path.value(), prominent_colors); const SkColor k_means_color = SK_ColorLTGRAY; - pref_manager_->CacheKMeanColor(kAccountId1, k_means_color); + pref_manager_->CacheKMeanColor(relative_path.value(), k_means_color); // Reset to login screen. GetSessionControllerClient()->RequestSignOut(); @@ -1094,9 +1165,9 @@ const std::vector<SkColor> prominent_colors = {SK_ColorGREEN, SK_ColorRED, SK_ColorBLUE, SK_ColorWHITE, SK_ColorWHITE, SK_ColorWHITE}; - pref_manager_->CacheProminentColors(kAccountId1, prominent_colors); + pref_manager_->CacheProminentColors(relative_path.value(), prominent_colors); const SkColor k_means_color = SK_ColorLTGRAY; - pref_manager_->CacheKMeanColor(kAccountId1, k_means_color); + pref_manager_->CacheKMeanColor(relative_path.value(), k_means_color); // Set a wallpaper for account 2. WallpaperInfo info2 = InfoWithType(WallpaperType::kDefault); @@ -1131,6 +1202,26 @@ } TEST_F(WallpaperControllerTest, + OnWallpaperColorsChangedAlwaysCalledOnFirstUpdate) { + TestWallpaperControllerObserver observer(controller_); + controller_->ShowUserWallpaper(kAccountId1, + user_manager::UserType::USER_TYPE_REGULAR); + task_environment()->RunUntilIdle(); + + // Even though the wallpaper color is invalid, observers should still be + // notified for the first update. + EXPECT_EQ(observer.colors_changed_count(), 1); + + controller_->ShowUserWallpaper(kAccountId2, + user_manager::UserType::USER_TYPE_REGULAR); + task_environment()->RunUntilIdle(); + + // Observers should not be notified after the first update if the colors do + // not change. + EXPECT_EQ(observer.colors_changed_count(), 1); +} + +TEST_F(WallpaperControllerTest, UpdatePrimaryUserWallpaperWhileSecondUserActive) { SetBypassDecode(); WallpaperInfo wallpaper_info;
diff --git a/ash/wallpaper/wallpaper_pref_manager.cc b/ash/wallpaper/wallpaper_pref_manager.cc index a907934f..1a07b3ee 100644 --- a/ash/wallpaper/wallpaper_pref_manager.cc +++ b/ash/wallpaper/wallpaper_pref_manager.cc
@@ -365,26 +365,19 @@ return absl::nullopt; } - void CacheProminentColors(const AccountId& account_id, + void CacheProminentColors(base::StringPiece location, const std::vector<SkColor>& colors) override { - WallpaperInfo old_info; - if (!GetLocalWallpaperInfo(account_id, &old_info)) { + if (location.empty()) { return; } - // TODO(crbug.com/787134): A blank key cannot be used as a key. This should - // be fixed (with a key that will not collide). - if (old_info.location.empty()) - return; - ScopedDictPrefUpdate wallpaper_colors_update(local_state_, prefs::kWallpaperColors); base::Value::List wallpaper_colors; for (SkColor color : colors) wallpaper_colors.Append(static_cast<double>(color)); base::Value wallpaper_colors_value(std::move(wallpaper_colors)); - wallpaper_colors_update->Set(old_info.location, - std::move(wallpaper_colors_value)); + wallpaper_colors_update->Set(location, std::move(wallpaper_colors_value)); } void RemoveProminentColors(const AccountId& account_id) override { @@ -401,7 +394,6 @@ absl::optional<std::vector<SkColor>> GetCachedProminentColors( const base::StringPiece location) const override { - // TODO(crbug.com/787134): When we can handle blank keys, remove this. if (location.empty()) return absl::nullopt; @@ -420,9 +412,9 @@ return cached_colors_out; } - void CacheKMeanColor(const AccountId& account_id, + void CacheKMeanColor(base::StringPiece location, SkColor k_mean_color) override { - CacheSingleColor(prefs::kWallpaperMeanColors, account_id, k_mean_color); + CacheSingleColor(prefs::kWallpaperMeanColors, location, k_mean_color); } absl::optional<SkColor> GetCachedKMeanColor( @@ -434,9 +426,9 @@ RemoveCachedColor(prefs::kWallpaperMeanColors, account_id); } - void CacheCelebiColor(const AccountId& account_id, + void CacheCelebiColor(base::StringPiece location, SkColor celebi_color) override { - CacheSingleColor(prefs::kWallpaperCelebiColors, account_id, celebi_color); + CacheSingleColor(prefs::kWallpaperCelebiColors, location, celebi_color); } absl::optional<SkColor> GetCelebiColor( const base::StringPiece location) const override { @@ -541,20 +533,15 @@ private: // Caches a single `color` in the dictionary for `pref_name`. void CacheSingleColor(const std::string& pref_name, - const AccountId& account_id, + base::StringPiece location, SkColor color) { - WallpaperInfo old_info; - if (!GetLocalWallpaperInfo(account_id, &old_info)) { - return; - } - // Blank keys are not allowed and will not be stored. - if (old_info.location.empty()) { + if (location.empty()) { return; } ScopedDictPrefUpdate color_dict(local_state_, pref_name); - color_dict->Set(old_info.location, static_cast<double>(color)); + color_dict->Set(location, static_cast<double>(color)); } // Returns the cached color for `location` in `pref_name` if it can be found.
diff --git a/ash/wallpaper/wallpaper_pref_manager.h b/ash/wallpaper/wallpaper_pref_manager.h index 5d33b04..9beab68 100644 --- a/ash/wallpaper/wallpaper_pref_manager.h +++ b/ash/wallpaper/wallpaper_pref_manager.h
@@ -127,7 +127,7 @@ virtual absl::optional<WallpaperCalculatedColors> GetCachedWallpaperColors( base::StringPiece location) const = 0; - virtual void CacheProminentColors(const AccountId& account_id, + virtual void CacheProminentColors(base::StringPiece location, const std::vector<SkColor>& colors) = 0; virtual void RemoveProminentColors(const AccountId& account_id) = 0; @@ -137,7 +137,7 @@ virtual absl::optional<std::vector<SkColor>> GetCachedProminentColors( const base::StringPiece location) const = 0; - virtual void CacheKMeanColor(const AccountId& account_id, + virtual void CacheKMeanColor(base::StringPiece location, SkColor k_mean_color) = 0; // Returns the cached KMeans color value for the wallpaper at `location`. @@ -147,7 +147,7 @@ virtual void RemoveKMeanColor(const AccountId& account_id) = 0; // Cache the prominent color sampled with the 'Celebi' algorithm. - virtual void CacheCelebiColor(const AccountId& account_id, + virtual void CacheCelebiColor(base::StringPiece location, SkColor celebi_color) = 0; // Returns the cached celebi color for the wallpaper at `location`. virtual absl::optional<SkColor> GetCelebiColor(
diff --git a/ash/wallpaper/wallpaper_pref_manager_unittest.cc b/ash/wallpaper/wallpaper_pref_manager_unittest.cc index b14d6d1c..82859de02 100644 --- a/ash/wallpaper/wallpaper_pref_manager_unittest.cc +++ b/ash/wallpaper/wallpaper_pref_manager_unittest.cc
@@ -375,53 +375,49 @@ } TEST_F(WallpaperPrefManagerTest, CacheProminentColors) { - profile_helper_->RegisterPrefsForAccount(account_id_1); - WallpaperInfo info = InfoWithType(WallpaperType::kCustomized); const char location[] = "/test/location"; info.location = location; - EXPECT_TRUE(pref_manager_->SetUserWallpaperInfo(account_id_1, info)); - const std::vector<SkColor> expected_colors = { SK_ColorGREEN, SK_ColorGREEN, SK_ColorGREEN, SkColorSetRGB(0xAB, 0xBC, 0xEF)}; - pref_manager_->CacheProminentColors(account_id_1, expected_colors); + pref_manager_->CacheProminentColors(location, expected_colors); EXPECT_EQ(expected_colors, *pref_manager_->GetCachedProminentColors(location)); } TEST_F(WallpaperPrefManagerTest, CacheKMeansColor) { - profile_helper_->RegisterPrefsForAccount(account_id_1); - + WallpaperInfo info = InfoWithType(WallpaperType::kCustomized); const char location[] = "/test/location"; - StoreWallpaper(account_id_1, location); + info.location = location; const SkColor expected_color = SkColorSetRGB(0xAB, 0xBC, 0xEF); - pref_manager_->CacheKMeanColor(account_id_1, expected_color); + pref_manager_->CacheKMeanColor(location, expected_color); EXPECT_EQ(expected_color, *pref_manager_->GetCachedKMeanColor(location)); } TEST_F(WallpaperPrefManagerTest, RemoveKMeansColor) { profile_helper_->RegisterPrefsForAccount(account_id_1); + WallpaperInfo info = InfoWithType(WallpaperType::kCustomized); const char location[] = "/test/location"; + info.location = location; + StoreWallpaper(account_id_1, location); - pref_manager_->CacheKMeanColor(account_id_1, SkColorSetRGB(0xFF, 0xFF, 0xFF)); + pref_manager_->CacheKMeanColor(location, SkColorSetRGB(0xFF, 0xFF, 0xFF)); pref_manager_->RemoveKMeanColor(account_id_1); EXPECT_FALSE(pref_manager_->GetCachedKMeanColor(location)); } TEST_F(WallpaperPrefManagerTest, CacheCelebiColor) { - profile_helper_->RegisterPrefsForAccount(account_id_1); - const char location[] = "/test/location"; - StoreWallpaper(account_id_1, location); const SkColor expected_color = SkColorSetRGB(0xAB, 0xBC, 0xEF); - pref_manager_->CacheCelebiColor(account_id_1, expected_color); + pref_manager_->CacheCelebiColor(location, expected_color); + absl::optional<SkColor> color = pref_manager_->GetCelebiColor(location); ASSERT_TRUE(color); EXPECT_EQ(expected_color, *color); @@ -430,30 +426,26 @@ TEST_F(WallpaperPrefManagerTest, RemoveCelebiColor) { profile_helper_->RegisterPrefsForAccount(account_id_1); const char location[] = "/test/location"; + + pref_manager_->CacheCelebiColor(location, SkColorSetRGB(0xFF, 0xFF, 0xFF)); + StoreWallpaper(account_id_1, location); - pref_manager_->CacheCelebiColor(account_id_1, - SkColorSetRGB(0xFF, 0xFF, 0xFF)); pref_manager_->RemoveCelebiColor(account_id_1); EXPECT_FALSE(pref_manager_->GetCelebiColor(location)); } TEST_F(WallpaperPrefManagerTest, SetCalculatedColors) { const char location[] = "location"; - WallpaperInfo info = InfoWithType(WallpaperType::kCustomized); - info.location = location; - - // Set current wallpaper - pref_manager_->SetUserWallpaperInfo(account_id_1, info); // Cache a prominent and KMean color entry const std::vector<SkColor> prominent_colors = { SK_ColorGREEN, SK_ColorGREEN, SK_ColorGREEN, SkColorSetRGB(0xAB, 0xBC, 0xEF)}; - pref_manager_->CacheProminentColors(account_id_1, prominent_colors); + pref_manager_->CacheProminentColors(location, prominent_colors); const SkColor k_mean_color = SkColorSetRGB(0xAB, 0xBC, 0xEF); - pref_manager_->CacheKMeanColor(account_id_1, k_mean_color); + pref_manager_->CacheKMeanColor(location, k_mean_color); absl::optional<WallpaperCalculatedColors> actual_colors = pref_manager_->GetCachedWallpaperColors(location); @@ -465,15 +457,11 @@ TEST_F(WallpaperPrefManagerTest, CalculatedColorsEmptyIfKMeanMissing) { const char location[] = "location"; - WallpaperInfo info = InfoWithType(WallpaperType::kCustomized); - info.location = location; - - pref_manager_->SetUserWallpaperInfo(account_id_1, info); const std::vector<SkColor> prominent_colors = { SK_ColorGREEN, SK_ColorGREEN, SK_ColorGREEN, SkColorSetRGB(0xAB, 0xBC, 0xEF)}; - pref_manager_->CacheProminentColors(account_id_1, prominent_colors); + pref_manager_->CacheProminentColors(location, prominent_colors); EXPECT_FALSE(pref_manager_->GetCachedWallpaperColors(location)); }
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc index b39cec8..ec1b9096 100644 --- a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc +++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
@@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/threading/thread_restrictions.h" +#include "base/time/time.h" #include "third_party/skia/include/core/SkImage.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/image/image_skia_rep.h" @@ -124,9 +125,8 @@ void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) { image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap); - UMA_HISTOGRAM_TIMES("Ash.Wallpaper.TimeSpentResizing", - base::TimeTicks::Now() - start_calculation_time_); - + DVLOG(2) << __func__ << " size=" << image_.size().ToString() + << " time=" << base::TimeTicks::Now() - start_calculation_time_; for (auto& observer : observers_) observer.OnWallpaperResized(); }
diff --git a/ash/webui/color_internals/wallpaper_colors_handler_impl.cc b/ash/webui/color_internals/wallpaper_colors_handler_impl.cc index 9c3de33..32a02c1 100644 --- a/ash/webui/color_internals/wallpaper_colors_handler_impl.cc +++ b/ash/webui/color_internals/wallpaper_colors_handler_impl.cc
@@ -35,8 +35,12 @@ void WallpaperColorsHandlerImpl::OnWallpaperColorsChanged() { DCHECK(observer_remote_.is_bound()); - observer_remote_->OnWallpaperColorsChanged( - Shell::Get()->wallpaper_controller()->calculated_colors()); + const auto& calculated_colors = + Shell::Get()->wallpaper_controller()->calculated_colors(); + if (!calculated_colors.has_value()) { + return; + } + observer_remote_->OnWallpaperColorsChanged(*calculated_colors); } } // namespace ash
diff --git a/ash/webui/eche_app_ui/eche_signaler_unittest.cc b/ash/webui/eche_app_ui/eche_signaler_unittest.cc index 8b20a08..9c881061 100644 --- a/ash/webui/eche_app_ui/eche_signaler_unittest.cc +++ b/ash/webui/eche_app_ui/eche_signaler_unittest.cc
@@ -416,7 +416,10 @@ base::HistogramTester histograms; mojo::PendingRemote<mojom::SignalingMessageObserver> observer; FakeObserver fake_observer(&observer, &task_runner_); - proto::ExoMessage message = getResponseMessage("123", "network", false); + FakeSystemInfoProvider fake_system_info_provider; + proto::ExoMessage message = getResponseMessage( + "123", "3009be769fb8f956e8413ee9f3e0836e34968bc40457d0a10c549d2edcf00cc1", + false); SetConnectionStatus(secure_channel::ConnectionManager::Status::kConnected); histograms.ExpectUniqueSample( @@ -424,6 +427,7 @@ EcheTray::ConnectionFailReason::kSignalingHasLateResponse, 0); signaler_->SetSignalingMessageObserver(std::move(observer)); + signaler_->SetSystemInfoProvider(&fake_system_info_provider); signaler_->OnMessageReceived(message.SerializeAsString()); task_runner_.WaitForResult(); signaler_->RecordSignalingTimeout();
diff --git a/ash/webui/eche_app_ui/system_info_provider_unittest.cc b/ash/webui/eche_app_ui/system_info_provider_unittest.cc index 88ddb3c5..dc86086f 100644 --- a/ash/webui/eche_app_ui/system_info_provider_unittest.cc +++ b/ash/webui/eche_app_ui/system_info_provider_unittest.cc
@@ -30,7 +30,7 @@ const bool kFakeMeasureLatency = false; const bool kFakeSendStartSignaling = true; const bool kFakeDisableStunServer = false; -const bool kFakeCheckAndroidNetworkInfo = false; +const bool kFakeCheckAndroidNetworkInfo = true; void ParseJson(const std::string& json, std::string& device_name,
diff --git a/ash/webui/personalization_app/mojom/personalization_app.mojom b/ash/webui/personalization_app/mojom/personalization_app.mojom index 4809683..8271845 100644 --- a/ash/webui/personalization_app/mojom/personalization_app.mojom +++ b/ash/webui/personalization_app/mojom/personalization_app.mojom
@@ -100,6 +100,9 @@ // Latest modification timestamp used to sort albums. mojo_base.mojom.Time timestamp; + + // Whether the album is a shared album. + bool is_shared; }; // Represents the server-provided response to a Google Photos albums request.
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 3effdbc..c70562054 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -250,6 +250,8 @@ {"googlePhotosLabel", IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS}, {"googlePhotosError", IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ERROR}, {"googlePhotosTryAgain", IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_TRY_AGAIN}, + {"googlePhotosAlbumShared", + IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUM_SHARED}, {"googlePhotosAlbumsTabLabel", IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUMS_TAB}, {"googlePhotosPhotosTabLabel",
diff --git a/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.ts b/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.ts index 4691782..4dc9ac40 100644 --- a/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.ts +++ b/ash/webui/personalization_app/resources/js/personalization_breadcrumb_element.ts
@@ -25,7 +25,8 @@ import {getTemplate} from './personalization_breadcrumb_element.html.js'; import {isPathValid, Paths, PersonalizationRouter} from './personalization_router_element.js'; import {WithPersonalizationStore} from './personalization_store.js'; -import {inBetween, isNonEmptyArray, isNonEmptyString} from './utils.js'; +import {inBetween, isNonEmptyArray} from './utils.js'; +import {findAlbumById} from './wallpaper/utils.js'; /** Event interface for dom-repeat. */ interface RepeaterEvent extends CustomEvent { @@ -85,7 +86,7 @@ breadcrumbs_: { type: Array, computed: - 'computeBreadcrumbs_(path, collections_, collectionId, googlePhotosAlbums_, googlePhotosAlbumId, topicSource)', + 'computeBreadcrumbs_(path, collections_, collectionId, albums_, albumsShared_, googlePhotosAlbumId, topicSource)', }, collections_: { @@ -93,7 +94,10 @@ }, /** The list of Google Photos albums. */ - googlePhotosAlbums_: Array, + albums_: Array, + + /** The list of shared Google Photos albums. */ + albumsShared_: Array, /** The breadcrumb being highlighted by keyboard navigation. */ selectedBreadcrumb_: { @@ -109,7 +113,8 @@ path: string; private breadcrumbs_: string[]; private collections_: WallpaperCollection[]|null; - private googlePhotosAlbums_: GooglePhotosAlbum[]|null; + private albums_: GooglePhotosAlbum[]|null; + private albumsShared_: GooglePhotosAlbum[]|null; private selectedBreadcrumb_: HTMLElement; override ready() { @@ -120,8 +125,9 @@ override connectedCallback() { super.connectedCallback(); this.watch('collections_', state => state.wallpaper.backdrop.collections); + this.watch('albums_', state => state.wallpaper.googlePhotos.albums); this.watch( - 'googlePhotosAlbums_', state => state.wallpaper.googlePhotos.albums); + 'albumsShared_', state => state.wallpaper.googlePhotos.albumsShared); this.updateFromStore(); } @@ -183,14 +189,15 @@ case Paths.GOOGLE_PHOTOS_COLLECTION: breadcrumbs.push(this.i18n('wallpaperLabel')); breadcrumbs.push(this.i18n('googlePhotosLabel')); - if (isNonEmptyString(this.googlePhotosAlbumId) && - isNonEmptyArray(this.googlePhotosAlbums_)) { - const googlePhotosAlbum = this.googlePhotosAlbums_.find( - googlePhotosAlbum => - googlePhotosAlbum.id === this.googlePhotosAlbumId); - if (googlePhotosAlbum) { - breadcrumbs.push(googlePhotosAlbum.title); - } + const googlePhotosAlbum = + findAlbumById(this.googlePhotosAlbumId, this.albums_) ?? + findAlbumById(this.googlePhotosAlbumId, this.albumsShared_); + if (googlePhotosAlbum) { + breadcrumbs.push(googlePhotosAlbum.title); + } else if (this.googlePhotosAlbumId) { + console.warn( + 'Can\'t find a matching album with id:', + this.googlePhotosAlbumId); } break; case Paths.LOCAL_COLLECTION:
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_albums_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_albums_element.ts index 74bf3f1a..09be3fec 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_albums_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_albums_element.ts
@@ -309,7 +309,8 @@ /** Returns the secondary text to display for the specified |album|. */ private getSecondaryText_(album: GooglePhotosAlbum): string { - return getCountText(album.photoCount); + return album.isShared ? this.i18n('googlePhotosAlbumShared') : + getCountText(album.photoCount); } /** Returns whether the specified |album| is a placeholder. */
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_photos_by_album_id_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_photos_by_album_id_element.ts index 12aadc9..877cbfa7 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/google_photos_photos_by_album_id_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/google_photos_photos_by_album_id_element.ts
@@ -25,7 +25,7 @@ import {DisplayableImage} from './constants.js'; import {recordWallpaperGooglePhotosSourceUMA, WallpaperGooglePhotosSource} from './google_photos_metrics_logger.js'; import {getTemplate} from './google_photos_photos_by_album_id_element.html.js'; -import {getLoadingPlaceholders, isGooglePhotosPhoto, isImageAMatchForKey, isImageEqualToSelected} from './utils.js'; +import {findAlbumById, getLoadingPlaceholders, isGooglePhotosPhoto, isImageAMatchForKey, isImageEqualToSelected} from './utils.js'; import {fetchGooglePhotosAlbum, selectWallpaper} from './wallpaper_controller.js'; import {WallpaperGridItemSelectedEvent} from './wallpaper_grid_item_element.js'; import {getWallpaperProvider} from './wallpaper_interface_provider.js'; @@ -71,7 +71,8 @@ value: getPlaceholders, }, - albums: Array, + albums_: Array, + albumsShared_: Array, currentSelected_: Object, pendingSelected_: Object, photosByAlbumId_: Object, @@ -87,7 +88,7 @@ static get observers() { return [ - 'onAlbumIdOrAlbumsOrPhotosByAlbumIdChanged_(albumId, albums_, photosByAlbumId_)', + 'onAlbumIdOrAlbumsOrPhotosByAlbumIdChanged_(albumId, albums_, albumsShared_, photosByAlbumId_)', 'onAlbumIdOrPhotosByAlbumIdResumeTokensChanged_(albumId, photosByAlbumIdResumeTokens_)', ]; } @@ -101,9 +102,12 @@ /** The list of photos for the currently selected album id. */ private album_: GooglePhotosPhoto[]; - /** The list of albums. */ + /** The list of Google Photos albums. */ private albums_: GooglePhotosAlbum[]|null|undefined; + /** The list of shared Google Photos albums. */ + private albumsShared_: GooglePhotosAlbum[]|null|undefined; + /** The currently selected wallpaper. */ private currentSelected_: CurrentWallpaper|null; @@ -132,6 +136,8 @@ this.watch<GooglePhotosPhotosByAlbumId['albums_']>( 'albums_', state => state.wallpaper.googlePhotos.albums); + this.watch<GooglePhotosPhotosByAlbumId['albumsShared_']>( + 'albumsShared_', state => state.wallpaper.googlePhotos.albumsShared); this.watch<GooglePhotosPhotosByAlbumId['currentSelected_']>( 'currentSelected_', state => state.wallpaper.currentSelected); this.watch<GooglePhotosPhotosByAlbumId['pendingSelected_']>( @@ -208,6 +214,7 @@ private onAlbumIdOrAlbumsOrPhotosByAlbumIdChanged_( albumId: GooglePhotosPhotosByAlbumId['albumId'], albums: GooglePhotosPhotosByAlbumId['albums_'], + albumsShared: GooglePhotosPhotosByAlbumId['albumsShared_'], photosByAlbumId: GooglePhotosPhotosByAlbumId['photosByAlbumId_']) { // If no album is currently selected there is nothing to display. if (!albumId) { @@ -219,8 +226,9 @@ // been set, there is nothing to display except placeholders. This occurs // if the user refreshes the wallpaper app while its navigated to a Google // Photos album. - if (!Array.isArray(albums) || !albums.some(album => album.id === albumId) || - !photosByAlbumId) { + const matchingAlbum = + findAlbumById(albumId, albums) ?? findAlbumById(albumId, albumsShared); + if (!matchingAlbum || !photosByAlbumId) { this.album_ = getPlaceholders(); return; }
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/utils.ts b/ash/webui/personalization_app/resources/js/wallpaper/utils.ts index a75e36f8..ec5e2d7 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/utils.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/utils.ts
@@ -7,8 +7,8 @@ import {assert} from 'chrome://resources/js/assert_ts.js'; import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js'; -import {CurrentWallpaper, GooglePhotosPhoto, WallpaperImage, WallpaperLayout, WallpaperType} from '../personalization_app.mojom-webui.js'; -import {getNumberOfGridItemsPerRow} from '../utils.js'; +import {CurrentWallpaper, GooglePhotosAlbum, GooglePhotosPhoto, WallpaperImage, WallpaperLayout, WallpaperType} from '../personalization_app.mojom-webui.js'; +import {getNumberOfGridItemsPerRow, isNonEmptyArray, isNonEmptyString} from '../utils.js'; import {DefaultImageSymbol, DisplayableImage, kDefaultImageSymbol} from './constants.js'; @@ -137,3 +137,16 @@ // Add a key query parameter to cache bust when the image changes. return `/wallpaper.jpg?key=${encodeURIComponent(image.key)}`; } + +/** + * Finds and returns a Google Photos album from albums list with a matching id. + * Returns null in case invalid id or albums list or no album is found. + */ +export function findAlbumById( + albumId: string|undefined, + albums: GooglePhotosAlbum[]|null|undefined): GooglePhotosAlbum|null { + if (isNonEmptyString(albumId) && isNonEmptyArray(albums)) { + return albums.find(album => album.id === albumId) ?? null; + } + return null; +}
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_reducers.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_reducers.ts index c75c3a5..2b448d5 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_reducers.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_reducers.ts
@@ -12,7 +12,7 @@ import {isImageDataUrl, isNonEmptyArray} from '../utils.js'; import {DefaultImageSymbol, kDefaultImageSymbol} from './constants.js'; -import {isDefaultImage, isFilePath} from './utils.js'; +import {findAlbumById, isDefaultImage, isFilePath} from './utils.js'; import {WallpaperActionName} from './wallpaper_actions.js'; import {DailyRefreshType, WallpaperState} from './wallpaper_state.js'; @@ -416,17 +416,24 @@ case WallpaperActionName.BEGIN_LOAD_GOOGLE_PHOTOS_ALBUM: // The list of photos for an album should be loaded only while additional // photos exist. - assert(!!state.albums); - assert(state.albums.some(album => album.id === action.albumId)); + assert( + findAlbumById(action.albumId, state.albums) || + findAlbumById(action.albumId, state.albumsShared), + 'No matching album id found in Google Photos albums.'); assert( !state.photosByAlbumId[action.albumId] || - state.resumeTokens.photosByAlbumId[action.albumId]); + state.resumeTokens.photosByAlbumId[action.albumId], + 'No photos available in the given Google Photos album.'); return state; case WallpaperActionName.APPEND_GOOGLE_PHOTOS_ALBUM: - assert(!!state.albums); - assert(state.albums.some(album => album.id === action.albumId)); - assert(action.albumId !== undefined); - assert(action.photos !== undefined); + assert(action.albumId !== undefined, 'Album id is undefined.'); + assert( + action.photos !== undefined, + 'List of Google Photos photos is undefined.'); + assert( + findAlbumById(action.albumId, state.albums) || + findAlbumById(action.albumId, state.albumsShared), + 'No matching album id found in Google Photos albums.'); // Case: First batch of photos. if (!Array.isArray(state.photosByAlbumId[action.albumId])) { return {
diff --git a/ash/wm/desks/desk_preview_view.cc b/ash/wm/desks/desk_preview_view.cc index 28b8976..2c12488e 100644 --- a/ash/wm/desks/desk_preview_view.cc +++ b/ash/wm/desks/desk_preview_view.cc
@@ -32,7 +32,6 @@ #include "base/containers/flat_set.h" #include "base/cxx17_backports.h" #include "base/ranges/algorithm.h" -#include "chromeos/ui/wm/features.h" #include "ui/accessibility/ax_node_data.h" #include "ui/aura/client/aura_constants.h" #include "ui/compositor/layer.h" @@ -396,11 +395,8 @@ // If there is a floated window that belongs to this desk, since it doesn't // belong to `desk_container`, we need to add it separately. - aura::Window* floated_window = nullptr; - if (chromeos::wm::features::IsFloatWindowEnabled() && - (floated_window = - Shell::Get()->float_controller()->FindFloatedWindowOfDesk( - mini_view_->desk()))) { + aura::Window* floated_window = window_util::GetFloatedWindowForActiveDesk(); + if (floated_window) { GetLayersData(floated_window, &layers_data); }
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc index c8b028b..9d36d52 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc
@@ -30,7 +30,6 @@ #include "base/i18n/rtl.h" #include "base/metrics/user_metrics.h" #include "chromeos/ui/base/window_properties.h" -#include "chromeos/ui/wm/features.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/wm/core/coordinate_conversion.h" @@ -453,12 +452,10 @@ // Do not enable back gesture if `screen_location` is inside the tuck handle, // let `FloatController` handle the event instead. - if (chromeos::wm::features::IsFloatWindowEnabled()) { + if (aura::Window* floated_window = + window_util::GetFloatedWindowForActiveDesk()) { auto* float_controller = Shell::Get()->float_controller(); - auto* floated_window = float_controller->FindFloatedWindowOfDesk( - DesksController::Get()->GetTargetActiveDesk()); - if (floated_window && - float_controller->IsFloatedWindowTuckedForTablet(floated_window)) { + if (float_controller->IsFloatedWindowTuckedForTablet(floated_window)) { auto* tuck_handle_widget = float_controller->GetTuckHandleWidget(floated_window); if (tuck_handle_widget &&
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 3b7e039..855a13af 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -647,12 +647,9 @@ bool should_animate_item = animate; // If we're in entering overview process, not all window items in the grid // might need animation even if the grid needs animation. - if (animate && transition == OverviewTransition::kEnter) - should_animate_item = window_item->should_animate_when_entering(); - if (animate && transition == OverviewTransition::kEnter) { - if (window_item->should_animate_when_entering() && - !has_non_cover_animating) { + should_animate_item = window_item->should_animate_when_entering(); + if (should_animate_item && !has_non_cover_animating) { has_non_cover_animating |= !CanCoverAvailableWorkspace(window_item->GetWindow()); ++animate_count;
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index dabc937..d2be976b 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -375,16 +375,18 @@ base::ScopedClosureRunner at_exit_runner(base::BindOnce( [](base::WeakPtr<OverviewItem> item, OverviewAnimationType animation_type) { - if (!item.get()) + if (!item.get()) { return; + } // Shadow is normally set after an animation is finished. In the case of // no animations, manually set the shadow. Shadow relies on both the // window transform and `item_widget_`'s new bounds so set it after // `SetItemBounds()` and `UpdateHeaderLayout()`. Do not apply the shadow // for drop target. - if (animation_type == OVERVIEW_ANIMATION_NONE) + if (animation_type == OVERVIEW_ANIMATION_NONE) { item->UpdateRoundedCornersAndShadow(); + } if (RoundedLabelWidget* widget = item->cannot_snap_widget_.get()) { SetWidgetBoundsAndMaybeAnimateTransform( @@ -487,7 +489,13 @@ // launcher. if (new_animation_type == OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER) { overview_item_view_->SetHeaderVisibility( - OverviewItemView::HeaderVisibility::kVisible); + OverviewItemView::HeaderVisibility::kVisible, /*animate=*/true); + } + + // Update the item header visibility immediately without an animation. + if (new_animation_type == OVERVIEW_ANIMATION_NONE) { + overview_item_view_->SetHeaderVisibility( + OverviewItemView::HeaderVisibility::kVisible, /*animate=*/false); } } @@ -609,7 +617,8 @@ overview_item_view_->SetHeaderVisibility( is_being_dragged_ ? OverviewItemView::HeaderVisibility::kInvisible - : OverviewItemView::HeaderVisibility::kCloseButtonInvisibleOnly); + : OverviewItemView::HeaderVisibility::kCloseButtonInvisibleOnly, + /*animate=*/true); } void OverviewItem::OnSelectorItemDragEnded(bool snap) { @@ -618,7 +627,7 @@ overview_item_view_->HideCloseInstantlyAndThenShowItSlowly(); } else { overview_item_view_->SetHeaderVisibility( - OverviewItemView::HeaderVisibility::kVisible); + OverviewItemView::HeaderVisibility::kVisible, /*animate=*/true); } is_being_dragged_ = false; } @@ -819,7 +828,7 @@ // Fade the title in if minimized. The rest of |item_widget_| should // already be shown. overview_item_view_->SetHeaderVisibility( - OverviewItemView::HeaderVisibility::kVisible); + OverviewItemView::HeaderVisibility::kVisible, /*animate=*/true); } else { FadeInWidgetToOverview(item_widget_.get(), OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, @@ -1307,7 +1316,15 @@ base::Unretained(this)), GetWindow(), transform_window_.IsMinimized())); item_widget_->Show(); - item_widget_->SetOpacity(0.f); + if (overview_session_ && + (overview_session_->enter_exit_overview_type() == + OverviewEnterExitType::kImmediateEnter || + overview_session_->enter_exit_overview_type() == + OverviewEnterExitType::kImmediateEnterWithoutFocus)) { + item_widget_->SetOpacity(1.f); + } else { + item_widget_->SetOpacity(0.f); + } widget_layer->SetMasksToBounds(false); }
diff --git a/ash/wm/overview/overview_item_view.cc b/ash/wm/overview/overview_item_view.cc index 26d279a..9405f93 100644 --- a/ash/wm/overview/overview_item_view.cc +++ b/ash/wm/overview/overview_item_view.cc
@@ -108,19 +108,26 @@ OverviewItemView::~OverviewItemView() = default; -void OverviewItemView::SetHeaderVisibility(HeaderVisibility visibility) { +void OverviewItemView::SetHeaderVisibility(HeaderVisibility visibility, + bool animate) { DCHECK(header_view()->layer()); - if (visibility == current_header_visibility_) + if (visibility == current_header_visibility_) { return; + } const HeaderVisibility previous_visibility = current_header_visibility_; current_header_visibility_ = visibility; const bool all_invisible = visibility == HeaderVisibility::kInvisible; - AnimateLayerOpacity(header_view()->layer(), !all_invisible); + if (animate) { + AnimateLayerOpacity(header_view()->layer(), !all_invisible); + } else { + header_view()->layer()->SetOpacity(all_invisible ? 0.f : 1.f); + } // If there is not a `close_button_`, then we are done. - if (!close_button_) + if (!close_button_) { return; + } // If the whole header is fading out and there is a `close_button_`, then // we need to disable the close button without also fading the close button. @@ -132,8 +139,9 @@ const bool close_button_visible = visibility == HeaderVisibility::kVisible; // If `header_view()` was hidden and is fading in, set the opacity and enabled // state of `close_button_` depending on whether the close button should fade - // in with `header_view()` or stay hidden. - if (previous_visibility == HeaderVisibility::kInvisible) { + // in with `header_view()` or stay hidden. Or show the close button + // immediately if we are not animating. + if (previous_visibility == HeaderVisibility::kInvisible || !animate) { close_button_->layer()->SetOpacity(close_button_visible ? 1.f : 0.f); close_button_->SetEnabled(close_button_visible); return;
diff --git a/ash/wm/overview/overview_item_view.h b/ash/wm/overview/overview_item_view.h index 0b15977b..c8a4a56 100644 --- a/ash/wm/overview/overview_item_view.h +++ b/ash/wm/overview/overview_item_view.h
@@ -38,8 +38,8 @@ kVisible, }; - // If |show_preview| is true, this class will contain a child view which - // mirrors |window|. + // If `show_preview` is true, this class will contain a child view which + // mirrors `window`. OverviewItemView(OverviewItem* overview_item, views::Button::PressedCallback close_callback, aura::Window* window, @@ -48,23 +48,24 @@ OverviewItemView& operator=(const OverviewItemView&) = delete; ~OverviewItemView() override; - // Fades the app icon and title out if |visibility| is kInvisible, in - // otherwise. If |close_button_| is not null, also fades the close button in - // if |visibility| is kVisible, out otherwise. Sets - // |current_header_visibility_| to |visibility|. - void SetHeaderVisibility(HeaderVisibility visibility); + // Fades the app icon and title out if `visibility` is kInvisible, in + // otherwise. If `close_button_` is not null, also fades the close button in + // if `visibility` is kVisible, out otherwise. Sets + // `current_header_visibility_` to `visibility`. Fades in if `animate` is + // true, otherwise shows immediately. + void SetHeaderVisibility(HeaderVisibility visibility, bool animate); // Hides the close button instantaneously, and then fades it in slowly and - // with a long delay. Sets |current_header_visibility_| to kVisible. Assumes - // that |close_button_| is not null, and that |current_header_visibility_| is + // with a long delay. Sets `current_header_visibility_` to kVisible. Assumes + // that `close_button_` is not null, and that `current_header_visibility_` is // not kInvisible. void HideCloseInstantlyAndThenShowItSlowly(); - // Called when |overview_item_| is about to be restored to its original state + // Called when `overview_item_` is about to be restored to its original state // outside of overview. void OnOverviewItemWindowRestoring(); - // Refreshes |preview_view_| so that its content is up-to-date. Used by tab + // Refreshes `preview_view_` so that its content is up-to-date. Used by tab // dragging. void RefreshPreviewView(); @@ -97,7 +98,7 @@ private: // The OverviewItem which owns the widget which houses this view. Non-null - // until |OnOverviewItemWindowRestoring| is called. + // until `OnOverviewItemWindowRestoring` is called. OverviewItem* overview_item_; CloseButton* close_button_;
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc index bfa9949..f50e0cd 100644 --- a/ash/wm/overview/overview_window_drag_controller.cc +++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -36,7 +36,6 @@ #include "base/functional/callback_helpers.h" #include "base/metrics/histogram_functions.h" #include "base/numerics/safe_conversions.h" -#include "chromeos/ui/wm/features.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" @@ -1020,20 +1019,15 @@ } void OverviewWindowDragController::MaybeCreateFloatDragHelper() { - if (!chromeos::wm::features::IsFloatWindowEnabled()) { + auto* float_window = window_util::GetFloatedWindowForActiveDesk(); + DCHECK(item_); + // If the float window is dragged, it will be on top of everything as + // expected. + if (!float_window || item_->GetWindow() == float_window) { return; } - if (auto* float_window = - Shell::Get()->float_controller()->FindFloatedWindowOfDesk( - DesksController::Get()->active_desk())) { - DCHECK(item_); - // If the float window is dragged, it will be on top of everything as - // expected. - if (item_->GetWindow() != float_window) { - float_drag_helper_ = std::make_unique<ScopedFloatDragHelper>(this); - } - } + float_drag_helper_ = std::make_unique<ScopedFloatDragHelper>(this); } void OverviewWindowDragController::DestroyFloatDragHelper() {
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc index c3c4319d..fc3c057 100644 --- a/ash/wm/window_util.cc +++ b/ash/wm/window_util.cc
@@ -34,6 +34,7 @@ #include "base/ranges/algorithm.h" #include "chromeos/ui/base/chromeos_ui_constants.h" #include "chromeos/ui/frame/interior_resize_handler_targeter.h" +#include "chromeos/ui/wm/features.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/focus_client.h" @@ -364,6 +365,17 @@ return nullptr; } +aura::Window* GetFloatedWindowForActiveDesk() { + if (!chromeos::wm::features::IsFloatWindowEnabled()) { + return nullptr; + } + + auto* float_controller = Shell::Get()->float_controller(); + DCHECK(float_controller); + return float_controller->FindFloatedWindowOfDesk( + DesksController::Get()->GetTargetActiveDesk()); +} + bool ShouldMinimizeTopWindowOnBack() { Shell* shell = Shell::Get(); // We never want to minimize the main app window in the Kiosk session.
diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h index a9c45e42..8baf002 100644 --- a/ash/wm/window_util.h +++ b/ash/wm/window_util.h
@@ -125,6 +125,9 @@ aura::Window* GetTopWindow(); aura::Window* GetTopNonFloatedWindow(); +// Returns the floated window for the active desk if it exists. +ASH_EXPORT aura::Window* GetFloatedWindowForActiveDesk(); + // Returns whether the top window should be minimized on back action. ASH_EXPORT bool ShouldMinimizeTopWindowOnBack();
diff --git a/base/BUILD.gn b/base/BUILD.gn index 29344e6..1f0e5cc5 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1277,8 +1277,8 @@ "mac/dispatch_source_mach.h", "mac/foundation_util.h", "mac/foundation_util.mm", - "mac/launch_services_util.h", - "mac/launch_services_util.mm", + "mac/launch_application.h", + "mac/launch_application.mm", "mac/launchd.cc", "mac/launchd.h", "mac/mac_logging.h", @@ -3699,6 +3699,7 @@ if (is_ios) { sources += [ "ios/device_util_unittest.mm", + "ios/scoped_critical_action_unittest.mm", "ios/weak_nsobject_unittest.mm", ]
diff --git a/base/allocator/partition_alloc_support.cc b/base/allocator/partition_alloc_support.cc index c554cad..4c5733d0 100644 --- a/base/allocator/partition_alloc_support.cc +++ b/base/allocator/partition_alloc_support.cc
@@ -468,7 +468,7 @@ // We are looking for the callers of the function releasing the raw_ptr and // freeing memory: const StringPiece callees[] = { - "internal::BackupRefPtrImpl<>::ReleaseInternal()", + "internal::RawPtrBackupRefImpl<>::ReleaseInternal()", "internal::PartitionFree()", "base::(anonymous namespace)::FreeFn()", };
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn index c3064d9..a7f33df 100644 --- a/base/allocator/partition_allocator/BUILD.gn +++ b/base/allocator/partition_allocator/BUILD.gn
@@ -373,7 +373,23 @@ "pointers/raw_ptr_exclusion.h", "pointers/raw_ref.h", ] - sources = [ "pointers/raw_ptr.cc" ] + sources = [] + if (enable_backup_ref_ptr_support) { + sources += [ + "pointers/raw_ptr_backup_ref_impl.cc", + "pointers/raw_ptr_backup_ref_impl.h", + ] + } else if (use_hookable_raw_ptr) { + sources += [ + "pointers/raw_ptr_hookable_impl.cc", + "pointers/raw_ptr_hookable_impl.h", + ] + } else if (use_asan_unowned_ptr) { + sources += [ + "pointers/raw_ptr_asan_unowned_impl.cc", + "pointers/raw_ptr_asan_unowned_impl.h", + ] + } if (use_partition_alloc) { public_deps = [ ":partition_alloc" ] }
diff --git a/base/allocator/partition_allocator/partition_alloc.gni b/base/allocator/partition_allocator/partition_alloc.gni index ebbe4767..f19b8ec 100644 --- a/base/allocator/partition_allocator/partition_alloc.gni +++ b/base/allocator/partition_allocator/partition_alloc.gni
@@ -55,7 +55,7 @@ declare_args() { # Build support for Use-after-Free protection via BackupRefPtr (BRP) or - # MTECheckedPtr, and switch the raw_ptr<T> implementation to BackupRefPtrImpl + # MTECheckedPtr, and switch the raw_ptr<T> implementation to RawPtrBackupRefImpl # and MTECheckedPtrImp, respectively. They're mutually exclusive. # # These are effective only for memory allocated from PartitionAlloc, so it is @@ -129,8 +129,7 @@ # to go through build_overrides enable_dangling_raw_ptr_perf_experiment = false - # TODO(bartekn): Enabled temporarily, disable before reaches Beta. - backup_ref_ptr_poison_oob_ptr = enable_backup_ref_ptr_support + backup_ref_ptr_poison_oob_ptr = false } declare_args() { @@ -208,15 +207,15 @@ assert(!enable_backup_ref_ptr_support || !use_asan_unowned_ptr, "Both BackupRefPtr and AsanUnownedPtr can't be enabled at the same time") -# HookableRawPtrImpl and BackupRefPtr are mutually exclusive variants of raw_ptr. +# RawPtrHookableImpl and BackupRefPtr are mutually exclusive variants of raw_ptr. assert( !use_hookable_raw_ptr || !enable_backup_ref_ptr_support, - "Both HookableRawPtrImpl and BackupRefPtr can't be enabled at the same time") + "Both RawPtrHookableImpl and BackupRefPtr can't be enabled at the same time") -# HookableRawPtrImpl and AsanUnownedPtr are mutually exclusive variants of raw_ptr. +# RawPtrHookableImpl and AsanUnownedPtr are mutually exclusive variants of raw_ptr. assert( !use_hookable_raw_ptr || !use_asan_unowned_ptr, - "Both HookableRawPtrImpl and AsanUnownedPtr can't be enabled at the same time") + "Both RawPtrHookableImpl and AsanUnownedPtr can't be enabled at the same time") assert(!use_asan_backup_ref_ptr || is_asan, "AsanBackupRefPtr requires AddressSanitizer") @@ -231,7 +230,7 @@ "AsanBackupRefPtr is not supported outside Chromium") assert(!use_asan_backup_ref_ptr || use_hookable_raw_ptr, - "AsanBackupRefPtr requires HookableRawPtrImpl") + "AsanBackupRefPtr requires RawPtrHookableImpl") declare_args() { enable_pkeys = is_linux && target_cpu == "x64"
diff --git a/base/allocator/partition_allocator/partition_ref_count.h b/base/allocator/partition_allocator/partition_ref_count.h index d0adf12a..ec0f4df 100644 --- a/base/allocator/partition_allocator/partition_ref_count.h +++ b/base/allocator/partition_allocator/partition_ref_count.h
@@ -25,7 +25,7 @@ #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) -// Special-purpose atomic reference count class used by BackupRefPtrImpl. +// Special-purpose atomic reference count class used by RawPtrBackupRefImpl. // The least significant bit of the count is reserved for tracking the liveness // state of an allocation: it's set when the allocation is created and cleared // on free(). So the count can be:
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr.cc b/base/allocator/partition_allocator/pointers/raw_ptr.cc deleted file mode 100644 index f7233eda..0000000 --- a/base/allocator/partition_allocator/pointers/raw_ptr.cc +++ /dev/null
@@ -1,201 +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 "base/allocator/partition_allocator/pointers/raw_ptr.h" -#include <cstdint> - -#include "base/allocator/partition_allocator/dangling_raw_ptr_checks.h" -#include "base/allocator/partition_allocator/partition_alloc_buildflags.h" - -// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under -// allocator/partition_allocator/ to be built. -#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - -#include "base/allocator/partition_allocator/partition_alloc.h" -#include "base/allocator/partition_allocator/partition_alloc_base/check.h" -#include "base/allocator/partition_allocator/partition_ref_count.h" -#include "base/allocator/partition_allocator/partition_root.h" -#include "base/allocator/partition_allocator/reservation_offset_table.h" - -namespace base::internal { - -template <bool AllowDangling> -void BackupRefPtrImpl<AllowDangling>::AcquireInternal(uintptr_t address) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); -#endif - uintptr_t slot_start = - partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); - if constexpr (AllowDangling) { - partition_alloc::internal::PartitionRefCountPointer(slot_start) - ->AcquireFromUnprotectedPtr(); - } else { - partition_alloc::internal::PartitionRefCountPointer(slot_start)->Acquire(); - } -} - -template <bool AllowDangling> -void BackupRefPtrImpl<AllowDangling>::ReleaseInternal(uintptr_t address) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); -#endif - uintptr_t slot_start = - partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); - if constexpr (AllowDangling) { - if (partition_alloc::internal::PartitionRefCountPointer(slot_start) - ->ReleaseFromUnprotectedPtr()) { - partition_alloc::internal::PartitionAllocFreeForRefCounting(slot_start); - } - } else { - if (partition_alloc::internal::PartitionRefCountPointer(slot_start) - ->Release()) { - partition_alloc::internal::PartitionAllocFreeForRefCounting(slot_start); - } - } -} - -template <bool AllowDangling> -void BackupRefPtrImpl<AllowDangling>::ReportIfDanglingInternal( - uintptr_t address) { - if (partition_alloc::internal::IsUnretainedDanglingRawPtrCheckEnabled()) { - if (IsSupportedAndNotNull(address)) { - uintptr_t slot_start = - partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); - partition_alloc::internal::PartitionRefCountPointer(slot_start) - ->ReportIfDangling(); - } - } -} - -template <bool AllowDangling> -bool BackupRefPtrImpl<AllowDangling>::IsPointeeAlive(uintptr_t address) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); -#endif - uintptr_t slot_start = - partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); - return partition_alloc::internal::PartitionRefCountPointer(slot_start) - ->IsAlive(); -} - -template <bool AllowDangling> -template <typename Z> -partition_alloc::PtrPosWithinAlloc -BackupRefPtrImpl<AllowDangling>::IsValidDelta( - uintptr_t address, - partition_alloc::internal::PtrDelta<Z> delta) { - return partition_alloc::internal::PartitionAllocIsValidPtrDelta(address, - delta); -} - -// Explicitly instantiates the two BackupRefPtr variants in the .cc. This -// ensures the definitions not visible from the .h are available in the binary. -template struct BackupRefPtrImpl</*AllowDangling=*/false>; -template struct BackupRefPtrImpl</*AllowDangling=*/true>; - -template PA_COMPONENT_EXPORT(RAW_PTR) - partition_alloc::PtrPosWithinAlloc BackupRefPtrImpl<false>::IsValidDelta( - uintptr_t, - partition_alloc::internal::PtrDelta<size_t>); -template PA_COMPONENT_EXPORT(RAW_PTR) - partition_alloc::PtrPosWithinAlloc BackupRefPtrImpl<false>::IsValidDelta( - uintptr_t, - partition_alloc::internal::PtrDelta<ptrdiff_t>); -template PA_COMPONENT_EXPORT(RAW_PTR) - partition_alloc::PtrPosWithinAlloc BackupRefPtrImpl<true>::IsValidDelta( - uintptr_t, - partition_alloc::internal::PtrDelta<size_t>); -template PA_COMPONENT_EXPORT(RAW_PTR) - partition_alloc::PtrPosWithinAlloc BackupRefPtrImpl<true>::IsValidDelta( - uintptr_t, - partition_alloc::internal::PtrDelta<ptrdiff_t>); - -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) -void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address) { - if (partition_alloc::internal::IsManagedByDirectMap(address)) { - uintptr_t reservation_start = - partition_alloc::internal::GetDirectMapReservationStart(address); - PA_BASE_CHECK(address - reservation_start >= - partition_alloc::PartitionPageSize()); - } else { - PA_BASE_CHECK(partition_alloc::internal::IsManagedByNormalBuckets(address)); - PA_BASE_CHECK(address % partition_alloc::kSuperPageSize >= - partition_alloc::PartitionPageSize()); - } -} -#endif // BUILDFLAG(PA_DCHECK_IS_ON) || - // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - -} // namespace base::internal - -#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - -#if BUILDFLAG(USE_ASAN_UNOWNED_PTR) - -#include <sanitizer/asan_interface.h> -#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" -#include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h" - -namespace base::internal { - -PA_NO_SANITIZE("address") -bool AsanUnownedPtrImpl::EndOfAliveAllocation(const volatile void* ptr) { - uintptr_t address = reinterpret_cast<uintptr_t>(ptr); - return __asan_region_is_poisoned(reinterpret_cast<void*>(address), 1) && - !__asan_region_is_poisoned(reinterpret_cast<void*>(address - 1), 1); -} - -bool AsanUnownedPtrImpl::LikelySmuggledScalar(const volatile void* ptr) { - intptr_t address = reinterpret_cast<intptr_t>(ptr); - return address < 0x4000; // Negative or small positive. -} - -} // namespace base::internal - -#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) - -#if BUILDFLAG(USE_HOOKABLE_RAW_PTR) -#include <atomic> - -namespace base::internal { - -namespace { - -void DefaultWrapPtrHook(uintptr_t address) {} -void DefaultReleaseWrappedPtrHook(uintptr_t address) {} -void DefaultUnwrapForDereferenceHook(uintptr_t address) {} -void DefaultUnwrapForExtractionHook(uintptr_t address) {} -void DefaultUnwrapForComparisonHook(uintptr_t address) {} -void DefaultAdvanceHook(uintptr_t old_address, uintptr_t new_address) {} -void DefaultDuplicateHook(uintptr_t address) {} - -constexpr RawPtrHooks default_hooks = { - DefaultWrapPtrHook, - DefaultReleaseWrappedPtrHook, - DefaultUnwrapForDereferenceHook, - DefaultUnwrapForExtractionHook, - DefaultUnwrapForComparisonHook, - DefaultAdvanceHook, - DefaultDuplicateHook, -}; - -} // namespace - -std::atomic<const RawPtrHooks*> g_hooks{&default_hooks}; - -const RawPtrHooks* GetRawPtrHooks() { - return g_hooks.load(std::memory_order_relaxed); -} - -void InstallRawPtrHooks(const RawPtrHooks* hooks) { - g_hooks.store(hooks, std::memory_order_relaxed); -} - -void ResetRawPtrHooks() { - InstallRawPtrHooks(&default_hooks); -} - -} // namespace base::internal - -#endif // BUILDFLAG(USE_HOOKABLE_RAW_PTR)
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr.h b/base/allocator/partition_allocator/pointers/raw_ptr.h index a8f38e2..2248a455 100644 --- a/base/allocator/partition_allocator/pointers/raw_ptr.h +++ b/base/allocator/partition_allocator/pointers/raw_ptr.h
@@ -25,21 +25,14 @@ #include "build/buildflag.h" #if PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) +#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" +#include "base/allocator/partition_allocator/partition_address_space.h" +#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/allocator/partition_allocator/partition_tag.h" #include "base/allocator/partition_allocator/partition_tag_types.h" #include "base/allocator/partition_allocator/tagging.h" #endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) -#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \ - PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) -// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under -// allocator/partition_allocator/ to be built. -#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" -#include "base/allocator/partition_allocator/partition_address_space.h" -#include "base/allocator/partition_allocator/partition_alloc_constants.h" -#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || - // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) - #if BUILDFLAG(IS_WIN) #include "base/allocator/partition_allocator/partition_alloc_base/win/win_handle_types.h" #endif @@ -65,6 +58,18 @@ #define PA_RAW_PTR_CHECK(condition) #endif // BUILDFLAG(USE_PARTITION_ALLOC) +#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#include "base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.h" +#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) + +#if BUILDFLAG(USE_ASAN_UNOWNED_PTR) +#include "base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.h" +#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) + +#if BUILDFLAG(USE_HOOKABLE_RAW_PTR) +#include "base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.h" +#endif // BUILDFLAG(USE_HOOKABLE_RAW_PTR) + namespace cc { class Scheduler; } @@ -511,602 +516,6 @@ #endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) -#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) -PA_COMPONENT_EXPORT(RAW_PTR) -void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address); -#endif - -template <bool AllowDangling = false> -struct BackupRefPtrImpl { - // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads - // modify the same smart pointer object without synchronization, a data race - // will occur. - - static PA_ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) { - // There are many situations where the compiler can prove that - // `ReleaseWrappedPtr` is called on a value that is always nullptr, but the - // way `IsManagedByPartitionAllocBRPPool` is written, the compiler can't - // prove that nullptr is not managed by PartitionAlloc; and so the compiler - // has to emit a useless check and dead code. To avoid that without making - // the runtime check slower, tell the compiler to skip - // `IsManagedByPartitionAllocBRPPool` when it can statically determine that - // address is nullptr. -#if PA_HAS_BUILTIN(__builtin_constant_p) - if (__builtin_constant_p(address == 0) && (address == 0)) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK( - !partition_alloc::IsManagedByPartitionAllocBRPPool(address)); -#endif // BUILDFLAG(PA_DCHECK_IS_ON) || - // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - return false; - } -#endif // PA_HAS_BUILTIN(__builtin_constant_p) - - // This covers the nullptr case, as address 0 is never in any - // PartitionAlloc pool. - bool is_in_brp_pool = - partition_alloc::IsManagedByPartitionAllocBRPPool(address); - - // There may be pointers immediately after the allocation, e.g. - // { - // // Assume this allocation happens outside of PartitionAlloc. - // raw_ptr<T> ptr = new T[20]; - // for (size_t i = 0; i < 20; i ++) { ptr++; } - // } - // - // Such pointers are *not* at risk of accidentally falling into BRP pool, - // because: - // 1) On 64-bit systems, BRP pool is preceded by a forbidden region. - // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP - // pool aren't considered to be part of that pool. - // - // This allows us to make a stronger assertion that if - // IsManagedByPartitionAllocBRPPool returns true for a valid pointer, - // it must be at least partition page away from the beginning of a super - // page. -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - if (is_in_brp_pool) { - CheckThatAddressIsntWithinFirstPartitionPage(address); - } -#endif - - return is_in_brp_pool; - } - -#if PA_CONFIG(USE_OOB_POISON) - // Out-Of-Bounds (OOB) poison bit is set when the pointer has overflowed by - // one byte. -#if defined(ARCH_CPU_X86_64) - // Bit 63 is the only pointer bit that will work as the poison bit across both - // LAM48 and LAM57. It also works when all unused linear address bits are - // checked for canonicality. - static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 63; -#else - // Avoid ARM's Top-Byte Ignore. - static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 55; -#endif - - template <typename T> - static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) { - return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) & - ~OOB_POISON_BIT); - } - - template <typename T> - static PA_ALWAYS_INLINE bool IsPtrOOB(T* ptr) { - return (reinterpret_cast<uintptr_t>(ptr) & OOB_POISON_BIT) == - OOB_POISON_BIT; - } - - template <typename T> - static PA_ALWAYS_INLINE T* PoisonOOBPtr(T* ptr) { - return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) | - OOB_POISON_BIT); - } -#else // PA_USE_OOB_POISON - template <typename T> - static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) { - return ptr; - } -#endif // PA_USE_OOB_POISON - - // Wraps a pointer. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { - uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(ptr)); - if (IsSupportedAndNotNull(address)) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK(ptr != nullptr); -#endif - AcquireInternal(address); - } else { -#if !PA_CONFIG(HAS_64_BITS_POINTERS) -#if PA_HAS_BUILTIN(__builtin_constant_p) - // Similarly to `IsSupportedAndNotNull` above, elide the - // `BanSuperPageFromBRPPool` call if the compiler can prove that `address` - // is zero since PA won't be able to map anything at that address anyway. - bool known_constant_zero = - __builtin_constant_p(address == 0) && (address == 0); -#else // PA_HAS_BUILTIN(__builtin_constant_p) - bool known_constant_zero = false; -#endif // PA_HAS_BUILTIN(__builtin_constant_p) - - if (!known_constant_zero) { - partition_alloc::internal::AddressPoolManagerBitmap:: - BanSuperPageFromBRPPool(address); - } -#endif // !PA_CONFIG(HAS_64_BITS_POINTERS) - } - - return ptr; - } - - // Notifies the allocator when a wrapped pointer is being removed or replaced. - template <typename T> - static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { - uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr)); - if (IsSupportedAndNotNull(address)) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - PA_BASE_CHECK(wrapped_ptr != nullptr); -#endif - ReleaseInternal(address); - } - // We are unable to counteract BanSuperPageFromBRPPool(), called from - // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if - // there's more than one associated raw_ptr<T> at a given time. The risk of - // exhausting the entire address space is minuscule, therefore, we couldn't - // resist the perf gain of a single relaxed store (in the above mentioned - // function) over much more expensive two CAS operations, which we'd have to - // use if we were to un-ban a super-page. - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function is allowed to crash on nullptr. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { -#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) -#if PA_CONFIG(USE_OOB_POISON) - PA_BASE_CHECK(!IsPtrOOB(wrapped_ptr)); -#endif - uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr); - if (IsSupportedAndNotNull(address)) { - PA_BASE_CHECK(wrapped_ptr != nullptr); - PA_BASE_CHECK(IsPointeeAlive(address)); - } -#endif // BUILDFLAG(PA_DCHECK_IS_ON) || - // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) - return wrapped_ptr; - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function must handle nullptr gracefully. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { - T* unpoisoned_ptr = UnpoisonPtr(wrapped_ptr); -#if PA_CONFIG(USE_OOB_POISON) - // Some code uses invalid pointer values as indicators, so those values must - // be passed through unchanged during extraction. The following check will - // pass invalid values through if those values do not fall within the BRP - // pool after being unpoisoned. - if (!IsSupportedAndNotNull(partition_alloc::UntagPtr(unpoisoned_ptr))) { - return wrapped_ptr; - } - // Poison-based OOB checks do not extend to extracted pointers. The - // alternative of retaining poison on extracted pointers could introduce new - // OOB conditions, e.g., in code that extracts an end-of-allocation pointer - // for use in a loop termination condition. The poison bit would make that - // pointer appear to reference a very high address. -#endif // PA_CONFIG(USE_OOB_POISON) - return unpoisoned_ptr; - } - - // Unwraps the pointer, without making an assertion on whether memory was - // freed or not. - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { - // This may be used for unwrapping an end-of-allocation pointer to be used - // as an endpoint in an iterative algorithm, so this removes the OOB poison - // bit. - return UnpoisonPtr(wrapped_ptr); - } - - // Upcasts the wrapped pointer. - template <typename To, typename From> - static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { - static_assert(std::is_convertible<From*, To*>::value, - "From must be convertible to To."); - // Note, this cast may change the address if upcasting to base that lies in - // the middle of the derived object. - return wrapped_ptr; - } - - // Advance the wrapped pointer by `delta_elems`. - template < - typename T, - typename Z, - typename = - std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> - static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { -#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) - T* unpoisoned_ptr = UnpoisonPtr(wrapped_ptr); - T* new_ptr = unpoisoned_ptr + delta_elems; - // First check if the new address didn't migrate in/out the BRP pool, and - // that it lands within the same allocation. An end-of-allocation address is - // ok, too, and that may lead to the pointer being poisoned if the relevant - // feature is enabled. These checks add a non-trivial cost, but they're - // cheaper and more secure than the previous implementation that rewrapped - // the pointer (wrapped the new pointer and unwrapped the old one). - // - // Note, the value of these checks goes beyond OOB protection. They're - // important for integrity of the BRP algorithm. Without these, an attacker - // could make the pointer point to another allocation, and cause its - // ref-count to go to 0 upon this pointer's destruction, even though there - // may be another pointer still pointing to it, thus making it lose the BRP - // protection prematurely. - uintptr_t address = partition_alloc::UntagPtr(unpoisoned_ptr); - // TODO(bartekn): Consider adding support for non-BRP pools too (without - // removing the cross-pool migration check). - if (IsSupportedAndNotNull(address)) { - auto ptr_pos_within_alloc = IsValidDelta( - address, delta_elems * static_cast<Z>(sizeof(T)), sizeof(T)); - // No need to check that |new_ptr| is in the same pool, as IsValidDeta() - // checks that it's within the same allocation, so must be the same pool. - PA_BASE_CHECK(ptr_pos_within_alloc != - partition_alloc::PtrPosWithinAlloc::kFarOOB); -#if PA_CONFIG(USE_OOB_POISON) - if (ptr_pos_within_alloc == - partition_alloc::PtrPosWithinAlloc::kAllocEnd) { - new_ptr = PoisonOOBPtr(new_ptr); - } -#endif - } else { - // Check that the new address didn't migrate into the BRP pool, as it - // would result in more pointers pointing to an allocation than its - // ref-count reflects. - PA_BASE_CHECK(!IsSupportedAndNotNull(partition_alloc::UntagPtr(new_ptr))); - } - return new_ptr; -#else // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) - // In the "before allocation" mode, on 32-bit, we can run into a problem - // that the end-of-allocation address could fall outside of - // PartitionAlloc's pools, if this is the last slot of the super page, - // thus pointing to the guard page. This means the ref-count won't be - // decreased when the pointer is released (leak). - // - // We could possibly solve it in a few different ways: - // - Add the trailing guard page to the pool, but we'd have to think very - // hard if this doesn't create another hole. - // - Add an address adjustment to "is in pool?" check, similar as the one in - // PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to - // mention adding an extra instruction to an inlined hot path. - // - Let the leak happen, since it should a very rare condition. - // - Go back to the previous solution of rewrapping the pointer, but that - // had an issue of losing BRP protection in case the pointer ever gets - // shifted back before the end of allocation. - // - // We decided to cross that bridge once we get there... if we ever get - // there. Currently there are no plans to switch back to the "before - // allocation" mode. - // - // This problem doesn't exist in the "previous slot" mode, or any mode that - // involves putting extras after the allocation, because the - // end-of-allocation address belongs to the same slot. - static_assert(false); -#endif // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) - } - - template <typename T> - static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, - T* wrapped_ptr2) { - T* unpoisoned_ptr1 = UnpoisonPtr(wrapped_ptr1); - T* unpoisoned_ptr2 = UnpoisonPtr(wrapped_ptr2); - uintptr_t address1 = partition_alloc::UntagPtr(unpoisoned_ptr1); - uintptr_t address2 = partition_alloc::UntagPtr(unpoisoned_ptr2); - // Ensure that both pointers are within the same slot, and pool! - // TODO(bartekn): Consider adding support for non-BRP pool too. - if (IsSupportedAndNotNull(address1)) { - PA_BASE_CHECK(IsSupportedAndNotNull(address2)); - PA_BASE_CHECK(IsValidDelta(address2, address1 - address2, sizeof(T)) != - partition_alloc::PtrPosWithinAlloc::kFarOOB); - } else { - PA_BASE_CHECK(!IsSupportedAndNotNull(address2)); - } - return unpoisoned_ptr1 - unpoisoned_ptr2; - } - - // Returns a copy of a wrapped pointer, without making an assertion on whether - // memory was freed or not. - // This method increments the reference count of the allocation slot. - template <typename T> - static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { - return WrapRawPtr(wrapped_ptr); - } - - // Report the current wrapped pointer if pointee isn't alive anymore. - template <typename T> - static PA_ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) { - ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr)); - } - - // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used - // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { - return WrapRawPtr(ptr); - } - - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { - return UnpoisonPtr(wrapped_ptr); - } - - // This is for accounting only, used by unit tests. - static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} - static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} - static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} - - private: - // We've evaluated several strategies (inline nothing, various parts, or - // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark - // to measure performance. The best results were obtained when only the - // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined. - // Therefore, we've extracted the rest into the functions below and marked - // them as PA_NOINLINE to prevent unintended LTO effects. - static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE - void AcquireInternal(uintptr_t address); - static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE - void ReleaseInternal(uintptr_t address); - static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE - bool IsPointeeAlive(uintptr_t address); - static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE - void ReportIfDanglingInternal(uintptr_t address); - template < - typename Z, - typename = - std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> - static PA_ALWAYS_INLINE partition_alloc::PtrPosWithinAlloc - IsValidDelta(uintptr_t address, Z delta_in_bytes, size_t type_size) { - using delta_t = std::conditional_t<std::is_signed_v<Z>, ptrdiff_t, size_t>; - partition_alloc::internal::PtrDelta<delta_t> ptr_delta(delta_in_bytes, - type_size); - - return IsValidDelta(address, ptr_delta); - } - template <typename Z> - static PA_COMPONENT_EXPORT(RAW_PTR) - PA_NOINLINE partition_alloc::PtrPosWithinAlloc - IsValidDelta(uintptr_t address, - partition_alloc::internal::PtrDelta<Z> delta); -}; - -#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - -#if BUILDFLAG(USE_ASAN_UNOWNED_PTR) - -struct AsanUnownedPtrImpl { - // Wraps a pointer. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { - return ptr; - } - - // Notifies the allocator when a wrapped pointer is being removed or replaced. - template <typename T> - static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { - ProbeForLowSeverityLifetimeIssue(wrapped_ptr); - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function is allowed to crash on nullptr. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { - // ASAN will catch use of dereferenced ptr without additional probing. - return wrapped_ptr; - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function must handle nullptr gracefully. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { - ProbeForLowSeverityLifetimeIssue(wrapped_ptr); - return wrapped_ptr; - } - - // Unwraps the pointer, without making an assertion on whether memory was - // freed or not. - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { - return wrapped_ptr; - } - - // Upcasts the wrapped pointer. - template <typename To, typename From> - static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { - static_assert(std::is_convertible<From*, To*>::value, - "From must be convertible to To."); - // Note, this cast may change the address if upcasting to base that lies in - // the middle of the derived object. - return wrapped_ptr; - } - - // Advance the wrapped pointer by `delta_elems`. - template < - typename T, - typename Z, - typename = - std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> - static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { - return wrapped_ptr + delta_elems; - } - - template <typename T> - static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, - T* wrapped_ptr2) { - return wrapped_ptr1 - wrapped_ptr2; - } - - // Returns a copy of a wrapped pointer, without making an assertion on whether - // memory was freed or not. - template <typename T> - static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { - return wrapped_ptr; - } - - template <typename T> - static void ProbeForLowSeverityLifetimeIssue(T* wrapped_ptr) { - if (wrapped_ptr && !LikelySmuggledScalar(wrapped_ptr) && - !EndOfAliveAllocation(wrapped_ptr)) { - reinterpret_cast<const volatile uint8_t*>(wrapped_ptr)[0]; - } - } - - static bool EndOfAliveAllocation(const volatile void* ptr); - static bool LikelySmuggledScalar(const volatile void* ptr); - - // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used - // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { - return ptr; - } - - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { - return wrapped_ptr; - } - - // This is for accounting only, used by unit tests. - static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} - static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} - static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} -}; - -#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) - -#if BUILDFLAG(USE_HOOKABLE_RAW_PTR) - -struct RawPtrHooks { - using WrapPtr = void(uintptr_t address); - using ReleaseWrappedPtr = void(uintptr_t address); - using SafelyUnwrapForDereference = void(uintptr_t address); - using SafelyUnwrapForExtraction = void(uintptr_t address); - using UnsafelyUnwrapForComparison = void(uintptr_t address); - using Advance = void(uintptr_t old_address, uintptr_t new_address); - using Duplicate = void(uintptr_t address); - - WrapPtr* wrap_ptr; - ReleaseWrappedPtr* release_wrapped_ptr; - SafelyUnwrapForDereference* safely_unwrap_for_dereference; - SafelyUnwrapForExtraction* safely_unwrap_for_extraction; - UnsafelyUnwrapForComparison* unsafely_unwrap_for_comparison; - Advance* advance; - Duplicate* duplicate; -}; - -PA_COMPONENT_EXPORT(RAW_PTR) const RawPtrHooks* GetRawPtrHooks(); -PA_COMPONENT_EXPORT(RAW_PTR) void InstallRawPtrHooks(const RawPtrHooks*); -PA_COMPONENT_EXPORT(RAW_PTR) void ResetRawPtrHooks(); - -struct RawPtrHookableImpl { - // Wraps a pointer. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { - GetRawPtrHooks()->wrap_ptr(reinterpret_cast<uintptr_t>(ptr)); - return ptr; - } - - // Notifies the allocator when a wrapped pointer is being removed or replaced. - template <typename T> - static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) { - GetRawPtrHooks()->release_wrapped_ptr(reinterpret_cast<uintptr_t>(ptr)); - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function is allowed to crash on nullptr. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { - GetRawPtrHooks()->safely_unwrap_for_dereference( - reinterpret_cast<uintptr_t>(wrapped_ptr)); - return wrapped_ptr; - } - - // Unwraps the pointer, while asserting that memory hasn't been freed. The - // function must handle nullptr gracefully. - template <typename T> - static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { - GetRawPtrHooks()->safely_unwrap_for_extraction( - reinterpret_cast<uintptr_t>(wrapped_ptr)); - return wrapped_ptr; - } - - // Unwraps the pointer, without making an assertion on whether memory was - // freed or not. - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { - GetRawPtrHooks()->unsafely_unwrap_for_comparison( - reinterpret_cast<uintptr_t>(wrapped_ptr)); - return wrapped_ptr; - } - - // Upcasts the wrapped pointer. - template <typename To, typename From> - static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { - static_assert(std::is_convertible<From*, To*>::value, - "From must be convertible to To."); - // Note, this cast may change the address if upcasting to base that lies in - // the middle of the derived object. - return wrapped_ptr; - } - - // Advance the wrapped pointer by `delta_elems`. - template < - typename T, - typename Z, - typename = - std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> - static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { - GetRawPtrHooks()->advance( - reinterpret_cast<uintptr_t>(wrapped_ptr), - reinterpret_cast<uintptr_t>(wrapped_ptr + delta_elems)); - return wrapped_ptr + delta_elems; - } - - template <typename T> - static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, - T* wrapped_ptr2) { - return wrapped_ptr1 - wrapped_ptr2; - } - - // Returns a copy of a wrapped pointer, without making an assertion on whether - // memory was freed or not. - template <typename T> - static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { - GetRawPtrHooks()->duplicate(reinterpret_cast<uintptr_t>(wrapped_ptr)); - return wrapped_ptr; - } - - // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used - // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. - template <typename T> - static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { - return ptr; - } - - template <typename T> - static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { - return wrapped_ptr; - } - - // This is for accounting only, used by unit tests. - static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} - static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} - static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} -}; - -#endif // BUILDFLAG(USE_HOOKABLE_RAW_PTR) - // Wraps a raw_ptr/raw_ref implementation, with a class of the same interface // that provides accounting, for test purposes. raw_ptr/raw_ref that use it // perform extra bookkeeping, e.g. to track the number of times the raw_ptr is @@ -1282,7 +691,7 @@ // UnderlyingImpl is the struct that provides the implementation of the // protections related to raw_ptr. #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) - using UnderlyingImpl = internal::BackupRefPtrImpl< + using UnderlyingImpl = internal::RawPtrBackupRefImpl< /*AllowDangling=*/Traits::kMayDangle>; #elif BUILDFLAG(USE_ASAN_UNOWNED_PTR) using UnderlyingImpl = @@ -1290,7 +699,7 @@ // No special bookkeeping required for this case, // just treat these as ordinary pointers. internal::RawPtrNoOpImpl, - internal::AsanUnownedPtrImpl>; + internal::RawPtrAsanUnownedImpl>; #elif PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) using UnderlyingImpl = std::conditional_t<Traits::kDisableMTECheckedPtr,
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.cc b/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.cc new file mode 100644 index 0000000..c00b915 --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.cc
@@ -0,0 +1,26 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.h" + +#include <sanitizer/asan_interface.h> +#include <cstdint> + +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" + +namespace base::internal { + +PA_NO_SANITIZE("address") +bool RawPtrAsanUnownedImpl::EndOfAliveAllocation(const volatile void* ptr) { + uintptr_t address = reinterpret_cast<uintptr_t>(ptr); + return __asan_region_is_poisoned(reinterpret_cast<void*>(address), 1) && + !__asan_region_is_poisoned(reinterpret_cast<void*>(address - 1), 1); +} + +bool RawPtrAsanUnownedImpl::LikelySmuggledScalar(const volatile void* ptr) { + intptr_t address = reinterpret_cast<intptr_t>(ptr); + return address < 0x4000; // Negative or small positive. +} + +} // namespace base::internal
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.h b/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.h new file mode 100644 index 0000000..4fe1884e --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_asan_unowned_impl.h
@@ -0,0 +1,122 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_ASAN_UNOWNED_IMPL_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_ASAN_UNOWNED_IMPL_H_ + +#include <stddef.h> + +#include <type_traits> + +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" +#include "base/allocator/partition_allocator/partition_alloc_buildflags.h" +#include "base/allocator/partition_allocator/partition_alloc_forward.h" + +#if !BUILDFLAG(USE_ASAN_UNOWNED_PTR) +#error "Included under wrong build option" +#endif + +namespace base::internal { + +struct RawPtrAsanUnownedImpl { + // Wraps a pointer. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { + ProbeForLowSeverityLifetimeIssue(wrapped_ptr); + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { + // ASAN will catch use of dereferenced ptr without additional probing. + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { + ProbeForLowSeverityLifetimeIssue(wrapped_ptr); + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by `delta_elems`. + template < + typename T, + typename Z, + typename = + std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> + static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { + return wrapped_ptr + delta_elems; + } + + template <typename T> + static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, + T* wrapped_ptr2) { + return wrapped_ptr1 - wrapped_ptr2; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { + return wrapped_ptr; + } + + template <typename T> + static void ProbeForLowSeverityLifetimeIssue(T* wrapped_ptr) { + if (wrapped_ptr && !LikelySmuggledScalar(wrapped_ptr) && + !EndOfAliveAllocation(wrapped_ptr)) { + reinterpret_cast<const volatile uint8_t*>(wrapped_ptr)[0]; + } + } + + static bool EndOfAliveAllocation(const volatile void* ptr); + static bool LikelySmuggledScalar(const volatile void* ptr); + + // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used + // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { + return ptr; + } + + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { + return wrapped_ptr; + } + + // This is for accounting only, used by unit tests. + static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} + static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} + static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} +}; + +} // namespace base::internal + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_ASAN_UNOWNED_IMPL_H_
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.cc b/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.cc new file mode 100644 index 0000000..63b5c85 --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.cc
@@ -0,0 +1,126 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.h" + +#include <cstdint> + +#include "base/allocator/partition_allocator/dangling_raw_ptr_checks.h" +#include "base/allocator/partition_allocator/partition_alloc.h" +#include "base/allocator/partition_allocator/partition_alloc_base/check.h" +#include "base/allocator/partition_allocator/partition_alloc_buildflags.h" +#include "base/allocator/partition_allocator/partition_ref_count.h" +#include "base/allocator/partition_allocator/partition_root.h" +#include "base/allocator/partition_allocator/reservation_offset_table.h" + +namespace base::internal { + +template <bool AllowDangling> +void RawPtrBackupRefImpl<AllowDangling>::AcquireInternal(uintptr_t address) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); +#endif + uintptr_t slot_start = + partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); + if constexpr (AllowDangling) { + partition_alloc::internal::PartitionRefCountPointer(slot_start) + ->AcquireFromUnprotectedPtr(); + } else { + partition_alloc::internal::PartitionRefCountPointer(slot_start)->Acquire(); + } +} + +template <bool AllowDangling> +void RawPtrBackupRefImpl<AllowDangling>::ReleaseInternal(uintptr_t address) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); +#endif + uintptr_t slot_start = + partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); + if constexpr (AllowDangling) { + if (partition_alloc::internal::PartitionRefCountPointer(slot_start) + ->ReleaseFromUnprotectedPtr()) { + partition_alloc::internal::PartitionAllocFreeForRefCounting(slot_start); + } + } else { + if (partition_alloc::internal::PartitionRefCountPointer(slot_start) + ->Release()) { + partition_alloc::internal::PartitionAllocFreeForRefCounting(slot_start); + } + } +} + +template <bool AllowDangling> +void RawPtrBackupRefImpl<AllowDangling>::ReportIfDanglingInternal( + uintptr_t address) { + if (partition_alloc::internal::IsUnretainedDanglingRawPtrCheckEnabled()) { + if (IsSupportedAndNotNull(address)) { + uintptr_t slot_start = + partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); + partition_alloc::internal::PartitionRefCountPointer(slot_start) + ->ReportIfDangling(); + } + } +} + +template <bool AllowDangling> +bool RawPtrBackupRefImpl<AllowDangling>::IsPointeeAlive(uintptr_t address) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK(partition_alloc::IsManagedByPartitionAllocBRPPool(address)); +#endif + uintptr_t slot_start = + partition_alloc::PartitionAllocGetSlotStartInBRPPool(address); + return partition_alloc::internal::PartitionRefCountPointer(slot_start) + ->IsAlive(); +} + +template <bool AllowDangling> +template <typename Z> +partition_alloc::PtrPosWithinAlloc +RawPtrBackupRefImpl<AllowDangling>::IsValidDelta( + uintptr_t address, + partition_alloc::internal::PtrDelta<Z> delta) { + return partition_alloc::internal::PartitionAllocIsValidPtrDelta(address, + delta); +} + +// Explicitly instantiates the two BackupRefPtr variants in the .cc. This +// ensures the definitions not visible from the .h are available in the binary. +template struct RawPtrBackupRefImpl</*AllowDangling=*/false>; +template struct RawPtrBackupRefImpl</*AllowDangling=*/true>; + +template PA_COMPONENT_EXPORT(RAW_PTR) + partition_alloc::PtrPosWithinAlloc RawPtrBackupRefImpl<false>::IsValidDelta( + uintptr_t, + partition_alloc::internal::PtrDelta<size_t>); +template PA_COMPONENT_EXPORT(RAW_PTR) + partition_alloc::PtrPosWithinAlloc RawPtrBackupRefImpl<false>::IsValidDelta( + uintptr_t, + partition_alloc::internal::PtrDelta<ptrdiff_t>); +template PA_COMPONENT_EXPORT(RAW_PTR) + partition_alloc::PtrPosWithinAlloc RawPtrBackupRefImpl<true>::IsValidDelta( + uintptr_t, + partition_alloc::internal::PtrDelta<size_t>); +template PA_COMPONENT_EXPORT(RAW_PTR) + partition_alloc::PtrPosWithinAlloc RawPtrBackupRefImpl<true>::IsValidDelta( + uintptr_t, + partition_alloc::internal::PtrDelta<ptrdiff_t>); + +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) +void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address) { + if (partition_alloc::internal::IsManagedByDirectMap(address)) { + uintptr_t reservation_start = + partition_alloc::internal::GetDirectMapReservationStart(address); + PA_BASE_CHECK(address - reservation_start >= + partition_alloc::PartitionPageSize()); + } else { + PA_BASE_CHECK(partition_alloc::internal::IsManagedByNormalBuckets(address)); + PA_BASE_CHECK(address % partition_alloc::kSuperPageSize >= + partition_alloc::PartitionPageSize()); + } +} +#endif // BUILDFLAG(PA_DCHECK_IS_ON) || + // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + +} // namespace base::internal
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.h b/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.h new file mode 100644 index 0000000..3693277 --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_backup_ref_impl.h
@@ -0,0 +1,397 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_BACKUP_REF_IMPL_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_BACKUP_REF_IMPL_H_ + +#include <stddef.h> + +#include <type_traits> + +#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" +#include "base/allocator/partition_allocator/partition_address_space.h" +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" +#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h" +#include "base/allocator/partition_allocator/partition_alloc_config.h" +#include "base/allocator/partition_allocator/partition_alloc_constants.h" +#include "base/allocator/partition_allocator/partition_alloc_forward.h" +#include "build/build_config.h" + +#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) +#error "Included under wrong build option" +#endif + +namespace base::internal { + +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) +PA_COMPONENT_EXPORT(RAW_PTR) +void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address); +#endif + +template <bool AllowDangling = false> +struct RawPtrBackupRefImpl { + // Note that `RawPtrBackupRefImpl` itself is not thread-safe. If multiple + // threads modify the same smart pointer object without synchronization, a + // data race will occur. + + static PA_ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) { + // There are many situations where the compiler can prove that + // `ReleaseWrappedPtr` is called on a value that is always nullptr, but the + // way `IsManagedByPartitionAllocBRPPool` is written, the compiler can't + // prove that nullptr is not managed by PartitionAlloc; and so the compiler + // has to emit a useless check and dead code. To avoid that without making + // the runtime check slower, tell the compiler to skip + // `IsManagedByPartitionAllocBRPPool` when it can statically determine that + // address is nullptr. +#if PA_HAS_BUILTIN(__builtin_constant_p) + if (__builtin_constant_p(address == 0) && (address == 0)) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK( + !partition_alloc::IsManagedByPartitionAllocBRPPool(address)); +#endif // BUILDFLAG(PA_DCHECK_IS_ON) || + // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + return false; + } +#endif // PA_HAS_BUILTIN(__builtin_constant_p) + + // This covers the nullptr case, as address 0 is never in any + // PartitionAlloc pool. + bool is_in_brp_pool = + partition_alloc::IsManagedByPartitionAllocBRPPool(address); + + // There may be pointers immediately after the allocation, e.g. + // { + // // Assume this allocation happens outside of PartitionAlloc. + // raw_ptr<T> ptr = new T[20]; + // for (size_t i = 0; i < 20; i ++) { ptr++; } + // } + // + // Such pointers are *not* at risk of accidentally falling into BRP pool, + // because: + // 1) On 64-bit systems, BRP pool is preceded by a forbidden region. + // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP + // pool aren't considered to be part of that pool. + // + // This allows us to make a stronger assertion that if + // IsManagedByPartitionAllocBRPPool returns true for a valid pointer, + // it must be at least partition page away from the beginning of a super + // page. +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + if (is_in_brp_pool) { + CheckThatAddressIsntWithinFirstPartitionPage(address); + } +#endif + + return is_in_brp_pool; + } + +#if PA_CONFIG(USE_OOB_POISON) + // Out-Of-Bounds (OOB) poison bit is set when the pointer has overflowed by + // one byte. +#if defined(ARCH_CPU_X86_64) + // Bit 63 is the only pointer bit that will work as the poison bit across both + // LAM48 and LAM57. It also works when all unused linear address bits are + // checked for canonicality. + static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 63; +#else + // Avoid ARM's Top-Byte Ignore. + static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 55; +#endif + + template <typename T> + static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) { + return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) & + ~OOB_POISON_BIT); + } + + template <typename T> + static PA_ALWAYS_INLINE bool IsPtrOOB(T* ptr) { + return (reinterpret_cast<uintptr_t>(ptr) & OOB_POISON_BIT) == + OOB_POISON_BIT; + } + + template <typename T> + static PA_ALWAYS_INLINE T* PoisonOOBPtr(T* ptr) { + return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) | + OOB_POISON_BIT); + } +#else // PA_USE_OOB_POISON + template <typename T> + static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) { + return ptr; + } +#endif // PA_USE_OOB_POISON + + // Wraps a pointer. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { + uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(ptr)); + if (IsSupportedAndNotNull(address)) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK(ptr != nullptr); +#endif + AcquireInternal(address); + } else { +#if !PA_CONFIG(HAS_64_BITS_POINTERS) +#if PA_HAS_BUILTIN(__builtin_constant_p) + // Similarly to `IsSupportedAndNotNull` above, elide the + // `BanSuperPageFromBRPPool` call if the compiler can prove that `address` + // is zero since PA won't be able to map anything at that address anyway. + bool known_constant_zero = + __builtin_constant_p(address == 0) && (address == 0); +#else // PA_HAS_BUILTIN(__builtin_constant_p) + bool known_constant_zero = false; +#endif // PA_HAS_BUILTIN(__builtin_constant_p) + + if (!known_constant_zero) { + partition_alloc::internal::AddressPoolManagerBitmap:: + BanSuperPageFromBRPPool(address); + } +#endif // !PA_CONFIG(HAS_64_BITS_POINTERS) + } + + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { + uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr)); + if (IsSupportedAndNotNull(address)) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + PA_BASE_CHECK(wrapped_ptr != nullptr); +#endif + ReleaseInternal(address); + } + // We are unable to counteract BanSuperPageFromBRPPool(), called from + // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if + // there's more than one associated raw_ptr<T> at a given time. The risk of + // exhausting the entire address space is minuscule, therefore, we couldn't + // resist the perf gain of a single relaxed store (in the above mentioned + // function) over much more expensive two CAS operations, which we'd have to + // use if we were to un-ban a super-page. + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { +#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) +#if PA_CONFIG(USE_OOB_POISON) + PA_BASE_CHECK(!IsPtrOOB(wrapped_ptr)); +#endif + uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr); + if (IsSupportedAndNotNull(address)) { + PA_BASE_CHECK(wrapped_ptr != nullptr); + PA_BASE_CHECK(IsPointeeAlive(address)); + } +#endif // BUILDFLAG(PA_DCHECK_IS_ON) || + // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { + T* unpoisoned_ptr = UnpoisonPtr(wrapped_ptr); +#if PA_CONFIG(USE_OOB_POISON) + // Some code uses invalid pointer values as indicators, so those values must + // be passed through unchanged during extraction. The following check will + // pass invalid values through if those values do not fall within the BRP + // pool after being unpoisoned. + if (!IsSupportedAndNotNull(partition_alloc::UntagPtr(unpoisoned_ptr))) { + return wrapped_ptr; + } + // Poison-based OOB checks do not extend to extracted pointers. The + // alternative of retaining poison on extracted pointers could introduce new + // OOB conditions, e.g., in code that extracts an end-of-allocation pointer + // for use in a loop termination condition. The poison bit would make that + // pointer appear to reference a very high address. +#endif // PA_CONFIG(USE_OOB_POISON) + return unpoisoned_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { + // This may be used for unwrapping an end-of-allocation pointer to be used + // as an endpoint in an iterative algorithm, so this removes the OOB poison + // bit. + return UnpoisonPtr(wrapped_ptr); + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by `delta_elems`. + template < + typename T, + typename Z, + typename = + std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> + static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { +#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) + T* unpoisoned_ptr = UnpoisonPtr(wrapped_ptr); + T* new_ptr = unpoisoned_ptr + delta_elems; + // First check if the new address didn't migrate in/out the BRP pool, and + // that it lands within the same allocation. An end-of-allocation address is + // ok, too, and that may lead to the pointer being poisoned if the relevant + // feature is enabled. These checks add a non-trivial cost, but they're + // cheaper and more secure than the previous implementation that rewrapped + // the pointer (wrapped the new pointer and unwrapped the old one). + // + // Note, the value of these checks goes beyond OOB protection. They're + // important for integrity of the BRP algorithm. Without these, an attacker + // could make the pointer point to another allocation, and cause its + // ref-count to go to 0 upon this pointer's destruction, even though there + // may be another pointer still pointing to it, thus making it lose the BRP + // protection prematurely. + uintptr_t address = partition_alloc::UntagPtr(unpoisoned_ptr); + // TODO(bartekn): Consider adding support for non-BRP pools too (without + // removing the cross-pool migration check). + if (IsSupportedAndNotNull(address)) { + auto ptr_pos_within_alloc = IsValidDelta( + address, delta_elems * static_cast<Z>(sizeof(T)), sizeof(T)); + // No need to check that |new_ptr| is in the same pool, as IsValidDeta() + // checks that it's within the same allocation, so must be the same pool. + PA_BASE_CHECK(ptr_pos_within_alloc != + partition_alloc::PtrPosWithinAlloc::kFarOOB); +#if PA_CONFIG(USE_OOB_POISON) + if (ptr_pos_within_alloc == + partition_alloc::PtrPosWithinAlloc::kAllocEnd) { + new_ptr = PoisonOOBPtr(new_ptr); + } +#endif + } else { + // Check that the new address didn't migrate into the BRP pool, as it + // would result in more pointers pointing to an allocation than its + // ref-count reflects. + PA_BASE_CHECK(!IsSupportedAndNotNull(partition_alloc::UntagPtr(new_ptr))); + } + return new_ptr; +#else // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) + // In the "before allocation" mode, on 32-bit, we can run into a problem + // that the end-of-allocation address could fall outside of + // PartitionAlloc's pools, if this is the last slot of the super page, + // thus pointing to the guard page. This means the ref-count won't be + // decreased when the pointer is released (leak). + // + // We could possibly solve it in a few different ways: + // - Add the trailing guard page to the pool, but we'd have to think very + // hard if this doesn't create another hole. + // - Add an address adjustment to "is in pool?" check, similar as the one in + // PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to + // mention adding an extra instruction to an inlined hot path. + // - Let the leak happen, since it should a very rare condition. + // - Go back to the previous solution of rewrapping the pointer, but that + // had an issue of losing BRP protection in case the pointer ever gets + // shifted back before the end of allocation. + // + // We decided to cross that bridge once we get there... if we ever get + // there. Currently there are no plans to switch back to the "before + // allocation" mode. + // + // This problem doesn't exist in the "previous slot" mode, or any mode that + // involves putting extras after the allocation, because the + // end-of-allocation address belongs to the same slot. + static_assert(false); +#endif // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) + } + + template <typename T> + static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, + T* wrapped_ptr2) { + T* unpoisoned_ptr1 = UnpoisonPtr(wrapped_ptr1); + T* unpoisoned_ptr2 = UnpoisonPtr(wrapped_ptr2); + uintptr_t address1 = partition_alloc::UntagPtr(unpoisoned_ptr1); + uintptr_t address2 = partition_alloc::UntagPtr(unpoisoned_ptr2); + // Ensure that both pointers are within the same slot, and pool! + // TODO(bartekn): Consider adding support for non-BRP pool too. + if (IsSupportedAndNotNull(address1)) { + PA_BASE_CHECK(IsSupportedAndNotNull(address2)); + PA_BASE_CHECK(IsValidDelta(address2, address1 - address2, sizeof(T)) != + partition_alloc::PtrPosWithinAlloc::kFarOOB); + } else { + PA_BASE_CHECK(!IsSupportedAndNotNull(address2)); + } + return unpoisoned_ptr1 - unpoisoned_ptr2; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + // This method increments the reference count of the allocation slot. + template <typename T> + static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { + return WrapRawPtr(wrapped_ptr); + } + + // Report the current wrapped pointer if pointee isn't alive anymore. + template <typename T> + static PA_ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) { + ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr)); + } + + // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used + // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { + return WrapRawPtr(ptr); + } + + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { + return UnpoisonPtr(wrapped_ptr); + } + + // This is for accounting only, used by unit tests. + static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} + static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} + static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} + + private: + // We've evaluated several strategies (inline nothing, various parts, or + // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark + // to measure performance. The best results were obtained when only the + // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined. + // Therefore, we've extracted the rest into the functions below and marked + // them as PA_NOINLINE to prevent unintended LTO effects. + static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE + void AcquireInternal(uintptr_t address); + static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE + void ReleaseInternal(uintptr_t address); + static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE + bool IsPointeeAlive(uintptr_t address); + static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE + void ReportIfDanglingInternal(uintptr_t address); + template < + typename Z, + typename = + std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> + static PA_ALWAYS_INLINE partition_alloc::PtrPosWithinAlloc + IsValidDelta(uintptr_t address, Z delta_in_bytes, size_t type_size) { + using delta_t = std::conditional_t<std::is_signed_v<Z>, ptrdiff_t, size_t>; + partition_alloc::internal::PtrDelta<delta_t> ptr_delta(delta_in_bytes, + type_size); + + return IsValidDelta(address, ptr_delta); + } + template <typename Z> + static PA_COMPONENT_EXPORT(RAW_PTR) + PA_NOINLINE partition_alloc::PtrPosWithinAlloc + IsValidDelta(uintptr_t address, + partition_alloc::internal::PtrDelta<Z> delta); +}; + +} // namespace base::internal + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_BACKUP_REF_IMPL_H_
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.cc b/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.cc new file mode 100644 index 0000000..1e8ca8a78 --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.cc
@@ -0,0 +1,48 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.h" + +#include <atomic> +#include <cstdint> + +namespace base::internal { + +namespace { + +void DefaultWrapPtrHook(uintptr_t address) {} +void DefaultReleaseWrappedPtrHook(uintptr_t address) {} +void DefaultUnwrapForDereferenceHook(uintptr_t address) {} +void DefaultUnwrapForExtractionHook(uintptr_t address) {} +void DefaultUnwrapForComparisonHook(uintptr_t address) {} +void DefaultAdvanceHook(uintptr_t old_address, uintptr_t new_address) {} +void DefaultDuplicateHook(uintptr_t address) {} + +constexpr RawPtrHooks default_hooks = { + DefaultWrapPtrHook, + DefaultReleaseWrappedPtrHook, + DefaultUnwrapForDereferenceHook, + DefaultUnwrapForExtractionHook, + DefaultUnwrapForComparisonHook, + DefaultAdvanceHook, + DefaultDuplicateHook, +}; + +} // namespace + +std::atomic<const RawPtrHooks*> g_hooks{&default_hooks}; + +const RawPtrHooks* GetRawPtrHooks() { + return g_hooks.load(std::memory_order_relaxed); +} + +void InstallRawPtrHooks(const RawPtrHooks* hooks) { + g_hooks.store(hooks, std::memory_order_relaxed); +} + +void ResetRawPtrHooks() { + InstallRawPtrHooks(&default_hooks); +} + +} // namespace base::internal
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.h b/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.h new file mode 100644 index 0000000..7590a4e --- /dev/null +++ b/base/allocator/partition_allocator/pointers/raw_ptr_hookable_impl.h
@@ -0,0 +1,143 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_HOOKABLE_IMPL_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_HOOKABLE_IMPL_H_ + +#include <stddef.h> + +#include <type_traits> + +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" +#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h" +#include "base/allocator/partition_allocator/partition_alloc_buildflags.h" +#include "base/allocator/partition_allocator/partition_alloc_forward.h" + +#if !BUILDFLAG(USE_HOOKABLE_RAW_PTR) +#error "Included under wrong build option" +#endif + +namespace base::internal { + +struct RawPtrHooks { + using WrapPtr = void(uintptr_t address); + using ReleaseWrappedPtr = void(uintptr_t address); + using SafelyUnwrapForDereference = void(uintptr_t address); + using SafelyUnwrapForExtraction = void(uintptr_t address); + using UnsafelyUnwrapForComparison = void(uintptr_t address); + using Advance = void(uintptr_t old_address, uintptr_t new_address); + using Duplicate = void(uintptr_t address); + + WrapPtr* wrap_ptr; + ReleaseWrappedPtr* release_wrapped_ptr; + SafelyUnwrapForDereference* safely_unwrap_for_dereference; + SafelyUnwrapForExtraction* safely_unwrap_for_extraction; + UnsafelyUnwrapForComparison* unsafely_unwrap_for_comparison; + Advance* advance; + Duplicate* duplicate; +}; + +PA_COMPONENT_EXPORT(RAW_PTR) const RawPtrHooks* GetRawPtrHooks(); +PA_COMPONENT_EXPORT(RAW_PTR) void InstallRawPtrHooks(const RawPtrHooks*); +PA_COMPONENT_EXPORT(RAW_PTR) void ResetRawPtrHooks(); + +struct RawPtrHookableImpl { + // Wraps a pointer. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) { + GetRawPtrHooks()->wrap_ptr(reinterpret_cast<uintptr_t>(ptr)); + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) { + GetRawPtrHooks()->release_wrapped_ptr(reinterpret_cast<uintptr_t>(ptr)); + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { + GetRawPtrHooks()->safely_unwrap_for_dereference( + reinterpret_cast<uintptr_t>(wrapped_ptr)); + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { + GetRawPtrHooks()->safely_unwrap_for_extraction( + reinterpret_cast<uintptr_t>(wrapped_ptr)); + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { + GetRawPtrHooks()->unsafely_unwrap_for_comparison( + reinterpret_cast<uintptr_t>(wrapped_ptr)); + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by `delta_elems`. + template < + typename T, + typename Z, + typename = + std::enable_if_t<partition_alloc::internal::offset_type<Z>, void>> + static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) { + GetRawPtrHooks()->advance( + reinterpret_cast<uintptr_t>(wrapped_ptr), + reinterpret_cast<uintptr_t>(wrapped_ptr + delta_elems)); + return wrapped_ptr + delta_elems; + } + + template <typename T> + static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1, + T* wrapped_ptr2) { + return wrapped_ptr1 - wrapped_ptr2; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + template <typename T> + static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { + GetRawPtrHooks()->duplicate(reinterpret_cast<uintptr_t>(wrapped_ptr)); + return wrapped_ptr; + } + + // `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used + // to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor. + template <typename T> + static PA_ALWAYS_INLINE T* WrapRawPtrForDuplication(T* ptr) { + return ptr; + } + + template <typename T> + static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForDuplication(T* wrapped_ptr) { + return wrapped_ptr; + } + + // This is for accounting only, used by unit tests. + static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {} + static PA_ALWAYS_INLINE void IncrementLessCountForTest() {} + static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} +}; + +} // namespace base::internal + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_HOOKABLE_IMPL_H_
diff --git a/base/allocator/partition_allocator/pointers/raw_ref.h b/base/allocator/partition_allocator/pointers/raw_ref.h index 28f319a..05d293f 100644 --- a/base/allocator/partition_allocator/pointers/raw_ref.h +++ b/base/allocator/partition_allocator/pointers/raw_ref.h
@@ -81,7 +81,7 @@ internal::MTECheckedPtrImplPartitionAllocSupport>> || #endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS) #if BUILDFLAG(USE_ASAN_UNOWNED_PTR) - std::is_same_v<Impl, internal::AsanUnownedPtrImpl> || + std::is_same_v<Impl, internal::RawPtrAsanUnownedImpl> || #endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR) std::is_same_v<Impl, internal::RawPtrNoOpImpl>;
diff --git a/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc b/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc index 3cde46c..dcf26fa5 100644 --- a/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc +++ b/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc
@@ -704,6 +704,13 @@ counts_after = total_counts(allocs_intercepted_by_size); EXPECT_GT(counts_after, counts_before); + // With component builds on Android, we cannot intercept calls to functions + // inside another component, in this instance the call to vasprintf() inside + // libc++. This is not necessarily an issue for allocator shims, as long as we + // accept that allocations and deallocations will not be matched at all times. + // It is however essential for PartitionAlloc, which is exercized in the test + // below. +#ifndef COMPONENT_BUILD // Calls vasprintf() indirectly, see below. counts_before = counts_after; std::stringstream stream; @@ -711,6 +718,7 @@ EXPECT_GT(stream.str().size(), 30u); counts_after = total_counts(allocs_intercepted_by_size); EXPECT_GT(counts_after, counts_before); +#endif // COMPONENT_BUILD RemoveAllocatorDispatchForTesting(&g_mock_dispatch); }
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index 6f3e4321..f1a749de 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py
@@ -11,7 +11,6 @@ import argparse import base64 import collections -import errno import hashlib import os import re @@ -524,13 +523,15 @@ return m[0] -def ExtractFullyQualifiedJavaClassName(java_file_name, contents): +def ExtractFullyQualifiedJavaClassName(file_name, contents): + assert not file_name.endswith('.kt'), ( + f'Found {file_name}, but Kotlin is not supported by JNI generator.') re_package = re.compile('.*?package (.*?);') matches = re.findall(re_package, contents) if not matches: - raise SyntaxError('Unable to find "package" line in %s' % java_file_name) + raise SyntaxError('Unable to find "package" line in %s' % file_name) class_path = matches[0].replace('.', '/') - class_name = os.path.splitext(os.path.basename(java_file_name))[0] + class_name = os.path.splitext(os.path.basename(file_name))[0] return class_path + '/' + class_name @@ -1659,7 +1660,9 @@ parser.add_argument('--stamp', help='Process --prev_output_dir and touch this file.') args = parser.parse_args() - input_files = args.input_files + # Kotlin files are not supported by jni_generator.py, but they do end up in + # the list of source files passed to jni_generator.py. + input_files = [f for f in args.input_files if not f.endswith('.kt')] output_names = args.output_names if args.prev_output_dir:
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index 60fd271..9ca0a1f3 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -882,6 +882,9 @@ self.assertRaises(SyntaxError, jni_generator.ExtractFullyQualifiedJavaClassName, 'com/foo/Bar', 'no PACKAGE line') + self.assertRaises(AssertionError, + jni_generator.ExtractFullyQualifiedJavaClassName, + 'com/foo/Bar.kt', 'Kotlin not supported') def testMethodNameMangling(self): jni_params = jni_generator.JniParams('')
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py index f939014..ae838d4e 100755 --- a/base/android/jni_generator/jni_registration_generator.py +++ b/base/android/jni_generator/jni_registration_generator.py
@@ -949,10 +949,11 @@ java_file_paths = [] for f in sources_files: - # Skip generated files, since the GN targets do not declare any deps. + # Skip generated files, since the GN targets do not declare any deps. Also + # skip Kotlin files as they are not supported by JNI generation. java_file_paths.extend( - p for p in build_utils.ReadSourcesList(f) - if p.startswith('..') and p not in args.sources_exclusions) + p for p in build_utils.ReadSourcesList(f) if p.startswith('..') + and p not in args.sources_exclusions and not p.endswith('.kt')) _Generate(java_file_paths, args.srcjar_path, proxy_opts=proxy_opts,
diff --git a/base/android/unguessable_token_android.cc b/base/android/unguessable_token_android.cc index 448daee..efff14b 100644 --- a/base/android/unguessable_token_android.cc +++ b/base/android/unguessable_token_android.cc
@@ -30,7 +30,7 @@ Java_UnguessableToken_getLowForSerialization(env, token)); DCHECK(high); DCHECK(low); - return base::UnguessableToken::Deserialize2(high, low); + return base::UnguessableToken::Deserialize(high, low); } ScopedJavaLocalRef<jobject>
diff --git a/base/critical_closure.h b/base/critical_closure.h index 228131e..d2673de3 100644 --- a/base/critical_closure.h +++ b/base/critical_closure.h
@@ -75,6 +75,9 @@ // background running time, |MakeCriticalClosure| should be applied on them // before posting. |task_name| is used by the platform to identify any tasks // that do not complete in time for suspension. +// +// This function is used automatically for tasks posted to a sequence runner +// using TaskShutdownBehavior::BLOCK_SHUTDOWN. #if BUILDFLAG(IS_IOS) inline OnceClosure MakeCriticalClosure(StringPiece task_name, OnceClosure closure,
diff --git a/base/feature_list.cc b/base/feature_list.cc index 55baff2..a924a1e 100644 --- a/base/feature_list.cc +++ b/base/feature_list.cc
@@ -93,7 +93,10 @@ // TODO(crbug.com/1383852): When we believe that all early accesses have // been fixed, remove this base::debug::DumpWithoutCrashing() and change the // above DCHECK to a CHECK. - base::debug::DumpWithoutCrashing(); + + // The following line is commented to reduce the crash volume while a fix + // for crbug.com/1392145 is prepared. + // base::debug::DumpWithoutCrashing(); #endif // !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) && // !BUILDFLAG(IS_CHROMEOS) }
diff --git a/base/ios/scoped_critical_action.h b/base/ios/scoped_critical_action.h index d3f9e47..b7040b6f 100644 --- a/base/ios/scoped_critical_action.h +++ b/base/ios/scoped_critical_action.h
@@ -5,13 +5,22 @@ #ifndef BASE_IOS_SCOPED_CRITICAL_ACTION_H_ #define BASE_IOS_SCOPED_CRITICAL_ACTION_H_ +#include <map> +#include <string> +#include <utility> + +#include "base/feature_list.h" #include "base/memory/ref_counted.h" #include "base/strings/string_piece_forward.h" #include "base/synchronization/lock.h" +#include "base/time/time.h" namespace base { namespace ios { +// Feature exposed publicly for unit-testing purposes. +BASE_DECLARE_FEATURE(kScopedCriticalActionReuseEnabled); + // This class attempts to allow the application to continue to run for a period // of time after it transitions to the background. The construction of an // instance of this class marks the beginning of a task that needs background @@ -34,11 +43,15 @@ ~ScopedCriticalAction(); + // Exposed for unit-testing. + static void ClearNumActiveBackgroundTasksForTest(); + static int GetNumActiveBackgroundTasksForTest(); + private: // Core logic; ScopedCriticalAction should not be reference counted so // that it follows the normal pattern of stack-allocating ScopedFoo objects, // but the expiration handler needs to have a reference counted object to - // refer to. + // refer to. All functions are thread safe. class Core : public base::RefCountedThreadSafe<Core> { public: Core(); @@ -49,10 +62,14 @@ // Informs the OS that the background task has started. This is a // static method to ensure that the instance has a non-zero refcount. // |task_name| is used by the OS to log any leaked background tasks. + // Invoking this function more than once is allowed: all except the + // first successful call will be a no-op. static void StartBackgroundTask(scoped_refptr<Core> core, StringPiece task_name); // Informs the OS that the background task has completed. This is a // static method to ensure that the instance has a non-zero refcount. + // Invoking this function more than once is allowed: all except the + // first call will be a no-op. static void EndBackgroundTask(scoped_refptr<Core> core); private: @@ -68,8 +85,57 @@ Lock background_task_id_lock_; }; - // The instance of the core that drives the background task. + // This class is thread safe. + class ActiveBackgroundTaskCache { + public: + // This struct should be considered internal to this class and opaque to + // callers. + struct InternalEntry { + InternalEntry(); + InternalEntry(const InternalEntry&) = delete; + InternalEntry(InternalEntry&&); + ~InternalEntry(); + + InternalEntry& operator=(const InternalEntry&) = delete; + InternalEntry& operator=(InternalEntry&&); + + // The instance of the core that drives the background task. + scoped_refptr<Core> core; + // Refcounting for the number of ScopedCriticalAction instances that + // require the existence of this background task. + int num_active_handles = 0; + }; + + using NameAndTime = std::pair<std::string, base::TimeTicks>; + using InternalEntriesMap = std::map<NameAndTime, InternalEntry>; + // A handle should be treated as an opaque token by the caller. + using Handle = InternalEntriesMap::iterator; + + // Returns a leaky singleton instance. + static ActiveBackgroundTaskCache* GetInstance(); + + ActiveBackgroundTaskCache(); + ~ActiveBackgroundTaskCache(); + + // Starts a new background task if none existed with the same name. If a + // task already exists with the same name, its lifetime is effectively + // extended. Callers must invoke ReleaseHandle() once they no longer need to + // prevent background suspension. + Handle EnsureBackgroundTaskExistsWithName(StringPiece task_name); + + // Indicates that a previous caller to EnsureBackgroundTaskExistsWithName() + // no longer needs to prevent background suspension. + void ReleaseHandle(Handle handle); + + private: + InternalEntriesMap entries_map_ GUARDED_BY(entries_map_lock_); + Lock entries_map_lock_; + }; + + // Depepending on whether reuse is globally enabled upon construction, either + // a dedicated Core instance is used or a reusable one. scoped_refptr<Core> core_; + ActiveBackgroundTaskCache::Handle task_handle_; }; } // namespace ios
diff --git a/base/ios/scoped_critical_action.mm b/base/ios/scoped_critical_action.mm index 1f65254..038da26 100644 --- a/base/ios/scoped_critical_action.mm +++ b/base/ios/scoped_critical_action.mm
@@ -6,10 +6,13 @@ #import <UIKit/UIKit.h> +#include <atomic> + #include <float.h> #include "base/ios/ios_util.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/memory/singleton.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/strings/string_piece.h" @@ -19,13 +22,48 @@ namespace base { namespace ios { -ScopedCriticalAction::ScopedCriticalAction(StringPiece task_name) - : core_(MakeRefCounted<ScopedCriticalAction::Core>()) { - ScopedCriticalAction::Core::StartBackgroundTask(core_, task_name); +BASE_FEATURE(kScopedCriticalActionReuseEnabled, + "ScopedCriticalActionReuseEnabled", + base::FEATURE_DISABLED_BY_DEFAULT); + +namespace { + +constexpr base::TimeDelta kMaxTaskReuseDelay = base::Seconds(3); + +// Used for unit-testing only. +std::atomic<int> g_num_active_background_tasks_for_test{0}; + +} // namespace + +ScopedCriticalAction::ScopedCriticalAction(StringPiece task_name) { + if (base::FeatureList::IsEnabled(kScopedCriticalActionReuseEnabled)) { + task_handle_ = ActiveBackgroundTaskCache::GetInstance() + ->EnsureBackgroundTaskExistsWithName(task_name); + DCHECK(!core_); + } else { + core_ = MakeRefCounted<Core>(); + Core::StartBackgroundTask(core_, task_name); + } } ScopedCriticalAction::~ScopedCriticalAction() { - ScopedCriticalAction::Core::EndBackgroundTask(core_); + if (core_) { + // kScopedCriticalActionReuseEnabled was disabled upon construction. + Core::EndBackgroundTask(core_); + } else { + // kScopedCriticalActionReuseEnabled was enabled upon construction. + ActiveBackgroundTaskCache::GetInstance()->ReleaseHandle(task_handle_); + } +} + +// static +void ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest() { + g_num_active_background_tasks_for_test.store(0); +} + +// static +int ScopedCriticalAction::GetNumActiveBackgroundTasksForTest() { + return g_num_active_background_tasks_for_test.load(); } ScopedCriticalAction::Core::Core() @@ -48,6 +86,11 @@ } AutoLock lock_scope(core->background_task_id_lock_); + if (core->background_task_id_ != UIBackgroundTaskInvalid) { + // Already started. + return; + } + NSString* task_string = !task_name.empty() ? base::SysUTF8ToNSString(task_name) : nil; core->background_task_id_ = [application @@ -68,6 +111,8 @@ } else { VLOG(3) << "Beginning background task <" << task_name << "> with id " << core->background_task_id_; + g_num_active_background_tasks_for_test.fetch_add(1, + std::memory_order_relaxed); } } @@ -77,6 +122,7 @@ { AutoLock lock_scope(core->background_task_id_lock_); if (core->background_task_id_ == UIBackgroundTaskInvalid) { + // Never started successfully or already ended. return; } task_id = @@ -86,6 +132,98 @@ VLOG(3) << "Ending background task with id " << task_id; [[UIApplication sharedApplication] endBackgroundTask:task_id]; + g_num_active_background_tasks_for_test.fetch_sub(1, + std::memory_order_relaxed); +} + +ScopedCriticalAction::ActiveBackgroundTaskCache::InternalEntry:: + InternalEntry() = default; + +ScopedCriticalAction::ActiveBackgroundTaskCache::InternalEntry:: + ~InternalEntry() = default; + +ScopedCriticalAction::ActiveBackgroundTaskCache::InternalEntry::InternalEntry( + InternalEntry&&) = default; + +ScopedCriticalAction::ActiveBackgroundTaskCache::InternalEntry& +ScopedCriticalAction::ActiveBackgroundTaskCache::InternalEntry::operator=( + InternalEntry&&) = default; + +// static +ScopedCriticalAction::ActiveBackgroundTaskCache* +ScopedCriticalAction::ActiveBackgroundTaskCache::GetInstance() { + return base::Singleton< + ActiveBackgroundTaskCache, + base::LeakySingletonTraits<ActiveBackgroundTaskCache>>::get(); +} + +ScopedCriticalAction::ActiveBackgroundTaskCache::ActiveBackgroundTaskCache() = + default; + +ScopedCriticalAction::ActiveBackgroundTaskCache::~ActiveBackgroundTaskCache() = + default; + +ScopedCriticalAction::ActiveBackgroundTaskCache::Handle ScopedCriticalAction:: + ActiveBackgroundTaskCache::EnsureBackgroundTaskExistsWithName( + StringPiece task_name) { + const base::TimeTicks now = base::TimeTicks::Now(); + const base::TimeTicks min_reusable_time = now - kMaxTaskReuseDelay; + NameAndTime min_reusable_key{task_name, min_reusable_time}; + + Handle handle; + { + AutoLock lock_scope(entries_map_lock_); + auto lower_it = entries_map_.lower_bound(min_reusable_key); + + if (lower_it != entries_map_.end() && lower_it->first.first == task_name) { + // A reusable Core instance exists, with the same name and created + // recently enough to warrant reuse. + DCHECK_GE(lower_it->first.second, min_reusable_time); + handle = lower_it; + } else { + // No reusable entry exists, so a new entry needs to be created. + auto it = entries_map_.emplace_hint( + lower_it, NameAndTime{std::move(min_reusable_key.first), now}, + InternalEntry{}); + DCHECK_EQ(it->first.second, now); + DCHECK(!it->second.core); + handle = it; + handle->second.core = MakeRefCounted<Core>(); + } + + // This guarantees a non-zero counter and hence the deletion of this map + // entry during this function body, even after the lock is released. + ++handle->second.num_active_handles; + } + + // If this call didn't newly-create a Core instance, the call to + // StartBackgroundTask() is almost certainly (barring race conditions) + // unnecessary. It is however harmless to invoke it twice. + Core::StartBackgroundTask(handle->second.core, task_name); + + return handle; +} + +void ScopedCriticalAction::ActiveBackgroundTaskCache::ReleaseHandle( + Handle handle) { + scoped_refptr<Core> background_task_to_end; + + { + AutoLock lock_scope(entries_map_lock_); + --handle->second.num_active_handles; + if (handle->second.num_active_handles == 0) { + // Move to |background_task_to_end| so the global lock is released before + // invoking EndBackgroundTask() which is expensive. + background_task_to_end = std::move(handle->second.core); + entries_map_.erase(handle); + } + } + + // Note that at this point another, since the global lock was released, + // another task could have started with the same name, but this harmless. + if (background_task_to_end != nullptr) { + Core::EndBackgroundTask(std::move(background_task_to_end)); + } } } // namespace ios
diff --git a/base/ios/scoped_critical_action_unittest.mm b/base/ios/scoped_critical_action_unittest.mm new file mode 100644 index 0000000..3f8d9aa --- /dev/null +++ b/base/ios/scoped_critical_action_unittest.mm
@@ -0,0 +1,160 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/ios/scoped_critical_action.h" + +#include <memory> + +#include "base/strings/string_piece.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace base { +namespace ios { +namespace { + +class ScopedCriticalActionTest : public PlatformTest { + protected: + ScopedCriticalActionTest() { + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + } + + ~ScopedCriticalActionTest() override = default; + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; +}; + +TEST_F(ScopedCriticalActionTest, ShouldStartBackgroundTaskWhenConstructed) { + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + ScopedCriticalAction scoped_critical_action("name"); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, ShouldEndBackgroundTaskWhenDestructed) { + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action = std::make_unique<ScopedCriticalAction>("name"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, ShouldUseMultipleBackgroundTasks) { + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action1 = + std::make_unique<ScopedCriticalAction>("name1"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action2 = + std::make_unique<ScopedCriticalAction>("name2"); + EXPECT_EQ(2, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action1.reset(); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action2.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, + ShouldReuseBackgroundTasksForSameNameIfEnabled) { + test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(kScopedCriticalActionReuseEnabled); + + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action1 = std::make_unique<ScopedCriticalAction>("name"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action2 = std::make_unique<ScopedCriticalAction>("name"); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action1.reset(); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action2.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, + ShouldNotReuseBackgroundTasksForSameNameIfDisabled) { + test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(kScopedCriticalActionReuseEnabled); + + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action1 = std::make_unique<ScopedCriticalAction>("name"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action2 = std::make_unique<ScopedCriticalAction>("name"); + EXPECT_EQ(2, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action1.reset(); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action2.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, + ShouldNotReuseBackgroundTasksForSameNameIfTimeDifferenceLarge) { + test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(kScopedCriticalActionReuseEnabled); + + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action1 = std::make_unique<ScopedCriticalAction>("name"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + // Mimic advancing time more than 3 seconds (kMaxTaskReuseDelay). + task_environment_.FastForwardBy(base::Seconds(4)); + + auto scoped_critical_action2 = std::make_unique<ScopedCriticalAction>("name"); + EXPECT_EQ(2, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action1.reset(); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action2.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +TEST_F(ScopedCriticalActionTest, + ShouldReuseBackgroundTasksForSameNameIfTimeDifferenceSmall) { + test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(kScopedCriticalActionReuseEnabled); + + ScopedCriticalAction::ClearNumActiveBackgroundTasksForTest(); + ASSERT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + auto scoped_critical_action1 = std::make_unique<ScopedCriticalAction>("name"); + ASSERT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + // Mimic advancing time less than 3 seconds (kMaxTaskReuseDelay). + task_environment_.FastForwardBy(base::Seconds(2)); + + auto scoped_critical_action2 = std::make_unique<ScopedCriticalAction>("name"); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action1.reset(); + EXPECT_EQ(1, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); + + scoped_critical_action2.reset(); + EXPECT_EQ(0, ScopedCriticalAction::GetNumActiveBackgroundTasksForTest()); +} + +} // namespace +} // namespace ios +} // namespace base
diff --git a/base/json/values_util.cc b/base/json/values_util.cc index 45035d8..8f14256 100644 --- a/base/json/values_util.cc +++ b/base/json/values_util.cc
@@ -113,7 +113,7 @@ if (!HexStringToSpan(value.GetString(), repr.buffer)) return absl::nullopt; absl::optional<base::UnguessableToken> token = - UnguessableToken::Deserialize2(repr.field.high, repr.field.low); + UnguessableToken::Deserialize(repr.field.high, repr.field.low); if (!token.has_value()) { return absl::nullopt; }
diff --git a/base/mac/launch_application.h b/base/mac/launch_application.h new file mode 100644 index 0000000..4e33428 --- /dev/null +++ b/base/mac/launch_application.h
@@ -0,0 +1,65 @@ +// Copyright 2013 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MAC_LAUNCH_APPLICATION_H_ +#define BASE_MAC_LAUNCH_APPLICATION_H_ + +#import <AppKit/AppKit.h> + +#include <string> +#include <vector> + +#include "base/base_export.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/functional/callback_forward.h" +#include "base/types/expected.h" +#include "third_party/abseil-cpp/absl/types/variant.h" + +// Launches an application. +// +// What makes this different from `LaunchProcess()` in /base/process/launch.h? +// That code creates a sub-process, which is useful for utility processes and +// the like, but inappropriate for independent applications. +// `LaunchApplication()` below, on the other hand, launches an app in the way +// that the Finder or Dock would launch an app. + +namespace base::mac { + +struct LaunchApplicationOptions { + bool activate = true; + bool create_new_instance = false; + bool prompt_user_if_needed = false; +}; + +using LaunchApplicationCallback = + base::OnceCallback<void(base::expected<NSRunningApplication*, NSError*>)>; + +using CommandLineArgs = + absl::variant<absl::monostate, CommandLine, std::vector<std::string>>; + +// Launches the specified application. +// - `app_bundle_path`: the location of the application to launch +// - `command_line_args`: the command line arguments to pass to the +// application if the app isn't already running (the default-constructed +// monostate alternative means no arguments) +// - Note: The application to launch is specified as `app_bundle_path`, so +// if `base::CommandLine` is used to provide command line arguments, its +// first argument will be ignored +// - `url_specs`: the URLs for the application to open (an empty vector is OK) +// - `options`: options to modify the launch +// - `callback`: the result callback +// +// When the launch is complete, `callback` is called on the main thread. If the +// launch succeeded, it will be called with an `NSRunningApplication*`. If the +// launch failed, it will be called with an `NSError*`. +BASE_EXPORT void LaunchApplication(const FilePath& app_bundle_path, + const CommandLineArgs& command_line_args, + const std::vector<std::string>& url_specs, + LaunchApplicationOptions options, + LaunchApplicationCallback callback); + +} // namespace base::mac + +#endif // BASE_MAC_LAUNCH_APPLICATION_H_
diff --git a/base/mac/launch_services_util.mm b/base/mac/launch_application.mm similarity index 66% rename from base/mac/launch_services_util.mm rename to base/mac/launch_application.mm index 58b2218..beefe92 100644 --- a/base/mac/launch_services_util.mm +++ b/base/mac/launch_application.mm
@@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "base/mac/launch_services_util.h" +#import "base/mac/launch_application.h" +#include "base/command_line.h" #include "base/functional/callback.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -14,37 +15,50 @@ namespace { -NSArray* CommandLineToArgsArray(const CommandLine& command_line) { - const auto& argv = command_line.argv(); - size_t argc = argv.size(); - DCHECK_GT(argc, 0lu); +NSArray* CommandLineArgsToArgsArray(const CommandLineArgs& command_line_args) { + if (const CommandLine* command_line = + absl::get_if<CommandLine>(&command_line_args)) { + const auto& argv = command_line->argv(); + size_t argc = argv.size(); + DCHECK_GT(argc, 0lu); - NSMutableArray* args_array = [NSMutableArray arrayWithCapacity:argc - 1]; - // NSWorkspace automatically adds the binary path as the first argument and - // thus it should not be included in the list. - for (size_t i = 1; i < argc; ++i) { - [args_array addObject:base::SysUTF8ToNSString(argv[i])]; + NSMutableArray* args_array = [NSMutableArray arrayWithCapacity:argc - 1]; + // NSWorkspace automatically adds the binary path as the first argument and + // thus it should not be included in the list. + for (size_t i = 1; i < argc; ++i) { + [args_array addObject:base::SysUTF8ToNSString(argv[i])]; + } + + return args_array; } - return args_array; + if (const std::vector<std::string>* string_vector = + absl::get_if<std::vector<std::string>>(&command_line_args)) { + NSMutableArray* args_array = + [NSMutableArray arrayWithCapacity:string_vector->size()]; + for (const auto& arg : *string_vector) { + [args_array addObject:base::SysUTF8ToNSString(arg)]; + } + } + + return @[]; } NSWorkspaceOpenConfiguration* GetOpenConfiguration( - OpenApplicationOptions options, - const CommandLine& command_line) API_AVAILABLE(macos(10.15)) { + LaunchApplicationOptions options, + const CommandLineArgs& command_line_args) API_AVAILABLE(macos(10.15)) { NSWorkspaceOpenConfiguration* config = [NSWorkspaceOpenConfiguration configuration]; config.activates = options.activate; config.createsNewApplicationInstance = options.create_new_instance; - config.promptsUserIfNeeded = NO; - - config.arguments = CommandLineToArgsArray(command_line); + config.promptsUserIfNeeded = options.prompt_user_if_needed; + config.arguments = CommandLineArgsToArgsArray(command_line_args); return config; } -NSWorkspaceLaunchOptions GetLaunchOptions(OpenApplicationOptions options) { +NSWorkspaceLaunchOptions GetLaunchOptions(LaunchApplicationOptions options) { NSWorkspaceLaunchOptions launch_options = NSWorkspaceLaunchDefault; if (!options.activate) { @@ -53,18 +67,21 @@ if (options.create_new_instance) { launch_options |= NSWorkspaceLaunchNewInstance; } + if (options.prompt_user_if_needed) { + launch_options |= NSWorkspaceLaunchWithErrorPresentation; + } return launch_options; } } // namespace -void OpenApplication(const base::FilePath& app_bundle_path, - const CommandLine& command_line, - const std::vector<std::string>& url_specs, - OpenApplicationOptions options, - ApplicationOpenedCallback callback) { - __block ApplicationOpenedCallback callback_block_access = std::move(callback); +void LaunchApplication(const base::FilePath& app_bundle_path, + const CommandLineArgs& command_line_args, + const std::vector<std::string>& url_specs, + LaunchApplicationOptions options, + LaunchApplicationCallback callback) { + __block LaunchApplicationCallback callback_block_access = std::move(callback); NSURL* bundle_url = FilePathToNSURL(app_bundle_path); if (!bundle_url) { @@ -100,7 +117,7 @@ }; NSWorkspaceOpenConfiguration* configuration = - GetOpenConfiguration(options, command_line); + GetOpenConfiguration(options, command_line_args); if (ns_urls) { [NSWorkspace.sharedWorkspace openURLs:ns_urls @@ -115,7 +132,7 @@ } else { NSDictionary* configuration = @{ NSWorkspaceLaunchConfigurationArguments : - CommandLineToArgsArray(command_line), + CommandLineArgsToArgsArray(command_line_args), }; NSWorkspaceLaunchOptions launch_options = GetLaunchOptions(options);
diff --git a/base/mac/launch_services_util.h b/base/mac/launch_services_util.h deleted file mode 100644 index 499f7c8c..0000000 --- a/base/mac/launch_services_util.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MAC_LAUNCH_SERVICES_UTIL_H_ -#define BASE_MAC_LAUNCH_SERVICES_UTIL_H_ - -#import <AppKit/AppKit.h> - -#include <string> -#include <vector> - -#include "base/base_export.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/functional/callback_forward.h" -#include "base/types/expected.h" - -namespace base::mac { - -struct OpenApplicationOptions { - bool activate = true; - bool create_new_instance = false; -}; - -using ApplicationOpenedCallback = - base::OnceCallback<void(base::expected<NSRunningApplication*, NSError*>)>; - -// Launches the specified application bundle. -// - `app_bundle_path`: the location of the application to launch -// - `command_line`: the arguments to pass to the application as command line -// arguments if the app isn't already running -// - `url_specs`: the URLs for the application to open (an empty vector is OK) -// - `options`: options to modify the launch -// - `callback`: the result callback -// -// When the launch is complete, `callback` is called on the main thread. If the -// launch succeeded, it will be called with an `NSRunningApplication*`. If the -// launch failed, it will be called with an `NSError*`. -BASE_EXPORT void OpenApplication(const FilePath& app_bundle_path, - const CommandLine& command_line, - const std::vector<std::string>& url_specs, - OpenApplicationOptions options, - ApplicationOpenedCallback callback); - -} // namespace base::mac - -#endif // BASE_MAC_LAUNCH_SERVICES_UTIL_H_
diff --git a/base/memory/raw_ptr.md b/base/memory/raw_ptr.md index b0876c1..85adc0d 100644 --- a/base/memory/raw_ptr.md +++ b/base/memory/raw_ptr.md
@@ -267,8 +267,8 @@ [Field destruction order](https://groups.google.com/a/chromium.org/g/memory-safety-dev/c/3sEmSnFc61I/m/ZtaeWGslAQAJ)), but you’d likely get away without any consequences. In the `raw_ptr<T>` world, an obscure crash may occur. Those crashes often manifest themselves as SEGV or -`CHECK` inside `BackupRefPtrImpl::AcquireInternal()` or -`BackupRefPtrImpl::ReleaseInternal()`, but you may also experience memory +`CHECK` inside `RawPtrBackupRefImpl::AcquireInternal()` or +`RawPtrBackupRefImpl::ReleaseInternal()`, but you may also experience memory corruption or a silent drop of UaF protection. ## Recoverable compile-time problems
diff --git a/base/message_loop/message_pump_default.cc b/base/message_loop/message_pump_default.cc index 96abf52..789545c 100644 --- a/base/message_loop/message_pump_default.cc +++ b/base/message_loop/message_pump_default.cc
@@ -23,7 +23,7 @@ namespace { #if BUILDFLAG(IS_APPLE) -bool g_use_thread_qos = true; +bool g_use_thread_qos = false; #endif } // namespace
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc index 7b6d955d..72f67b8 100644 --- a/base/message_loop/message_pump_libevent.cc +++ b/base/message_loop/message_pump_libevent.cc
@@ -153,9 +153,7 @@ #if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL) MessagePumpLibevent::MessagePumpLibevent(decltype(kUseEpoll)) - : epoll_pump_(std::make_unique<MessagePumpEpoll>()) { - epoll_pump_ = std::make_unique<MessagePumpEpoll>(); -} + : epoll_pump_(std::make_unique<MessagePumpEpoll>()) {} #endif MessagePumpLibevent::~MessagePumpLibevent() {
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index c79acd7..8ebcd47 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -203,7 +203,7 @@ return false; absl::optional<UnguessableToken> token = - UnguessableToken::Deserialize2(high, low); + UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return false; } @@ -441,14 +441,10 @@ // static FieldTrialList* FieldTrialList::global_ = nullptr; -// static -bool FieldTrialList::used_without_global_ = false; - FieldTrialList::Observer::~Observer() = default; FieldTrialList::FieldTrialList() { DCHECK(!global_); - DCHECK(!used_without_global_); global_ = this; } @@ -1350,10 +1346,8 @@ // static void FieldTrialList::Register(FieldTrial* trial, bool is_randomized_trial) { - if (!global_) { - used_without_global_ = true; - return; - } + DCHECK(global_); + AutoLock auto_lock(global_->lock_); CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); trial->AddRef(); @@ -1378,8 +1372,6 @@ bool FieldTrialList::CreateTrialsFromFieldTrialStatesInternal( const std::vector<FieldTrial::State>& entries) { DCHECK(global_); - if (entries.empty() || !global_) - return true; for (const auto& entry : entries) { FieldTrial* trial = CreateFieldTrial(entry.trial_name, entry.group_name);
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h index efa8ff6..a3417978 100644 --- a/base/metrics/field_trial.h +++ b/base/metrics/field_trial.h
@@ -152,7 +152,9 @@ subtle::Atomic32 activated; // On e.g. x86, alignof(uint64_t) is 4. Ensure consistent size and - // alignment of `pickle_size` across platforms. + // alignment of `pickle_size` across platforms. This can be considered + // to be padding for the final 32 bit value (activated). If this struct + // gains or loses fields, consider if this padding is still needed. uint32_t padding; // Size of the pickled structure, NOT the total size of this entry. @@ -291,9 +293,6 @@ virtual ~FieldTrial(); - // Return the default group name of the FieldTrial. - const std::string& default_group_name() const { return default_group_name_; } - // Marks this trial as having been registered with the FieldTrialList. Must be // called no more than once and before any |group()| calls have occurred. void SetTrialRegistered(); @@ -432,10 +431,6 @@ // registered, or to retrieve a pointer to it from the global map. static FieldTrial* Find(StringPiece trial_name); - // Returns the group number chosen for the named trial, or - // FieldTrial::kNotFinalized if the trial does not exist. - static int FindValue(StringPiece trial_name); - // Returns the group name chosen for the named trial, or the empty string if // the trial does not exist. The first call of this function on a given field // trial will mark it as active, so that its state will be reported with usage @@ -719,12 +714,6 @@ static FieldTrialList* global_; // The singleton of this class. - // This will tell us if there is an attempt to register a field - // trial or check if one-time randomization is enabled without - // creating the FieldTrialList. This is not an error, unless a - // FieldTrialList is created after that. - static bool used_without_global_; - // Lock for access to |registered_|, |observers_|, // |count_of_manually_created_field_trials_|. Lock lock_;
diff --git a/base/task/thread_pool/sequence.cc b/base/task/thread_pool/sequence.cc index b82760e..1303403 100644 --- a/base/task/thread_pool/sequence.cc +++ b/base/task/thread_pool/sequence.cc
@@ -37,6 +37,26 @@ const raw_ref<const CheckedLock> acquired_lock_; }; +void MaybeMakeCriticalClosure(TaskShutdownBehavior shutdown_behavior, + Task& task) { + switch (shutdown_behavior) { + case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN: + // Nothing to do. + break; + case TaskShutdownBehavior::SKIP_ON_SHUTDOWN: + // MakeCriticalClosure() is arguably useful for SKIP_ON_SHUTDOWN, possibly + // in combination with is_immediate=false. However, SKIP_ON_SHUTDOWN is + // the default and hence the theoretical benefits don't warrant the + // performance implications. + break; + case TaskShutdownBehavior::BLOCK_SHUTDOWN: + task.task = + MakeCriticalClosure(task.posted_from, std::move(task.task), + /*is_immediate=*/task.delayed_run_time.is_null()); + break; + } +} + } // namespace Sequence::Transaction::Transaction(Sequence* sequence) @@ -67,12 +87,8 @@ bool was_unretained = sequence()->IsEmpty() && !sequence()->has_worker_; bool queue_was_empty = sequence()->queue_.empty(); - task.task = sequence()->traits_.shutdown_behavior() == - TaskShutdownBehavior::BLOCK_SHUTDOWN - ? MakeCriticalClosure( - task.posted_from, std::move(task.task), - /*is_immediate=*/task.delayed_run_time.is_null()) - : std::move(task.task); + + MaybeMakeCriticalClosure(sequence()->traits_.shutdown_behavior(), task); sequence()->queue_.push(std::move(task)); @@ -97,11 +113,8 @@ bool top_will_change = sequence()->DelayedSortKeyWillChange(task); bool was_empty = sequence()->IsEmpty(); - task.task = - sequence()->traits_.shutdown_behavior() == - TaskShutdownBehavior::BLOCK_SHUTDOWN - ? MakeCriticalClosure(task.posted_from, std::move(task.task), false) - : std::move(task.task); + + MaybeMakeCriticalClosure(sequence()->traits_.shutdown_behavior(), task); sequence()->delayed_queue_.insert(std::move(task));
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm index 1a332e33..197d50e 100644 --- a/base/threading/platform_thread_mac.mm +++ b/base/threading/platform_thread_mac.mm
@@ -92,7 +92,7 @@ #endif ); -const Feature kUseThreadQoSMac{"UseThreadQoSMac", FEATURE_ENABLED_BY_DEFAULT}; +const Feature kUseThreadQoSMac{"UseThreadQoSMac", FEATURE_DISABLED_BY_DEFAULT}; namespace { @@ -328,7 +328,6 @@ break; case ThreadType::kResourceEfficient: if (use_thread_qos) { - priority = ThreadPriorityForTest::kUtility; pthread_set_qos_class_self_np(QOS_CLASS_UTILITY, 0); break; }
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc index a4e34ee..48b558f 100644 --- a/base/threading/platform_thread_unittest.cc +++ b/base/threading/platform_thread_unittest.cc
@@ -488,13 +488,8 @@ ThreadPriorityForTest::kBackground); TestPriorityResultingFromThreadType(ThreadType::kUtility, ThreadPriorityForTest::kUtility); -#if BUILDFLAG(IS_APPLE) - TestPriorityResultingFromThreadType(ThreadType::kResourceEfficient, - ThreadPriorityForTest::kUtility); -#else TestPriorityResultingFromThreadType(ThreadType::kResourceEfficient, ThreadPriorityForTest::kNormal); -#endif // BUILDFLAG(IS_APPLE) TestPriorityResultingFromThreadType(ThreadType::kDefault, ThreadPriorityForTest::kNormal); #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 73e9a08..d9cb025 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc
@@ -24,6 +24,7 @@ #include "base/threading/scoped_thread_priority.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" +#include "base/threading/threading_features.h" #include "base/time/time_override.h" #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" @@ -41,12 +42,18 @@ BASE_FEATURE(kUseThreadPriorityLowest, "UseThreadPriorityLowest", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kAboveNormalCompositingBrowserWin, + "AboveNormalCompositingBrowserWin", + base::FEATURE_DISABLED_BY_DEFAULT); namespace { // Flag used to set thread priority to |THREAD_PRIORITY_LOWEST| for // |kUseThreadPriorityLowest| Feature. std::atomic<bool> g_use_thread_priority_lowest{false}; +// Flag used to map Compositing ThreadType |THREAD_PRIORITY_ABOVE_NORMAL| on the +// UI thread for |kAboveNormalCompositingBrowserWin| Feature. +std::atomic<bool> g_above_normal_compositing_browser{false}; // These values are sometimes returned by ::GetThreadPriority(). constexpr int kWinNormalPriority1 = 5; @@ -370,7 +377,8 @@ void SetCurrentThreadPriority(ThreadType thread_type, MessagePumpType pump_type_hint) { if (thread_type == ThreadType::kCompositing && - pump_type_hint == MessagePumpType::UI) { + pump_type_hint == MessagePumpType::UI && + !g_above_normal_compositing_browser) { // Ignore kCompositing thread type for UI thread as Windows has a // priority boost mechanism. See // https://docs.microsoft.com/en-us/windows/win32/procthread/priority-boosts @@ -557,6 +565,9 @@ g_use_thread_priority_lowest.store( FeatureList::IsEnabled(kUseThreadPriorityLowest), std::memory_order_relaxed); + g_above_normal_compositing_browser.store( + FeatureList::IsEnabled(kAboveNormalCompositingBrowserWin), + std::memory_order_relaxed); } // static
diff --git a/base/threading/threading_features.h b/base/threading/threading_features.h index 524d567..856c9efe 100644 --- a/base/threading/threading_features.h +++ b/base/threading/threading_features.h
@@ -26,6 +26,10 @@ extern const BASE_EXPORT Feature kUseThreadQoSMac; #endif +#if BUILDFLAG(IS_WIN) +BASE_EXPORT BASE_DECLARE_FEATURE(kAboveNormalCompositingBrowserWin); +#endif + BASE_EXPORT BASE_DECLARE_FEATURE(kEnableHangWatcher); } // namespace base
diff --git a/base/trace_event/memory_infra_background_allowlist.cc b/base/trace_event/memory_infra_background_allowlist.cc index fe2b7339..22c1d336 100644 --- a/base/trace_event/memory_infra_background_allowlist.cc +++ b/base/trace_event/memory_infra_background_allowlist.cc
@@ -70,6 +70,7 @@ "PartitionAlloc.AddressSpace", "ProcessMemoryMetrics", "SharedContextState", + "SharedImageManager", "SharedMemoryTracker", "Skia", "Sql",
diff --git a/base/unguessable_token.cc b/base/unguessable_token.cc index af8afb2..aa7423f8 100644 --- a/base/unguessable_token.cc +++ b/base/unguessable_token.cc
@@ -33,19 +33,8 @@ } // static -UnguessableToken UnguessableToken::Deserialize(uint64_t high, uint64_t low) { - // Receiving a zeroed out UnguessableToken from another process means that it - // was never initialized via Create(). The real check for this is in the - // StructTraits in mojo/public/cpp/base/unguessable_token_mojom_traits.cc - // where a zero-ed out token will fail to deserialize. This DCHECK is a - // backup check. - DCHECK(!(high == 0 && low == 0)); - return UnguessableToken(Token{high, low}); -} - -// static -absl::optional<UnguessableToken> UnguessableToken::Deserialize2(uint64_t high, - uint64_t low) { +absl::optional<UnguessableToken> UnguessableToken::Deserialize(uint64_t high, + uint64_t low) { // Receiving a zeroed out UnguessableToken from another process means that it // was never initialized via Create(). Since this method might also be used to // create an UnguessableToken from data on disk, we will handle this case more
diff --git a/base/unguessable_token.h b/base/unguessable_token.h index e8134091..d1e57a1 100644 --- a/base/unguessable_token.h +++ b/base/unguessable_token.h
@@ -56,23 +56,14 @@ // default constructor. static const UnguessableToken& Null(); - // NOTE: This method is deprecated and will soon be replaced by the one below. - // Return a UnguessableToken built from the high/low bytes provided. + // Return an UnguessableToken built from the high/low bytes provided. // It should only be used in deserialization scenarios. // - // NOTE: If the deserialized token is empty, it means that it was never + // NOTE: If the returned `absl::optional` does not have a value, it means that + // `high` and `low` correspond to an `UnguesssableToken` that was never // initialized via Create(). This is a security issue, and should be handled. - static UnguessableToken Deserialize(uint64_t high, uint64_t low); - - // Return a UnguessableToken built from the high/low bytes provided. - // It should only be used in deserialization scenarios. - // - // NOTE: Once `Deserialize` above is removed, this will be renamed to that. - // - // NOTE: If the deserialized token is empty, it means that it was never - // initialized via Create(). This is a security issue, and should be handled. - static absl::optional<UnguessableToken> Deserialize2(uint64_t high, - uint64_t low); + static absl::optional<UnguessableToken> Deserialize(uint64_t high, + uint64_t low); // Creates an empty UnguessableToken. // Assign to it with Create() before using it. @@ -116,7 +107,9 @@ #if defined(UNIT_TEST) static UnguessableToken CreateForTesting(uint64_t high, uint64_t low) { - return Deserialize(high, low); + absl::optional<UnguessableToken> token = Deserialize(high, low); + DCHECK(token.has_value()); + return token.value(); } #endif
diff --git a/base/unguessable_token_unittest.cc b/base/unguessable_token_unittest.cc index ff88f15..1064a35 100644 --- a/base/unguessable_token_unittest.cc +++ b/base/unguessable_token_unittest.cc
@@ -20,7 +20,7 @@ } TEST(UnguessableTokenTest, VerifyEveryBit) { - absl::optional<UnguessableToken> token = UnguessableToken::Deserialize2(1, 2); + absl::optional<UnguessableToken> token = UnguessableToken::Deserialize(1, 2); ASSERT_TRUE(token.has_value()); uint64_t high = 1; uint64_t low = 2; @@ -28,7 +28,7 @@ for (uint64_t bit = 1; bit != 0; bit <<= 1) { uint64_t new_high = high ^ bit; absl::optional<UnguessableToken> new_token = - UnguessableToken::Deserialize2(new_high, low); + UnguessableToken::Deserialize(new_high, low); ASSERT_TRUE(new_token.has_value()); EXPECT_FALSE(*token == *new_token); } @@ -36,7 +36,7 @@ for (uint64_t bit = 1; bit != 0; bit <<= 1) { uint64_t new_low = low ^ bit; absl::optional<UnguessableToken> new_token = - UnguessableToken::Deserialize2(high, new_low); + UnguessableToken::Deserialize(high, new_low); ASSERT_TRUE(new_token.has_value()); EXPECT_FALSE(*token == *new_token); } @@ -45,9 +45,9 @@ TEST(UnguessableTokenTest, VerifyEqualityOperators) { // Deserialize is used for testing purposes. // Use UnguessableToken::Create() in production code instead. - UnguessableToken token = UnguessableToken::Deserialize2(1, 2).value(); - UnguessableToken same_token = UnguessableToken::Deserialize2(1, 2).value(); - UnguessableToken diff_token = UnguessableToken::Deserialize2(1, 3).value(); + UnguessableToken token = UnguessableToken::Deserialize(1, 2).value(); + UnguessableToken same_token = UnguessableToken::Deserialize(1, 2).value(); + UnguessableToken diff_token = UnguessableToken::Deserialize(1, 3).value(); UnguessableToken empty_token; EXPECT_TRUE(token == token); @@ -96,7 +96,7 @@ EXPECT_TRUE(low); absl::optional<UnguessableToken> Deserialized = - UnguessableToken::Deserialize2(high, low); + UnguessableToken::Deserialize(high, low); ASSERT_TRUE(Deserialized.has_value()); EXPECT_EQ(token, *Deserialized); } @@ -104,7 +104,7 @@ // Common case (~88% of the time) - no leading zeroes in high_ nor low_. TEST(UnguessableTokenTest, VerifyToString1) { UnguessableToken token = - UnguessableToken::Deserialize2(0x1234567890ABCDEF, 0xFEDCBA0987654321) + UnguessableToken::Deserialize(0x1234567890ABCDEF, 0xFEDCBA0987654321) .value(); std::string expected = "1234567890ABCDEFFEDCBA0987654321"; @@ -118,7 +118,7 @@ // Less common case - leading zeroes in high_ or low_ (testing with both). TEST(UnguessableTokenTest, VerifyToString2) { - UnguessableToken token = UnguessableToken::Deserialize2(0x123, 0xABC).value(); + UnguessableToken token = UnguessableToken::Deserialize(0x123, 0xABC).value(); std::string expected = "00000000000001230000000000000ABC"; EXPECT_EQ(expected, token.ToString()); @@ -131,16 +131,16 @@ TEST(UnguessableTokenTest, VerifyToStringUniqueness) { const UnguessableToken token1 = - UnguessableToken::Deserialize2(0x0000000012345678, 0x0000000123456789) + UnguessableToken::Deserialize(0x0000000012345678, 0x0000000123456789) .value(); const UnguessableToken token2 = - UnguessableToken::Deserialize2(0x0000000123456781, 0x0000000023456789) + UnguessableToken::Deserialize(0x0000000123456781, 0x0000000023456789) .value(); EXPECT_NE(token1.ToString(), token2.ToString()); } TEST(UnguessableTokenTest, VerifyDeserializeZeroes) { - absl::optional<UnguessableToken> token = UnguessableToken::Deserialize2(0, 0); + absl::optional<UnguessableToken> token = UnguessableToken::Deserialize(0, 0); EXPECT_FALSE(token.has_value()); } @@ -150,23 +150,23 @@ // Use UnguessableToken::Create() in production code instead. { SCOPED_TRACE("a.low < b.low and a.high == b.high."); - TestSmallerThanOperator(UnguessableToken::Deserialize2(0, 1).value(), - UnguessableToken::Deserialize2(0, 5).value()); + TestSmallerThanOperator(UnguessableToken::Deserialize(0, 1).value(), + UnguessableToken::Deserialize(0, 5).value()); } { SCOPED_TRACE("a.low == b.low and a.high < b.high."); - TestSmallerThanOperator(UnguessableToken::Deserialize2(1, 0).value(), - UnguessableToken::Deserialize2(5, 0).value()); + TestSmallerThanOperator(UnguessableToken::Deserialize(1, 0).value(), + UnguessableToken::Deserialize(5, 0).value()); } { SCOPED_TRACE("a.low < b.low and a.high < b.high."); - TestSmallerThanOperator(UnguessableToken::Deserialize2(1, 1).value(), - UnguessableToken::Deserialize2(5, 5).value()); + TestSmallerThanOperator(UnguessableToken::Deserialize(1, 1).value(), + UnguessableToken::Deserialize(5, 5).value()); } { SCOPED_TRACE("a.low > b.low and a.high < b.high."); - TestSmallerThanOperator(UnguessableToken::Deserialize2(1, 10).value(), - UnguessableToken::Deserialize2(10, 1).value()); + TestSmallerThanOperator(UnguessableToken::Deserialize(1, 10).value(), + UnguessableToken::Deserialize(10, 1).value()); } }
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index 24e99bc..e43c435c1 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc
@@ -312,13 +312,16 @@ uint32_t minor, uint32_t build) { if (major == 11) { - if (build >= 22621) { - return Version::WIN11_22H2; - } + // We know nothing about this version of Windows or even if it exists. + // Known Windows 11 versions have a major number 10 and are thus handled by + // the == 10 block below. return Version::WIN11; } if (major == 10) { + if (build >= 22621) { + return Version::WIN11_22H2; + } if (build >= 22000) { return Version::WIN11; }
diff --git a/base/win/windows_version_unittest.cc b/base/win/windows_version_unittest.cc index 41720a9..e1a7506 100644 --- a/base/win/windows_version_unittest.cc +++ b/base/win/windows_version_unittest.cc
@@ -24,13 +24,11 @@ } TEST(OSInfo, MajorMinorBuildToVersion) { - EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 32767), - Version::WIN11_22H2); - EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 22621), - Version::WIN11_22H2); - EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 22000), Version::WIN11); EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 0), Version::WIN11); - EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 32767), Version::WIN11); + EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 32767), + Version::WIN11_22H2); + EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 22621), + Version::WIN11_22H2); EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 22000), Version::WIN11); EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 21999), Version::SERVER_2022);
diff --git a/build/android/gyp/bundletool.py b/build/android/gyp/bundletool.py index 6dfe129..79151335 100755 --- a/build/android/gyp/bundletool.py +++ b/build/android/gyp/bundletool.py
@@ -24,12 +24,10 @@ BUNDLETOOL_JAR_PATH = os.path.join(BUNDLETOOL_DIR, 'bundletool.jar') -def RunBundleTool(args, warnings_as_errors=(), print_stdout=False): - # Use () instead of None because command-line flags are None by default. - verify = warnings_as_errors == () or warnings_as_errors +def RunBundleTool(args, print_stdout=False): # ASAN builds failed with the default of 1GB (crbug.com/1120202). # Bug for bundletool: https://issuetracker.google.com/issues/165911616 - cmd = build_utils.JavaCmd(verify, xmx='4G') + cmd = build_utils.JavaCmd(xmx='4G') cmd += ['-jar', BUNDLETOOL_JAR_PATH] cmd += args logging.debug(' '.join(cmd))
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py index be309a0..fa6d03fc 100755 --- a/build/android/gyp/compile_java.py +++ b/build/android/gyp/compile_java.py
@@ -717,7 +717,8 @@ javac_args = [ '-g', - # We currently target JDK 11 everywhere. + # We currently target JDK 11 everywhere, since Mockito is broken by JDK17. + # See crbug.com/1409661 for more details. '--release', '11', # Chromium only allows UTF8 source files. Being explicit avoids @@ -752,6 +753,22 @@ '-XepPatchChecks:,' + ','.join(ERRORPRONE_CHECKS_TO_APPLY) ] + # These are required to use JDK 16, and are taken directly from + # https://errorprone.info/docs/installation + javac_args += [ + '-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=' + 'ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED', + '-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED', + '-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED', + '-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED', + ] + javac_args += ['-XDcompilePolicy=simple', ' '.join(errorprone_flags)] # This flag quits errorprone after checks and before code generation, since
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py index 8b3c797a..3fba5367 100755 --- a/build/android/gyp/create_app_bundle.py +++ b/build/android/gyp/create_app_bundle.py
@@ -532,7 +532,7 @@ f.write(bundle_config) logging.info('Running bundletool') - cmd_args = build_utils.JavaCmd(options.warnings_as_errors) + [ + cmd_args = build_utils.JavaCmd() + [ '-jar', bundletool.BUNDLETOOL_JAR_PATH, 'build-bundle',
diff --git a/build/android/gyp/create_java_binary_script.py b/build/android/gyp/create_java_binary_script.py index 909c008..bce0a57 100755 --- a/build/android/gyp/create_java_binary_script.py +++ b/build/android/gyp/create_java_binary_script.py
@@ -91,12 +91,12 @@ action='append', default=[], help='Classpath for running the jar.') - parser.add_argument('--noverify', - action='store_true', - help='JVM flag: noverify.') parser.add_argument('--tiered-stop-at-level-one', action='store_true', help='JVM flag: -XX:TieredStopAtLevel=1.') + parser.add_argument('--use-jdk-11', + action='store_true', + help='Use older JDK11 instead of modern JDK.') parser.add_argument('extra_program_args', nargs='*', help='This captures all ' @@ -105,8 +105,6 @@ args = parser.parse_args(argv) extra_flags = [f'java_cmd.append("-Xmx{args.max_heap_size}")'] - if args.noverify: - extra_flags.append('java_cmd.append("-noverify")') if args.tiered_stop_at_level_one: extra_flags.append('java_cmd.append("-XX:TieredStopAtLevel=1")') @@ -116,8 +114,12 @@ run_dir = os.path.dirname(args.output) classpath = [os.path.relpath(p, run_dir) for p in classpath] - java_path = os.path.relpath( - os.path.join(build_utils.JAVA_HOME, 'bin', 'java'), run_dir) + + if args.use_jdk_11: + java_home = build_utils.JAVA_11_HOME_DEPRECATED + else: + java_home = build_utils.JAVA_HOME + java_path = os.path.relpath(os.path.join(java_home, 'bin', 'java'), run_dir) with build_utils.AtomicOutput(args.output, mode='w') as script: script.write(
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py index 0b257709..abad5d7 100755 --- a/build/android/gyp/dex.py +++ b/build/android/gyp/dex.py
@@ -422,7 +422,7 @@ def MergeDexForIncrementalInstall(r8_jar_path, src_paths, dest_dex_jar, min_api): - dex_cmd = build_utils.JavaCmd(verify=False, xmx=_DEX_XMX) + [ + dex_cmd = build_utils.JavaCmd(xmx=_DEX_XMX) + [ '-cp', r8_jar_path, 'com.android.tools.r8.D8', @@ -460,7 +460,7 @@ final_dex_inputs = list(options.class_inputs) final_dex_inputs += options.dex_inputs - dex_cmd = build_utils.JavaCmd(options.warnings_as_errors, xmx=_DEX_XMX) + dex_cmd = build_utils.JavaCmd(xmx=_DEX_XMX) if options.dump_inputs: dex_cmd += ['-Dcom.android.tools.r8.dumpinputtofile=d8inputs.zip']
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py index f7581c7..aaf66c2 100644 --- a/build/android/gyp/finalize_apk.py +++ b/build/android/gyp/finalize_apk.py
@@ -38,7 +38,7 @@ else: signer_input_path = unsigned_apk_path - sign_cmd = build_utils.JavaCmd(warnings_as_errors) + [ + sign_cmd = build_utils.JavaCmd() + [ '-jar', apksigner_path, 'sign',
diff --git a/build/android/gyp/merge_manifest.py b/build/android/gyp/merge_manifest.py index 1389e67a..9acc5fe 100755 --- a/build/android/gyp/merge_manifest.py +++ b/build/android/gyp/merge_manifest.py
@@ -87,7 +87,7 @@ args = parser.parse_args(argv) with build_utils.AtomicOutput(args.output) as output: - cmd = build_utils.JavaCmd(args.warnings_as_errors) + [ + cmd = build_utils.JavaCmd() + [ '-cp', args.manifest_merger_jar, _MANIFEST_MERGER_MAIN_CLASS,
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py index 7c4e0dd6..fa01d19 100755 --- a/build/android/gyp/proguard.py +++ b/build/android/gyp/proguard.py
@@ -247,7 +247,7 @@ base_context = split_contexts_by_name['base'] # R8 OOMs with the default xmx=1G. - cmd = build_utils.JavaCmd(options.warnings_as_errors, xmx='2G') + [ + cmd = build_utils.JavaCmd(xmx='2G') + [ # Allows -whyareyounotinlining, which we don't have by default, but # which is useful for one-off queries. '-Dcom.android.tools.r8.experimental.enablewhyareyounotinlining=1', @@ -337,7 +337,7 @@ def _OutputKeepRules(r8_path, input_paths, classpath, targets_re_string, keep_rules_output): - cmd = build_utils.JavaCmd(False) + [ + cmd = build_utils.JavaCmd() + [ '-cp', r8_path, 'com.android.tools.r8.tracereferences.TraceReferences', '--map-diagnostics:MissingDefinitionsDiagnostic', 'error', 'warning', '--keep-rules', '--output', keep_rules_output @@ -356,7 +356,7 @@ def _CheckForMissingSymbols(r8_path, dex_files, classpath, warnings_as_errors, error_title): - cmd = build_utils.JavaCmd(warnings_as_errors) + [ + cmd = build_utils.JavaCmd() + [ '-cp', r8_path, 'com.android.tools.r8.tracereferences.TraceReferences', '--map-diagnostics:MissingDefinitionsDiagnostic', 'error', 'warning', '--check'
diff --git a/build/android/gyp/turbine.py b/build/android/gyp/turbine.py index 18e49dd..1c8d1f48 100755 --- a/build/android/gyp/turbine.py +++ b/build/android/gyp/turbine.py
@@ -76,7 +76,7 @@ # Turbine is run only on .java files. java_files = [f for f in files if f.endswith('.java')] - cmd = build_utils.JavaCmd(options.warnings_as_errors) + [ + cmd = build_utils.JavaCmd() + [ '-classpath', options.turbine_jar_path, 'com.google.turbine.main.Main' ] javac_cmd = [
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index da4a705..851c17b 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -39,6 +39,10 @@ JAVAP_PATH = os.path.join(JAVA_HOME, 'bin', 'javap') KOTLIN_HOME = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'kotlinc', 'current') KOTLINC_PATH = os.path.join(KOTLIN_HOME, 'bin', 'kotlinc') +# Please avoid using this. Our JAVA_HOME is using a newer and actively patched +# JDK. +JAVA_11_HOME_DEPRECATED = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'jdk11', + 'current') try: string_types = basestring @@ -46,17 +50,12 @@ string_types = (str, bytes) -def JavaCmd(verify=True, xmx='1G'): +def JavaCmd(xmx='1G'): ret = [os.path.join(JAVA_HOME, 'bin', 'java')] # Limit heap to avoid Java not GC'ing when it should, and causing # bots to OOM when many java commands are runnig at the same time # https://crbug.com/1098333 ret += ['-Xmx' + xmx] - - # Disable bytecode verification for local builds gives a ~2% speed-up. - if not verify: - ret += ['-noverify'] - return ret
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 8317907b..d403008 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -2109,7 +2109,7 @@ GetDepConfig(p) for p in GetAllDepsConfigsInOrder( deps_configs_paths, filter_func=ExcludeRecursiveResourcesDeps) ] - config['extra_android_manifests'] = [] + config['extra_android_manifests'] = list(mergeable_android_manifests) for c in extra_manifest_deps: config['extra_android_manifests'].extend( c.get('mergeable_android_manifests', []))
diff --git a/build/android/pylib/local/emulator/avd.py b/build/android/pylib/local/emulator/avd.py index be234dd..76de996 100644 --- a/build/android/pylib/local/emulator/avd.py +++ b/build/android/pylib/local/emulator/avd.py
@@ -41,6 +41,8 @@ # These files are used as backing files for corresponding qcow2 images. _BACKING_FILES = ('system.img', 'vendor.img') +_DEFAULT_JAVA_HOME = os.path.join(constants.DIR_SOURCE_ROOT, 'third_party', + 'jdk', 'current') _DEFAULT_AVDMANAGER_PATH = os.path.join(constants.ANDROID_SDK_ROOT, 'cmdline-tools', 'latest', 'bin', 'avdmanager') @@ -168,6 +170,8 @@ self._avd_home, 'AVDMANAGER_OPTS': '-Dcom.android.sdkmanager.toolsdir=%s' % fake_tools_dir, + 'JAVA_HOME': + _DEFAULT_JAVA_HOME, }) def Create(self, avd_name, system_image, force=False):
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index e675e08..1fa42b1 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -590,6 +590,16 @@ template("component") { if (is_component_build) { _component_mode = "shared_library" + + # Generate a unique output_name for a shared library if not set by invoker. + if (!defined(invoker.output_name)) { + _output_name = get_label_info(":$target_name", "label_no_toolchain") + _output_name = + string_replace(_output_name, "$target_name:$target_name", target_name) + _output_name = string_replace(_output_name, "//", "") + _output_name = string_replace(_output_name, "/", "_") + _output_name = string_replace(_output_name, ":", "_") + } } else if (defined(invoker.static_component_type)) { assert(invoker.static_component_type == "static_library" || invoker.static_component_type == "source_set") @@ -602,6 +612,9 @@ _component_mode = "static_library" } target(_component_mode, target_name) { + if (defined(_output_name)) { + output_name = _output_name + } forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) }
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 1cb6c57..bf183e4 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1393,9 +1393,6 @@ ] data += [ _jacoco_host_jar ] } - if (use_jacoco_coverage || !treat_warnings_as_errors) { - args += [ "--noverify" ] - } if (defined(invoker.tiered_stop_at_level_one) && invoker.tiered_stop_at_level_one) { args += [ "--tiered-stop-at-level-one" ] @@ -1409,6 +1406,12 @@ if (defined(invoker.wrapper_script_args)) { args += [ "--" ] + invoker.wrapper_script_args } + if (defined(invoker.use_jdk_11) && invoker.use_jdk_11) { + args += [ "--use-jdk-11" ] + deps += [ "//third_party/jdk11:java_data" ] + } else { + deps += [ "//third_party/jdk:java_data" ] + } } } @@ -3727,6 +3730,10 @@ } if (_kt_files != []) { + assert( + _kt_files == [ "android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.kt" ], + "Only a single Kotlin file is allowed for now. Feel free to " + + "remove this assert when experimenting locally.") _compile_kt_target_name = "${_main_target_name}__compile_kt" _kotlinc_jar_path = "$target_out_dir/$_output_name.kotlinc.jar" _kotlin_interface_jar_path = @@ -4059,10 +4066,7 @@ if (defined(invoker.wrapper_script_name)) { script_name = invoker.wrapper_script_name } - deps = [ - ":$_build_config_target_name", - "//third_party/jdk:java_data", - ] + deps = [ ":$_build_config_target_name" ] if (_is_robolectric) { # For robolectric tests, we also add the normal sdk jar to the # classpath since whenever we start using a new Android SDK, @@ -4071,6 +4075,10 @@ # new SDK classes, so providing our normal SDK will allow these # classes to resolve. For an example, see crbug.com/1350963. extra_classpath_jars = [ android_sdk_jar ] + + # Mockito bug with JDK17 requires us to use JDK11 until we find a fix + # for crbug.com/1409661. + use_jdk_11 = true } } }
diff --git a/build/config/rust.gni b/build/config/rust.gni index 6264492..96e9fe8 100644 --- a/build/config/rust.gni +++ b/build/config/rust.gni
@@ -4,6 +4,7 @@ import("//build/config/chrome_build.gni") import("//build/config/compiler/compiler.gni") +import("//build/config/sanitizers/sanitizers.gni") import("//build/toolchain/toolchain.gni") if (is_android) { @@ -73,6 +74,8 @@ # https://crbug.com/1229423 # NB this may be overridden by individual toolchains rustc_can_link = !is_android + + host_toolchain_no_sanitizers = host_toolchain } # Set rustc_version to the in-tree toolchain version, if enabled, or otherwise @@ -190,3 +193,15 @@ # here. This is not the complete command-line: toolchains should add -o # and probably --emit arguments too. rustc_common_args = "--crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}}" + +# Rust procedural macros are shared objects loaded into a prebuilt host rustc +# binary. To build them, we obviously need to build for the host. Not only that, +# but because the host rustc is prebuilt, it lacks the machinery to be able to +# load shared objects built using sanitizers (ASAN etc.) For that reason, we need +# to use a host toolchain that lacks sanitizers. This is only strictly necessary +# for procedural macros, but we may also choose to build standalone Rust host +# executable tools using the same toolchain, as they're likely to depend upon +# similar dependencies (syn, quote etc.) and it saves a little build time. +if (using_sanitizer || toolchain_disables_sanitizers) { + host_toolchain_no_sanitizers = "${host_toolchain}_no_sanitizers" +}
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index ebc3c3e2..3db3b91 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -119,7 +119,7 @@ "HWASan only supported on Android ARM64 builds.") # Disable sanitizers for non-target toolchains. -if (!is_a_target_toolchain) { +if (!is_a_target_toolchain || toolchain_disables_sanitizers) { is_asan = false is_cfi = false is_hwasan = false
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index eb74071..e9dd7a0a 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -11.20230125.1.1 +11.20230126.1.1
diff --git a/build/fuchsia/test/compatible_utils_unittests.py b/build/fuchsia/test/compatible_utils_unittests.py index f04d131..e6a03cb 100755 --- a/build/fuchsia/test/compatible_utils_unittests.py +++ b/build/fuchsia/test/compatible_utils_unittests.py
@@ -14,6 +14,7 @@ import compatible_utils +@unittest.skipIf(os.name == 'nt', 'Fuchsia tests not supported on Windows') class CompatibleUtilsTest(unittest.TestCase): """Test compatible_utils.py methods."""
diff --git a/build/fuchsia/test/coveragetest.py b/build/fuchsia/test/coveragetest.py index 6d8121a..11e8d11 100755 --- a/build/fuchsia/test/coveragetest.py +++ b/build/fuchsia/test/coveragetest.py
@@ -6,6 +6,7 @@ import importlib import io +import os import sys import unittest @@ -20,6 +21,10 @@ def main(): """Gather coverage data, ensure included files are 100% covered.""" + # Fuchsia tests not supported on Windows + if os.name == 'nt': + return 0 + cov = coverage.coverage(data_file=None, include=COVERED_FILES, config_file=True)
diff --git a/build/rust/cargo_crate.gni b/build/rust/cargo_crate.gni index 29143aa4..ef30626 100644 --- a/build/rust/cargo_crate.gni +++ b/build/rust/cargo_crate.gni
@@ -243,7 +243,8 @@ # Extra targets required to make build script work action("${build_script_name}_output") { script = rebase_path("//build/rust/run_build_script.py") - build_script_target = ":${build_script_name}($host_toolchain)" + build_script_target = + ":${build_script_name}($host_toolchain_no_sanitizers)" deps = [ build_script_target ] _build_script_exe_dir = @@ -296,7 +297,7 @@ } } - if (current_toolchain == host_toolchain) { + if (current_toolchain == host_toolchain_no_sanitizers) { rust_target(build_script_name) { target_type = "executable" sources = invoker.build_sources
diff --git a/build/rust/rust_target.gni b/build/rust/rust_target.gni index b0106b77..1407e6f 100644 --- a/build/rust/rust_target.gni +++ b/build/rust/rust_target.gni
@@ -127,7 +127,7 @@ } _forward_to_host_toolchain = false if (invoker.target_type == "rust_proc_macro") { - if (current_toolchain != host_toolchain) { + if (current_toolchain != host_toolchain_no_sanitizers) { _forward_to_host_toolchain = true } _main_target_suffix = "${target_name}__proc_macro" @@ -194,8 +194,9 @@ if (defined(_visibility)) { visibility = _visibility } - public_deps = - [ ":${_target_name}${_main_target_suffix}($host_toolchain)" ] + public_deps = [ + ":${_target_name}${_main_target_suffix}($host_toolchain_no_sanitizers)", + ] } not_needed(invoker, "*")
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index 00400ab..273aab5 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -122,7 +122,7 @@ "race:ipcz::BlockAllocator::Allocate\n" // https://crbug.com/1405439 - "race:perfetto::internal::g_category_state_storage\n" + "race:perfetto::perfetto_track_event::internal::g_category_state_storage\n" "race:perfetto::DataSource*::static_state_\n" "race:perfetto::Tracing::ResetForTesting\n"
diff --git a/build/toolchain/apple/toolchain.gni b/build/toolchain/apple/toolchain.gni index 7f65f49..5cd7051 100644 --- a/build/toolchain/apple/toolchain.gni +++ b/build/toolchain/apple/toolchain.gni
@@ -85,8 +85,11 @@ "trim scope") # Shared toolchain definition. Invocations should set current_os to set the -# build args in this definition. -template("apple_toolchain") { +# build args in this definition. This is titled "single_apple_toolchain" +# because it makes exactly one toolchain. Callers will normally want to +# invoke instead "apple_toolchain" which may make an additional toolchain +# without sanitizers. +template("single_apple_toolchain") { toolchain(target_name) { # When invoking this toolchain not as the default one, these args will be # passed to the build. They are ignored when this is the default toolchain. @@ -102,6 +105,10 @@ # set on those toolchains. host_toolchain = host_toolchain + # Similarly for the host toolchain which can be used to make .dylibs + # that will successfully load into prebuilt tools. + host_toolchain_no_sanitizers = host_toolchain_no_sanitizers + # Respect the global setting for whether rustc can make binaries. rustc_can_link = rustc_can_link } @@ -733,3 +740,41 @@ } } } + +# Makes a single Apple toolchain, or possibly two if we need a +# sanitizer-free equivalent. +template("apple_toolchain") { + single_apple_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "visibility", + "test_only", + ]) + + # No need to forward visibility and test_only as they apply to targets not + # toolchains, but presubmit checks require that we explicitly exclude them + } + + if (using_sanitizer) { + # Make an additional toolchain with no sanitizers. + single_apple_toolchain("${target_name}_no_sanitizers") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "toolchain_args", + "visibility", + "test_only", + ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_disables_sanitizers = true + } + } + } +}
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni index 48f9317..6c820c3 100644 --- a/build/toolchain/gcc_toolchain.gni +++ b/build/toolchain/gcc_toolchain.gni
@@ -107,7 +107,11 @@ # Location of the strip executable. When specified, strip will be run on # all shared libraries and executables as they are built. The pre-stripped # artifacts will be put in lib.unstripped/ and exe.unstripped/. -template("gcc_toolchain") { +# +# Callers will normally want to invoke "gcc_toolchain" instead, which makes +# a toolchain just like this but may additionally create an extra toolchain +# without sanitizers for host-side tools. +template("single_gcc_toolchain") { toolchain(target_name) { assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value") assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") @@ -145,6 +149,10 @@ # set on those toolchains. host_toolchain = host_toolchain + # The same applies to the toolchain we use to build Rust procedural + # macros, which is probably the same but might have sanitizers disabled. + host_toolchain_no_sanitizers = host_toolchain_no_sanitizers + if (!defined(invoker_toolchain_args.v8_current_cpu)) { v8_current_cpu = invoker_toolchain_args.current_cpu } @@ -777,6 +785,44 @@ } } +# Makes a single GCC toolchain, or possibly two if we need +# an equivalent toolchain without sanitizers. +template("gcc_toolchain") { + single_gcc_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "visibility", + "test_only", + ]) + + # No need to forward visibility and test_only as they apply to targets not + # toolchains, but presubmit checks require that we explicitly exclude them + } + + if (using_sanitizer) { + # Make an additional toolchain with no sanitizers. + single_gcc_toolchain("${target_name}_no_sanitizers") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "toolchain_args", + "visibility", + "test_only", + ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_disables_sanitizers = true + } + } + } +} + # This is a shorthand for gcc_toolchain instances based on the Chromium-built # version of Clang. Only the toolchain_cpu and toolchain_os variables need to # be specified by the invoker, and optionally toolprefix if it's a
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index 9d37839..c9558ee8 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni
@@ -19,6 +19,11 @@ # Used for binary size analysis. generate_linker_map = is_android && is_official_build + + # Whether this toolchain should avoid building any sanitizer support + # because it's a host toolchain where we aim to make shared objects that may + # be loaded by prebuilt binaries without sanitizer support. + toolchain_disables_sanitizers = false } if (generate_linker_map) { @@ -90,6 +95,10 @@ copy_command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})" } +if (!defined(toolchain_disables_sanitizers)) { + toolchain_disables_sanitizers = false +} + # This variable is true if the current toolchain is one of the target # toolchains, i.e. a toolchain which is being used to build the main Chrome # binary. This generally means "not the host toolchain", but in the case where
diff --git a/build/toolchain/win/toolchain.gni b/build/toolchain/win/toolchain.gni index 275cfcf9..a9b9674 100644 --- a/build/toolchain/win/toolchain.gni +++ b/build/toolchain/win/toolchain.gni
@@ -26,13 +26,17 @@ _clang_bin_path = rebase_path("$clang_base_path/bin", root_build_dir) +# Makes a single MSVC toolchain. Callers should normally instead invoke +# "msvc_toolchain" which might make an additional toolchain available +# without sanitizers if required. +# # Parameters: # environment: File name of environment file. # # You would also define a toolchain_args variable with at least these set: # current_cpu: current_cpu to pass as a build arg # current_os: current_os to pass as a build arg -template("msvc_toolchain") { +template("single_msvc_toolchain") { toolchain(target_name) { # When invoking this toolchain not as the default one, these args will be # passed to the build. They are ignored when this is the default toolchain. @@ -43,6 +47,9 @@ # This value needs to be passed through unchanged. host_toolchain = host_toolchain + # This value needs to be passed through unchanged. + host_toolchain_no_sanitizers = host_toolchain_no_sanitizers + # Respect the global setting for whether rustc can make binaries. rustc_can_link = rustc_can_link } @@ -493,6 +500,44 @@ } } +# Makes a single MSVC toolchain, or possibly two if we +# need an additional toolchain without sanitizers enabled. +template("msvc_toolchain") { + single_msvc_toolchain(target_name) { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "visibility", + "test_only", + ]) + + # No need to forward visibility and test_only as they apply to targets not + # toolchains, but presubmit checks require that we explicitly exclude them + } + + if (using_sanitizer) { + # Make an additional toolchain with no sanitizers. + single_msvc_toolchain("${target_name}_no_sanitizers") { + assert(defined(invoker.toolchain_args), + "Toolchains must declare toolchain_args") + forward_variables_from(invoker, + "*", + [ + "toolchain_args", + "visibility", + "test_only", + ]) + toolchain_args = { + # Populate toolchain args from the invoker. + forward_variables_from(invoker.toolchain_args, "*") + toolchain_disables_sanitizers = true + } + } + } +} + template("win_toolchains") { assert(defined(invoker.toolchain_arch)) toolchain_arch = invoker.toolchain_arch
diff --git a/build_overrides/tint.gni b/build_overrides/tint.gni index 44731b6..9b52393a 100644 --- a/build_overrides/tint.gni +++ b/build_overrides/tint.gni
@@ -7,7 +7,7 @@ tint_googletest_dir = "//third_party/googletest/src" tint_spirv_headers_dir = "//third_party/vulkan-deps/spirv-headers/src" -tint_build_spv_reader = true +tint_build_spv_reader = false tint_build_spv_writer = true tint_build_wgsl_reader = true tint_build_wgsl_writer = true
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 226c18d..26a0c6eb 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 vars in //DEPS. - libcxx_revision = "1dfd0022c4d7aa370a8572d4710558ff8684d7a3" + libcxx_revision = "1127c78cf90cf253be614a1e1d3645da57edbeb4" }
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h index 8d15c1e6..1bc5739 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -72,7 +72,6 @@ synthetic_begin_frame_source; UnboundMessagePipes pipes; bool wants_animate_only_begin_frames = false; - const char* client_name = nullptr; base::PlatformThreadId io_thread_id = base::kInvalidThreadId; };
diff --git a/cc/paint/image_provider.h b/cc/paint/image_provider.h index de41e84..f3fd470e 100644 --- a/cc/paint/image_provider.h +++ b/cc/paint/image_provider.h
@@ -5,6 +5,8 @@ #ifndef CC_PAINT_IMAGE_PROVIDER_H_ #define CC_PAINT_IMAGE_PROVIDER_H_ +#include <utility> + #include "base/functional/callback.h" #include "base/types/optional_util.h" #include "cc/paint/decoded_draw_image.h" @@ -38,9 +40,11 @@ explicit operator bool() const { return image_ || record_; } const DecodedDrawImage& decoded_image() const { return image_; } bool needs_unlock() const { return !destruction_callback_.is_null(); } - const PaintRecord* paint_record() { - DCHECK(record_); - return base::OptionalToPtr(record_); + + bool has_paint_record() const { return record_.has_value(); } + PaintRecord ReleaseAsRecord() { + DCHECK(has_paint_record()); + return std::move(record_.value()); } private:
diff --git a/cc/paint/paint_op.cc b/cc/paint/paint_op.cc index bc200f91..d4c9ded5 100644 --- a/cc/paint/paint_op.cc +++ b/cc/paint/paint_op.cc
@@ -1173,8 +1173,9 @@ // because a navigation is happening). In that case the PaintWorklet jobs // will fail and there will be no result to raster here. This state is // transient as the next main frame commit will remove the PaintWorklets. - if (result && result.paint_record()) - result.paint_record()->Playback(canvas, params); + if (result && result.has_paint_record()) { + result.ReleaseAsRecord().Playback(canvas, params); + } return; }
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc index 42e87621..44becf5 100644 --- a/cc/paint/paint_op_buffer_serializer.cc +++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -212,8 +212,9 @@ const DrawImageRectOp& draw_op = static_cast<const DrawImageRectOp&>(op); ImageProvider::ScopedResult result = options_.image_provider->GetRasterContent(DrawImage(draw_op.image)); - if (!result || !result.paint_record()) + if (!result || !result.has_paint_record()) { return true; + } int save_count = canvas->getSaveCount(); Save(canvas, params); @@ -239,7 +240,7 @@ if (!success) return false; - SerializeBuffer(canvas, result.paint_record()->buffer(), nullptr); + SerializeBuffer(canvas, result.ReleaseAsRecord().buffer(), nullptr); RestoreToCount(canvas, save_count, params); return true; } else {
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc index 94416bb6..da505ef 100644 --- a/cc/paint/paint_shader.cc +++ b/cc/paint/paint_shader.cc
@@ -327,10 +327,11 @@ ImageProvider::ScopedResult result = image_provider->GetRasterContent(DrawImage(image_)); - if (!result || !result.paint_record()) + if (!result || !result.has_paint_record()) { return nullptr; + } SkMatrix local_matrix = GetLocalMatrix(); - return PaintShader::MakePaintRecord(*result.paint_record(), tile_, tx_, ty_, + return PaintShader::MakePaintRecord(result.ReleaseAsRecord(), tile_, tx_, ty_, &local_matrix); }
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc index 16138b19..af8e6a0 100644 --- a/cc/paint/record_paint_canvas.cc +++ b/cc/paint/record_paint_canvas.cc
@@ -315,7 +315,7 @@ void RecordPaintCanvas::drawPicture(PaintRecord record) { // TODO(enne): If this is small, maybe flatten it? - push<DrawRecordOp>(record); + push<DrawRecordOp>(std::move(record)); } void RecordPaintCanvas::Annotate(AnnotationType type,
diff --git a/cc/paint/scoped_raster_flags.cc b/cc/paint/scoped_raster_flags.cc index 1019337c..175df32 100644 --- a/cc/paint/scoped_raster_flags.cc +++ b/cc/paint/scoped_raster_flags.cc
@@ -23,11 +23,11 @@ if (image.IsPaintWorklet()) { ImageProvider::ScopedResult result = decode_stashing_image_provider_->GetRasterContent(DrawImage(image)); - if (result && result.paint_record()) { + if (result && result.has_paint_record()) { const PaintShader* shader = flags()->getShader(); SkMatrix local_matrix = shader->GetLocalMatrix(); auto decoded_shader = PaintShader::MakePaintRecord( - *result.paint_record(), shader->tile(), shader->tx(), shader->tx(), + result.ReleaseAsRecord(), shader->tile(), shader->tx(), shader->tx(), &local_matrix); MutableFlags()->setShader(decoded_shader); } else {
diff --git a/cc/paint/skia_paint_canvas.cc b/cc/paint/skia_paint_canvas.cc index 2117a2d..795d18a 100644 --- a/cc/paint/skia_paint_canvas.cc +++ b/cc/paint/skia_paint_canvas.cc
@@ -360,7 +360,7 @@ } void SkiaPaintCanvas::drawPicture(PaintRecord record) { - drawPicture(record, PlaybackParams::CustomDataRasterCallback()); + drawPicture(std::move(record), PlaybackParams::CustomDataRasterCallback()); } SkM44 SkiaPaintCanvas::getLocalToDevice() const {
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index cfe5993..a4003417 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1309,6 +1309,7 @@ rebase_path(get_label_info(dump_syms, "root_out_dir") + "/" + get_label_info(dump_syms, "name"), root_build_dir), + "-d", "-m", "-g", rebase_path(
diff --git a/chrome/VERSION b/chrome/VERSION index 455d0010..e537a1d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=111 MINOR=0 -BUILD=5560 +BUILD=5563 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 51a1b3d2..0b92d16 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -12,6 +12,7 @@ import("//chrome/android/chrome_java_resources.gni") import("//chrome/android/chrome_public_apk_tmpl.gni") import("//chrome/android/chrome_test_apk_tmpl.gni") +import("//chrome/android/expectations/expectations.gni") import("//chrome/android/features/dev_ui/dev_ui_module.gni") import("//chrome/android/features/start_surface/start_surface_java_sources.gni") import("//chrome/android/features/tab_ui/buildflags.gni") @@ -94,22 +95,6 @@ chrome_jni_sources_exclusions += [ "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java" ] } - # Chosen to match what CQ bots exist. - _enable_libs_and_assets_verification = - public_android_sdk && !is_component_build && - ((target_cpu == "arm" && android_channel == "stable") || - (target_cpu == "arm64" && android_channel == "default" && - !skip_secondary_abi_for_cq && - # Disable checks in official arm64 builds due to unwind assets. - !is_official_build)) - - # Having //clank present causes different flags because of how play services - # is wired up. - # The channel is required because manifest entries vary based on channel. - _enable_manifest_verification = - !is_java_debug && !enable_chrome_android_internal && - android_channel == "stable" - jinja_template("chrome_public_android_manifest") { input = "java/AndroidManifest.xml" output = chrome_public_android_manifest @@ -2837,12 +2822,13 @@ include_64_bit_webview = true } - if (_enable_manifest_verification) { + if (enable_manifest_verification) { expected_android_manifest = "expectations/trichrome_library_apk.AndroidManifest.expected" } - if (_enable_libs_and_assets_verification) { - expected_libs_and_assets = "expectations/trichrome_library_apk.$target_cpu.libs_and_assets.expected" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" } } @@ -2871,6 +2857,10 @@ android_manifest_dep = ":trichrome_library_64_android_manifest" is_64_bit_browser = true include_32_bit_webview = false + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } if (!skip_secondary_abi_for_cq) { @@ -2880,6 +2870,10 @@ android_manifest_dep = ":trichrome_library_32_android_manifest" is_64_bit_browser = false include_64_bit_webview = false + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } trichrome_library_apk_tmpl("trichrome_library_64_32_apk") { @@ -2888,6 +2882,10 @@ android_manifest_dep = ":trichrome_library_64_32_android_manifest" is_64_bit_browser = true include_32_bit_webview = true + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } } } @@ -3395,15 +3393,10 @@ if (android_64bit_target_cpu) { is_64_bit_browser = true } - is_monochrome_or_trichrome = false add_view_trace_events = true manifest_package = chrome_public_manifest_package min_sdk_version = default_min_sdk_version module_descs = chrome_modern_module_descs - - if (_enable_libs_and_assets_verification) { - expected_libs_and_assets = "expectations/chrome_modern_public_bundle.$target_cpu.libs_and_assets.expected" - } } if (is_official_build) { @@ -3466,6 +3459,7 @@ "include_32_bit_webview", "include_64_bit_webview", "is_64_bit_browser", + "is_trichrome", "lint_baseline_file", "lint_min_sdk_version", "lint_suppressions_file", @@ -3474,9 +3468,9 @@ "expected_libs_and_assets", "expected_proguard_config", ]) + is_monochrome = !_is_trichrome base_module_target = ":$_base_module_target_name" bundle_name = _bundle_name - is_monochrome_or_trichrome = true manifest_package = chrome_public_manifest_package min_sdk_version = _min_sdk_version module_descs = _module_descs @@ -3527,13 +3521,14 @@ is_64_bit_browser = false include_64_bit_webview = true } - if (_enable_manifest_verification) { + if (enable_manifest_verification) { expected_android_manifest_template = "expectations/monochrome_public_bundle__SPLIT_NAME.AndroidManifest.expected" expected_proguard_config = "expectations/monochrome_public_bundle.proguard_flags.expected" } - if (_enable_libs_and_assets_verification) { - expected_libs_and_assets = "expectations/monochrome_public_bundle.$target_cpu.libs_and_assets.expected" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" } } @@ -3562,12 +3557,13 @@ include_64_bit_webview = true } - if (_enable_manifest_verification) { + if (enable_manifest_verification) { # Monochrome verifies all bundle modules, so only check base module here. expected_android_manifest = "expectations/trichrome_chrome_bundle__base.AndroidManifest.expected" } - if (_enable_libs_and_assets_verification) { - expected_libs_and_assets = "expectations/trichrome_chrome_bundle.$target_cpu.libs_and_assets.expected" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" } } @@ -3676,6 +3672,10 @@ is_64_bit_browser = true include_32_bit_webview = false static_library_provider = ":trichrome_library_64_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } if (!skip_secondary_abi_for_cq) { @@ -3693,12 +3693,28 @@ include_32_bit_webview = true } + monochrome_or_trichrome_public_bundle_tmpl( + "trichrome_chrome_64_32_bundle") { + is_trichrome = true + bundle_suffix = "6432" + is_64_bit_browser = true + include_32_bit_webview = true + static_library_provider = ":trichrome_library_64_32_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } + } monochrome_or_trichrome_public_bundle_tmpl("trichrome_chrome_32_bundle") { is_trichrome = true bundle_suffix = "32" is_64_bit_browser = false include_64_bit_webview = false static_library_provider = ":trichrome_library_32_apk" + if (enable_libs_and_assets_verification) { + expected_libs_and_assets = + "expectations/$target_name.$target_cpu.libs_and_assets.expected" + } } } } @@ -4159,18 +4175,31 @@ # Used by android-binary-size trybot to validate expectations. if (current_toolchain == default_toolchain && - (_enable_libs_and_assets_verification || _enable_manifest_verification)) { + (enable_libs_and_assets_verification || enable_manifest_verification)) { group("validate_expectations") { deps = [] - if (_enable_libs_and_assets_verification) { + if (enable_libs_and_assets_verification) { deps += [ - ":chrome_modern_public_bundle_validate_libs_and_assets", ":monochrome_public_bundle_validate_libs_and_assets", ":trichrome_chrome_bundle_validate_libs_and_assets", ":trichrome_library_apk_validate_libs_and_assets", + "//android_webview:trichrome_webview_bundle_validate_libs_and_assets", ] + if (android_64bit_target_cpu) { + deps += [ + ":trichrome_chrome_32_bundle_validate_libs_and_assets", + ":trichrome_chrome_64_32_bundle_validate_libs_and_assets", + ":trichrome_chrome_64_bundle_validate_libs_and_assets", + ":trichrome_library_32_apk_validate_libs_and_assets", + ":trichrome_library_64_32_apk_validate_libs_and_assets", + ":trichrome_library_64_apk_validate_libs_and_assets", + "//android_webview:trichrome_webview_32_bundle_validate_libs_and_assets", + "//android_webview:trichrome_webview_64_32_bundle_validate_libs_and_assets", + "//android_webview:trichrome_webview_64_bundle_validate_libs_and_assets", + ] + } } - if (_enable_manifest_verification) { + if (enable_manifest_verification) { deps += [ ":monochrome_public_bundle_validate_manifests", ":monochrome_public_bundle_validate_proguard_config",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index c61749a..35cc962 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -313,10 +313,7 @@ "_is_bundle_module is true but the invoker does not define is_base_module!") } - # TODO(crbug.com/1408322): Delete use_trichrome_library reference. - is_trichrome = (defined(invoker.use_trichrome_library) && - invoker.use_trichrome_library) || - (defined(invoker.is_trichrome) && invoker.is_trichrome) + is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome is_monochrome = !is_trichrome shared_libraries = []
diff --git a/chrome/android/expectations/README.md b/chrome/android/expectations/README.md index 7d093844..8f4f81c1 100644 --- a/chrome/android/expectations/README.md +++ b/chrome/android/expectations/README.md
@@ -116,6 +116,7 @@ 2. Run: ``` + rm $CHROMIUM_OUTPUT_DIR/failed_expectations/* autoninja -C $CHROMIUM_OUTPUT_DIR validate_expectations ```
diff --git a/chrome/android/expectations/chrome_modern_public_bundle.arm64.libs_and_assets.expected b/chrome/android/expectations/chrome_modern_public_bundle.arm64.libs_and_assets.expected deleted file mode 100644 index fad7978c..0000000 --- a/chrome/android/expectations/chrome_modern_public_bundle.arm64.libs_and_assets.expected +++ /dev/null
@@ -1,91 +0,0 @@ -apk_path=lib/arm64-v8a/libchrome.so, compress=False, alignment=4096 -apk_path=lib/arm64-v8a/libchrome_crashpad_handler.so, compress=True, alignment=0 -apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 -apk_path=assets/icudtl.dat, compress=False, alignment=4 -apk_path=assets/locales/af.pak, compress=False, alignment=4 -apk_path=assets/locales/am.pak, compress=False, alignment=4 -apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 -apk_path=assets/locales/ar.pak, compress=False, alignment=4 -apk_path=assets/locales/as.pak, compress=False, alignment=4 -apk_path=assets/locales/az.pak, compress=False, alignment=4 -apk_path=assets/locales/be.pak, compress=False, alignment=4 -apk_path=assets/locales/bg.pak, compress=False, alignment=4 -apk_path=assets/locales/bn.pak, compress=False, alignment=4 -apk_path=assets/locales/bs.pak, compress=False, alignment=4 -apk_path=assets/locales/ca.pak, compress=False, alignment=4 -apk_path=assets/locales/cs.pak, compress=False, alignment=4 -apk_path=assets/locales/da.pak, compress=False, alignment=4 -apk_path=assets/locales/de.pak, compress=False, alignment=4 -apk_path=assets/locales/el.pak, compress=False, alignment=4 -apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 -apk_path=assets/locales/en-US.pak, compress=False, alignment=4 -apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 -apk_path=assets/locales/es-419.pak, compress=False, alignment=4 -apk_path=assets/locales/es.pak, compress=False, alignment=4 -apk_path=assets/locales/et.pak, compress=False, alignment=4 -apk_path=assets/locales/eu.pak, compress=False, alignment=4 -apk_path=assets/locales/fa.pak, compress=False, alignment=4 -apk_path=assets/locales/fi.pak, compress=False, alignment=4 -apk_path=assets/locales/fil.pak, compress=False, alignment=4 -apk_path=assets/locales/fr-CA.pak, compress=False, alignment=4 -apk_path=assets/locales/fr.pak, compress=False, alignment=4 -apk_path=assets/locales/gl.pak, compress=False, alignment=4 -apk_path=assets/locales/gu.pak, compress=False, alignment=4 -apk_path=assets/locales/he.pak, compress=False, alignment=4 -apk_path=assets/locales/hi.pak, compress=False, alignment=4 -apk_path=assets/locales/hr.pak, compress=False, alignment=4 -apk_path=assets/locales/hu.pak, compress=False, alignment=4 -apk_path=assets/locales/hy.pak, compress=False, alignment=4 -apk_path=assets/locales/id.pak, compress=False, alignment=4 -apk_path=assets/locales/is.pak, compress=False, alignment=4 -apk_path=assets/locales/it.pak, compress=False, alignment=4 -apk_path=assets/locales/ja.pak, compress=False, alignment=4 -apk_path=assets/locales/ka.pak, compress=False, alignment=4 -apk_path=assets/locales/kk.pak, compress=False, alignment=4 -apk_path=assets/locales/km.pak, compress=False, alignment=4 -apk_path=assets/locales/kn.pak, compress=False, alignment=4 -apk_path=assets/locales/ko.pak, compress=False, alignment=4 -apk_path=assets/locales/ky.pak, compress=False, alignment=4 -apk_path=assets/locales/lo.pak, compress=False, alignment=4 -apk_path=assets/locales/lt.pak, compress=False, alignment=4 -apk_path=assets/locales/lv.pak, compress=False, alignment=4 -apk_path=assets/locales/mk.pak, compress=False, alignment=4 -apk_path=assets/locales/ml.pak, compress=False, alignment=4 -apk_path=assets/locales/mn.pak, compress=False, alignment=4 -apk_path=assets/locales/mr.pak, compress=False, alignment=4 -apk_path=assets/locales/ms.pak, compress=False, alignment=4 -apk_path=assets/locales/my.pak, compress=False, alignment=4 -apk_path=assets/locales/nb.pak, compress=False, alignment=4 -apk_path=assets/locales/ne.pak, compress=False, alignment=4 -apk_path=assets/locales/nl.pak, compress=False, alignment=4 -apk_path=assets/locales/or.pak, compress=False, alignment=4 -apk_path=assets/locales/pa.pak, compress=False, alignment=4 -apk_path=assets/locales/pl.pak, compress=False, alignment=4 -apk_path=assets/locales/pt-BR.pak, compress=False, alignment=4 -apk_path=assets/locales/pt-PT.pak, compress=False, alignment=4 -apk_path=assets/locales/ro.pak, compress=False, alignment=4 -apk_path=assets/locales/ru.pak, compress=False, alignment=4 -apk_path=assets/locales/si.pak, compress=False, alignment=4 -apk_path=assets/locales/sk.pak, compress=False, alignment=4 -apk_path=assets/locales/sl.pak, compress=False, alignment=4 -apk_path=assets/locales/sq.pak, compress=False, alignment=4 -apk_path=assets/locales/sr-Latn.pak, compress=False, alignment=4 -apk_path=assets/locales/sr.pak, compress=False, alignment=4 -apk_path=assets/locales/sv.pak, compress=False, alignment=4 -apk_path=assets/locales/sw.pak, compress=False, alignment=4 -apk_path=assets/locales/ta.pak, compress=False, alignment=4 -apk_path=assets/locales/te.pak, compress=False, alignment=4 -apk_path=assets/locales/th.pak, compress=False, alignment=4 -apk_path=assets/locales/tr.pak, compress=False, alignment=4 -apk_path=assets/locales/uk.pak, compress=False, alignment=4 -apk_path=assets/locales/ur.pak, compress=False, alignment=4 -apk_path=assets/locales/uz.pak, compress=False, alignment=4 -apk_path=assets/locales/vi.pak, compress=False, alignment=4 -apk_path=assets/locales/zh-CN.pak, compress=False, alignment=4 -apk_path=assets/locales/zh-HK.pak, compress=False, alignment=4 -apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 -apk_path=assets/locales/zu.pak, compress=False, alignment=4 -apk_path=assets/resources.pak, compress=False, alignment=4 -apk_path=assets/snapshot_blob_64.bin, compress=False, alignment=4 -apk_path=assets/webapk8.dex, compress=True, alignment=0 -apk_path=assets/webapk_dex_version.txt, compress=True, alignment=0
diff --git a/chrome/android/expectations/expectations.gni b/chrome/android/expectations/expectations.gni new file mode 100644 index 0000000..2b71a706 --- /dev/null +++ b/chrome/android/expectations/expectations.gni
@@ -0,0 +1,23 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +import("//build/config/android/config.gni") +import("//build/config/coverage/coverage.gni") + +# Chosen to match what CQ bots exist. +enable_libs_and_assets_verification = + !enable_chrome_android_internal && !is_component_build && + !use_jacoco_coverage && + ((target_cpu == "arm" && android_channel == "stable") || + (target_cpu == "arm64" && android_channel == "default" && + !skip_secondary_abi_for_cq && + # Disable checks in official arm64 builds due to unwind assets. + !is_official_build)) + +# Having //clank present causes different flags because of how play services +# is wired up. +# The channel is required because manifest entries vary based on channel. +enable_manifest_verification = + !is_java_debug && !enable_chrome_android_internal && !use_jacoco_coverage && + android_channel == "stable"
diff --git a/chrome/android/expectations/lint-baseline.xml b/chrome/android/expectations/lint-baseline.xml index 76b70d0..73235022 100644 --- a/chrome/android/expectations/lint-baseline.xml +++ b/chrome/android/expectations/lint-baseline.xml
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.0.0-alpha10" type="baseline" client="" dependencies="true" name="" variant="all" version="8.0.0-alpha10"> +<issues format="6" by="lint 8.1.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-alpha01"> <issue id="ResourceType" @@ -19,7 +19,7 @@ errorLine2=" ~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java" - line="490" + line="495" column="89"/> </issue> @@ -74,7 +74,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/partialcustomtab/PartialCustomTabVersionCompat.java" - line="202" + line="214" column="21"/> </issue> @@ -90,17 +90,6 @@ </issue> <issue - id="InvalidId" - message="Invalid id; ID definitions **must** be of the form `@+id/name`; did you mean `@+id/icon_frame`?" - errorLine1=" android:id="@app:id/icon_frame"" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="../../components/browser_ui/settings/android/java/res/layout/chrome_managed_preference.xml" - line="32" - column="11"/> - </issue> - - <issue id="NewApi" message="Call requires API level 26 (current min is 24): `shouldQueryAutofillSuggestion`" errorLine1=" if (mAutofillMenuItemTitle != 0 && mAutofillProvider.shouldQueryAutofillSuggestion()) {" @@ -162,7 +151,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java" - line="1169" + line="1164" column="56"/> </issue> @@ -173,7 +162,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java" - line="1179" + line="1173" column="21"/> </issue> @@ -184,7 +173,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java" - line="1194" + line="1188" column="52"/> </issue> @@ -195,7 +184,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java" - line="1269" + line="1254" column="56"/> </issue> @@ -239,7 +228,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="1601" + line="1586" column="25"/> </issue> @@ -250,7 +239,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="1641" + line="1626" column="29"/> </issue> @@ -261,7 +250,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="2158" + line="2143" column="13"/> </issue> @@ -272,7 +261,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="2172" + line="2157" column="17"/> </issue> @@ -679,7 +668,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../content/public/android/java/src/org/chromium/content/browser/selection/FloatingPastePopupMenu.java" - line="93" + line="90" column="42"/> </issue> @@ -822,7 +811,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java" - line="171" + line="174" column="35"/> </issue> @@ -833,7 +822,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="../../ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java" - line="175" + line="178" column="31"/> </issue> @@ -943,7 +932,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java" - line="255" + line="256" column="56"/> </issue> @@ -976,7 +965,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java" - line="1027" + line="997" column="34"/> </issue> @@ -987,7 +976,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java" - line="1042" + line="1012" column="34"/> </issue> @@ -998,7 +987,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java" - line="1496" + line="1465" column="36"/> </issue> @@ -1053,7 +1042,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> <location file="../../content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java" - line="920" + line="919" column="43"/> </issue> @@ -1064,7 +1053,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> <location file="../../content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java" - line="1447" + line="1445" column="47"/> </issue> @@ -1075,7 +1064,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="../../content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java" - line="1593" + line="1591" column="47"/> </issue> @@ -1345,6 +1334,17 @@ <issue id="NewApi" + message="Call requires API level 29 (current min is 24): `android.view.SurfaceControl#writeToParcel`" + errorLine1=" mSurfaceControl.writeToParcel(out, 0);" + errorLine2=" ~~~~~~~~~~~~~"> + <location + file="../../content/public/android/java/src/org/chromium/content/common/SurfaceWrapper.java" + line="85" + column="29"/> + </issue> + + <issue + id="NewApi" message="Call requires API level 26 (current min is 24): `onProvideAutoFillVirtualStructure`" errorLine1=" mAutofillProvider.onProvideAutoFillVirtualStructure(structure, flags);" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1372,7 +1372,7 @@ errorLine2=" ~~~~~~~~~"> <location file="../../weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java" - line="428" + line="434" column="31"/> </issue> @@ -1383,7 +1383,7 @@ errorLine2=" ~~~~~~~"> <location file="../../weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java" - line="1033" + line="1040" column="31"/> </issue> @@ -1394,7 +1394,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java" - line="655" + line="652" column="36"/> </issue> @@ -1581,7 +1581,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java" - line="328" + line="329" column="38"/> </issue> @@ -1636,39 +1636,6 @@ <issue id="WrongConstant" - message="Must be one of: AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.NONE, AdaptiveToolbarButtonVariant.NEW_TAB, AdaptiveToolbarButtonVariant.SHARE, AdaptiveToolbarButtonVariant.VOICE, AdaptiveToolbarButtonVariant.AUTO, AdaptiveToolbarButtonVariant.PRICE_TRACKING, AdaptiveToolbarButtonVariant.READER_MODE" - errorLine1=" && variant < AdaptiveToolbarButtonVariant.NUM_ENTRIES" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java" - line="121" - column="59"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.NONE, AdaptiveToolbarButtonVariant.NEW_TAB, AdaptiveToolbarButtonVariant.SHARE, AdaptiveToolbarButtonVariant.VOICE, AdaptiveToolbarButtonVariant.AUTO, AdaptiveToolbarButtonVariant.PRICE_TRACKING, AdaptiveToolbarButtonVariant.READER_MODE" - errorLine1=" AdaptiveToolbarButtonVariant.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java" - line="187" - column="50"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.NONE, AdaptiveToolbarButtonVariant.NEW_TAB, AdaptiveToolbarButtonVariant.SHARE, AdaptiveToolbarButtonVariant.VOICE, AdaptiveToolbarButtonVariant.AUTO, AdaptiveToolbarButtonVariant.PRICE_TRACKING, AdaptiveToolbarButtonVariant.READER_MODE" - errorLine1=" buttonVariant, AdaptiveToolbarButtonVariant.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java" - line="218" - column="65"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: AdaptiveToolbarRadioButtonState.UNKNOWN, AdaptiveToolbarRadioButtonState.AUTO_WITH_NEW_TAB, AdaptiveToolbarRadioButtonState.AUTO_WITH_SHARE, AdaptiveToolbarRadioButtonState.AUTO_WITH_VOICE, AdaptiveToolbarRadioButtonState.NEW_TAB, AdaptiveToolbarRadioButtonState.SHARE, AdaptiveToolbarRadioButtonState.VOICE" errorLine1=" AdaptiveToolbarRadioButtonState.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> @@ -1680,23 +1647,12 @@ <issue id="WrongConstant" - message="Must be one of: AdaptiveToolbarButtonVariant.UNKNOWN, AdaptiveToolbarButtonVariant.NONE, AdaptiveToolbarButtonVariant.NEW_TAB, AdaptiveToolbarButtonVariant.SHARE, AdaptiveToolbarButtonVariant.VOICE, AdaptiveToolbarButtonVariant.AUTO, AdaptiveToolbarButtonVariant.PRICE_TRACKING, AdaptiveToolbarButtonVariant.READER_MODE" - errorLine1=" AdaptiveToolbarButtonVariant.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStats.java" - line="72" - column="50"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: SettingsNavigationSource.OTHER, SettingsNavigationSource.TWA_CLEAR_DATA_DIALOG, SettingsNavigationSource.TWA_MANAGE_SPACE_ACTIVITY" errorLine1=" SettingsNavigationSource.EXTRA_KEY, SettingsNavigationSource.OTHER);" errorLine2=" ~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java" - line="284" + line="289" column="42"/> </issue> @@ -1707,7 +1663,7 @@ errorLine2=" ~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java" - line="290" + line="295" column="58"/> </issue> @@ -1834,7 +1790,7 @@ <issue id="WrongConstant" - message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT" + message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT, ActionType.WEB_APK_ACTION_BACK_TO_SITE" errorLine1=" NotificationUmaTracker.ActionType.AUTO_FETCH_CANCEL)" errorLine2=" ~~~~~~~~~~~~~~~~~"> <location @@ -1982,7 +1938,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java" - line="381" + line="380" column="36"/> </issue> @@ -2026,7 +1982,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="257" + line="254" column="27"/> </issue> @@ -2037,7 +1993,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="299" + line="296" column="57"/> </issue> @@ -2059,7 +2015,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java" - line="710" + line="668" column="85"/> </issue> @@ -2125,7 +2081,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java" - line="537" + line="544" column="35"/> </issue> @@ -2136,7 +2092,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java" - line="538" + line="545" column="35"/> </issue> @@ -2147,7 +2103,7 @@ errorLine2=" ~~~~~"> <location file="../../content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java" - line="269" + line="268" column="90"/> </issue> @@ -2169,7 +2125,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java" - line="182" + line="183" column="40"/> </issue> @@ -2180,7 +2136,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java" - line="193" + line="194" column="42"/> </issue> @@ -2279,7 +2235,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java" - line="167" + line="223" column="53"/> </issue> @@ -2290,7 +2246,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="537" + line="535" column="53"/> </issue> @@ -2301,7 +2257,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="1577" + line="1562" column="49"/> </issue> @@ -2312,7 +2268,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="1586" + line="1571" column="65"/> </issue> @@ -2411,23 +2367,12 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/ComponentsProviderService.java" - line="330" + line="317" column="72"/> </issue> <issue id="WrongConstant" - message="Must be one of: UserStatus.NON_USER, UserStatus.TAB_STRIP_NOT_SHOWN, UserStatus.TAB_STRIP_SHOWN, UserStatus.TAB_STRIP_SHOWN_AND_DISMISSED, UserStatus.TAB_STRIP_PERMANENTLY_HIDDEN" - errorLine1=" UMA_USER_STATUS_RESULT, userStatus, UserStatus.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/tasks/ConditionalTabStripUtils.java" - line="166" - column="64"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: ProbeResult.NO_INTERNET, ProbeResult.SERVER_ERROR, ProbeResult.NOT_VALIDATED, ProbeResult.VALIDATED_WITH_NO_CONTENT, ProbeResult.VALIDATED_WITH_OK_BUT_ZERO_CONTENT_LENGTH, ProbeResult.VALIDATED_WITH_OK_BUT_NO_CONTENT_LENGTH" errorLine1=" result, ProbeResult.RESULT_COUNT);" errorLine2=" ~~~~~~~~~~~~"> @@ -2730,7 +2675,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java" - line="962" + line="973" column="39"/> </issue> @@ -2824,7 +2769,7 @@ <issue id="WrongConstant" - message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT" + message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT, ActionType.WEB_APK_ACTION_BACK_TO_SITE" errorLine1=" NotificationUmaTracker.ActionType.TWA_NOTIFICATION_ACCEPTANCE)" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location @@ -2989,28 +2934,6 @@ <issue id="WrongConstant" - message="Must be one of: ExploreSitesCatalogUpdateRequestSource.NEW_TAB_PAGE, ExploreSitesCatalogUpdateRequestSource.EXPLORE_SITES_PAGE, ExploreSitesCatalogUpdateRequestSource.BACKGROUND" - errorLine1=" ExploreSitesCatalogUpdateRequestSource.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java" - line="74" - column="56"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: CategoryType.MORE_BUTTON, CategoryType.DEFAULT, CategoryType.SOCIAL, CategoryType.ENTERTAINMENT, CategoryType.SPORT, CategoryType.NEWS, CategoryType.SHOPPING, CategoryType.REFERENCE, CategoryType.BANKING, CategoryType.GOVERNMENT, CategoryType.TRAVEL, CategoryType.EDUCATION, CategoryType.JOBS, CategoryType.APPS_GAMES, CategoryType.FAVORITE, CategoryType.GOOGLE, CategoryType.FOOD, CategoryType.HEALTH, CategoryType.BOOKS, CategoryType.TECHNOLOGY, CategoryType.SCIENCE" - errorLine1=" ExploreSitesCategory.CategoryType.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java" - line="293" - column="51"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: StreamTabId.DEFAULT, StreamTabId.FOR_YOU, StreamTabId.FOLLOWING" errorLine1=" if (mTabToStreamMap.size() <= tabId) tabId = 0;" errorLine2=" ~"> @@ -3038,7 +2961,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java" - line="605" + line="607" column="80"/> </issue> @@ -3181,7 +3104,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java" - line="212" + line="214" column="88"/> </issue> @@ -3192,7 +3115,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java" - line="522" + line="523" column="84"/> </issue> @@ -3203,7 +3126,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java" - line="1159" + line="1164" column="37"/> </issue> @@ -3423,7 +3346,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java" - line="82" + line="81" column="85"/> </issue> @@ -3434,7 +3357,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java" - line="138" + line="137" column="36"/> </issue> @@ -3445,7 +3368,7 @@ errorLine2=" ~~~~~~~~"> <location file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingMediator.java" - line="772" + line="768" column="39"/> </issue> @@ -3665,7 +3588,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="84" + line="83" column="50"/> </issue> @@ -3676,7 +3599,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="85" + line="84" column="57"/> </issue> @@ -3687,7 +3610,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="121" + line="120" column="59"/> </issue> @@ -3698,7 +3621,7 @@ errorLine2=" ~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="122" + line="121" column="57"/> </issue> @@ -3709,7 +3632,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="205" + line="203" column="55"/> </issue> @@ -3720,7 +3643,7 @@ errorLine2=" ~~~~~~~"> <location file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java" - line="205" + line="203" column="81"/> </issue> @@ -3836,45 +3759,45 @@ <issue id="WrongConstant" - message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR" + message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR, SystemNotificationType.WEBAPK_INSTALL_FAILED" errorLine1=" SystemNotificationType.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java" - line="278" + line="298" column="40"/> </issue> <issue id="WrongConstant" - message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR" + message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR, SystemNotificationType.WEBAPK_INSTALL_FAILED" errorLine1=" "Mobile.SystemNotification.Dismiss", type, SystemNotificationType.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java" - line="325" + line="345" column="83"/> </issue> <issue id="WrongConstant" - message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT" + message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT, ActionType.WEB_APK_ACTION_BACK_TO_SITE" errorLine1=" "Mobile.SystemNotification.Action.Click", actionType, ActionType.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java" - line="369" + line="389" column="82"/> </issue> <issue id="WrongConstant" - message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR" + message="Must be one of: SystemNotificationType.UNKNOWN, SystemNotificationType.DOWNLOAD_FILES, SystemNotificationType.DOWNLOAD_PAGES, SystemNotificationType.CLOSE_INCOGNITO, SystemNotificationType.CONTENT_SUGGESTION, SystemNotificationType.MEDIA_CAPTURE, SystemNotificationType.PHYSICAL_WEB, SystemNotificationType.MEDIA, SystemNotificationType.SITES, SystemNotificationType.SYNC, SystemNotificationType.WEBAPK, SystemNotificationType.BROWSER_ACTIONS, SystemNotificationType.WEBAPP_ACTIONS, SystemNotificationType.OFFLINE_CONTENT_SUGGESTION, SystemNotificationType.TRUSTED_WEB_ACTIVITY_SITES, SystemNotificationType.OFFLINE_PAGES, SystemNotificationType.SEND_TAB_TO_SELF, SystemNotificationType.UPDATES, SystemNotificationType.CLICK_TO_CALL, SystemNotificationType.SHARED_CLIPBOARD, SystemNotificationType.SMS_FETCHER, SystemNotificationType.PERMISSION_REQUESTS, SystemNotificationType.PERMISSION_REQUESTS_HIGH, SystemNotificationType.ANNOUNCEMENT, SystemNotificationType.SHARE_SAVE_IMAGE, SystemNotificationType.TWA_DISCLOSURE_INITIAL, SystemNotificationType.TWA_DISCLOSURE_SUBSEQUENT, SystemNotificationType.CHROME_REENGAGEMENT_1, SystemNotificationType.CHROME_REENGAGEMENT_2, SystemNotificationType.CHROME_REENGAGEMENT_3, SystemNotificationType.PRICE_DROP_ALERTS, SystemNotificationType.WEBAPK_INSTALL_IN_PROGRESS, SystemNotificationType.WEBAPK_INSTALL_COMPLETE, SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED, SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED, SystemNotificationType.CHROME_TIPS, SystemNotificationType.BLUETOOTH, SystemNotificationType.USB, SystemNotificationType.UPM_ERROR, SystemNotificationType.WEBAPK_INSTALL_FAILED" errorLine1=" RecordHistogram.recordEnumeratedHistogram(name, type, SystemNotificationType.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java" - line="505" + line="525" column="86"/> </issue> @@ -4259,7 +4182,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java" - line="216" + line="215" column="60"/> </issue> @@ -4270,7 +4193,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java" - line="230" + line="229" column="50"/> </issue> @@ -4281,7 +4204,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java" - line="269" + line="258" column="16"/> </issue> @@ -4292,7 +4215,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java" - line="269" + line="258" column="16"/> </issue> @@ -4534,7 +4457,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java" - line="361" + line="303" column="33"/> </issue> @@ -4545,7 +4468,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java" - line="776" + line="732" column="51"/> </issue> @@ -4556,7 +4479,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java" - line="836" + line="792" column="61"/> </issue> @@ -4688,13 +4611,13 @@ errorLine2=" ~~~~~"> <location file="../../components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java" - line="443" + line="441" column="70"/> </issue> <issue id="WrongConstant" - message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT" + message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT, ActionType.WEB_APK_ACTION_BACK_TO_SITE" errorLine1=" confirmIntent, NotificationUmaTracker.ActionType.SHARING_CONFIRM);" errorLine2=" ~~~~~~~~~~~~~~~"> <location @@ -4705,7 +4628,7 @@ <issue id="WrongConstant" - message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT" + message="Must be one of: ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME, ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE, ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL, ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE, ActionType.WEB_APP_ACTION_OPEN_IN_CHROME, ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN, ActionType.SETTINGS, ActionType.ANNOUNCEMENT_ACK, ActionType.ANNOUNCEMENT_OPEN, ActionType.PRICE_DROP_VISIT_SITE, ActionType.PRICE_DROP_TURN_OFF_ALERT, ActionType.WEB_APK_ACTION_BACK_TO_SITE" errorLine1=" cancelIntent, NotificationUmaTracker.ActionType.SHARING_CANCEL);" errorLine2=" ~~~~~~~~~~~~~~"> <location @@ -4743,7 +4666,7 @@ errorLine2=" ~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java" - line="520" + line="530" column="50"/> </issue> @@ -4754,7 +4677,7 @@ errorLine2=" ~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java" - line="522" + line="532" column="50"/> </issue> @@ -4765,7 +4688,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java" - line="1464" + line="1502" column="74"/> </issue> @@ -4776,7 +4699,7 @@ errorLine2=" ~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java" - line="1224" + line="1225" column="42"/> </issue> @@ -4787,7 +4710,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java" - line="1226" + line="1227" column="60"/> </issue> @@ -5051,23 +4974,12 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java" - line="532" + line="484" column="80"/> </issue> <issue id="WrongConstant" - message="Must be one of: ReasonToShow.TAB_SWITCHED, ReasonToShow.NEW_TAB, ReasonToShow.LONG_PRESS" - errorLine1=" ConditionalTabStripUtils.ReasonToShow.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java" - line="593" - column="59"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: BringToFrontSource.ACTIVATE_TAB, BringToFrontSource.NOTIFICATION, BringToFrontSource.SEARCH_ACTIVITY" errorLine1=" return IntentHandler.BringToFrontSource.INVALID;" errorLine2=" ~~~~~~~"> @@ -5293,7 +5205,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1099" + line="962" column="85"/> </issue> @@ -5304,7 +5216,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1101" + line="964" column="80"/> </issue> @@ -5315,7 +5227,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1115" + line="978" column="86"/> </issue> @@ -5326,7 +5238,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1117" + line="980" column="81"/> </issue> @@ -5337,7 +5249,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1131" + line="994" column="40"/> </issue> @@ -5348,7 +5260,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1133" + line="996" column="84"/> </issue> @@ -5359,7 +5271,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1147" + line="1010" column="87"/> </issue> @@ -5370,7 +5282,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1149" + line="1012" column="82"/> </issue> @@ -5381,7 +5293,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1163" + line="1026" column="40"/> </issue> @@ -5392,29 +5304,18 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1165" + line="1028" column="86"/> </issue> <issue id="WrongConstant" - message="Must be one of: AssistantActionPerformed.UNKNOWN, AssistantActionPerformed.TRANSCRIPTION, AssistantActionPerformed.TRANSLATE, AssistantActionPerformed.READOUT" - errorLine1=" AssistantActionPerformed.NUM_ENTRIES);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1180" - column="46"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: AudioPermissionState.GRANTED, AudioPermissionState.DENIED_CAN_ASK_AGAIN, AudioPermissionState.DENIED_CANNOT_ASK_AGAIN" errorLine1=" permissionsState, AudioPermissionState.NUM_ENTRIES);" errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java" - line="1271" + line="1110" column="56"/> </issue> @@ -5425,7 +5326,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java" - line="116" + line="114" column="72"/> </issue> @@ -5436,7 +5337,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java" - line="126" + line="124" column="77"/> </issue> @@ -5447,7 +5348,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java" - line="175" + line="164" column="41"/> </issue> @@ -5458,7 +5359,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/WebApkUmaRecorder.java" - line="192" + line="181" column="41"/> </issue> @@ -5568,7 +5469,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java" - line="155" + line="154" column="63"/> </issue> @@ -5744,7 +5645,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java" - line="361" + line="348" column="47"/> </issue> @@ -5755,7 +5656,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java" - line="362" + line="349" column="40"/> </issue> @@ -5766,7 +5667,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java" - line="157" + line="155" column="57"/> </issue> @@ -5777,7 +5678,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java" - line="250" + line="248" column="77"/> </issue> @@ -5898,7 +5799,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java" - line="951" + line="946" column="23"/> </issue> @@ -5920,7 +5821,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - line="1043" + line="1038" column="71"/> </issue> @@ -6151,7 +6052,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java" - line="405" + line="446" column="41"/> </issue> @@ -6459,7 +6360,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java" - line="668" + line="663" column="52"/> </issue> @@ -6547,7 +6448,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java" - line="1138" + line="1152" column="31"/> </issue> @@ -6635,7 +6536,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java" - line="1610" + line="1593" column="74"/> </issue> @@ -6646,7 +6547,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java" - line="709" + line="706" column="31"/> </issue> @@ -6717,17 +6618,6 @@ </issue> <issue - id="Deprecated" - message="Job scheduling with `GcmNetworkManager` is deprecated: Use AndroidX `WorkManager` instead" - errorLine1=" return GcmNetworkManager.getInstance(context);" - errorLine2=" ~~~~~~~~~~~"> - <location - file="../../components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerGcmNetworkManager.java" - line="249" - column="38"/> - </issue> - - <issue id="UseAppTint" message="Must use `app:tint` instead of `android:tint`" errorLine1=" android:tint="@macro/drag_handlebar_color" />" @@ -6745,7 +6635,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_item.xml" - line="84" + line="85" column="9"/> </issue> @@ -6778,19 +6668,19 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java" - line="221" + line="214" column="24"/> </issue> <issue id="UseCompatLoadingForDrawables" message="Use `AppCompatResources.getDrawable()`" - errorLine1=" Drawable mInlineTitleIcon = context.getDrawable(mGooglePayDrawableId);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" cardIconView.setImageDrawable(context.getDrawable(cardIconId));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java" - line="302" - column="37"/> + line="168" + column="47"/> </issue> <issue @@ -6855,7 +6745,7 @@ errorLine2=" ^"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java" - line="380" + line="377" column="56"/> </issue> @@ -6866,7 +6756,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java" - line="2615" + line="2604" column="19"/> </issue> @@ -6943,7 +6833,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="51" + line="52" column="21"/> </issue> @@ -6954,7 +6844,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="52" + line="53" column="21"/> </issue> @@ -6965,7 +6855,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="62" + line="63" column="21"/> </issue> @@ -6976,7 +6866,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="63" + line="64" column="21"/> </issue> @@ -6987,7 +6877,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="73" + line="74" column="21"/> </issue> @@ -6998,7 +6888,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="74" + line="75" column="21"/> </issue> @@ -7009,7 +6899,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="84" + line="85" column="21"/> </issue> @@ -7020,11 +6910,33 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml" - line="85" + line="86" column="21"/> </issue> <issue + id="UnspecifiedRegisterReceiverFlag" + message="`receiver` \
is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected \
broadcasts registered for an IntentFilter that cannot be inspected by lint" + errorLine1=" return context.registerReceiver(receiver, filter, permission, scheduler);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="../../base/android/java/src/org/chromium/base/ContextUtils.java" + line="307" + column="20"/> + </issue> + + <issue + id="UnspecifiedRegisterReceiverFlag" + message="`receiver` \
is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected \
broadcasts registered for an IntentFilter that cannot be inspected by lint" + errorLine1=" return super.registerReceiver(receiver, filter, permission, handler);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="../../content/public/android/java/src/org/chromium/content/browser/sms/Wrappers.java" + line="100" + column="20"/> + </issue> + + <issue id="DataExtractionRules" message="The attribute `android:allowBackup` is deprecated from Android 12 and higher and may be removed in future versions. Consider adding the attribute `android:dataExtractionRules` specifying an `@xml` resource which configures cloud backups and device transfers on Android 12 and higher." errorLine1=" <application android:name="org.chromium.chrome.browser.base.SplitMonochromeApplication" android:icon="@drawable/ic_launcher" android:roundIcon="@drawable/ic_launcher_round" android:label="@string/app_name" android:largeHeap="false" android:manageSpaceActivity="@string/manage_space_activity" android:supportsRtl="true" android:zygotePreloadName="org.chromium.content_public.app.ZygotePreload" android:allowBackup="false" android:networkSecurityConfig="@xml/network_security_config" android:allowAudioPlaybackCapture="false" android:appComponentFactory="org.chromium.chrome.browser.base.SplitCompatAppComponentFactory" android:enableOnBackInvokedCallback="true" android:multiArch="true" android:extractNativeLibs="false" android:use32bitAbi="true">" @@ -7053,7 +6965,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="193" + line="190" column="9"/> </issue> @@ -7064,7 +6976,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="359" + line="356" column="9"/> </issue> @@ -7075,7 +6987,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="409" + line="406" column="9"/> </issue> @@ -7086,7 +6998,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="422" + line="419" column="32"/> </issue> @@ -7097,7 +7009,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java" - line="107" + line="134" column="13"/> </issue> @@ -7185,7 +7097,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java" - line="211" + line="201" column="13"/> </issue> @@ -7400,6 +7312,17 @@ <issue id="AssertionSideEffect" + message="Assertion condition has a side effect: sSyncService = SyncServiceImpl.create()" + errorLine1=" assert SyncService.get() != null;" + errorLine2=" ~~~~~~~~~~~~~~~~~"> + <location + file="../../chrome/android/java/src/org/chromium/chrome/browser/signin/LegacySyncPromoView.java" + line="63" + column="16"/> + </issue> + + <issue + id="AssertionSideEffect" message="Assertion condition has a side effect: sRemotingNotificationId = WebLayerImpl.getRemotePlaybackApiNotificationId()" errorLine1=" assert mNotificationId == getRemotingNotificationIdFromClient();" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -7498,17 +7421,6 @@ </issue> <issue - id="AssertionSideEffect" - message="Assertion condition has a side effect: sSyncService = SyncServiceImpl.create()" - errorLine1=" assert SyncService.get() != null;" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/signin/LegacySyncPromoView.java" - line="59" - column="16"/> - </issue> - - <issue id="MergeRootFrame" message="This `<FrameLayout>` can be replaced with a `<merge>` tag" errorLine1="<FrameLayout" @@ -7603,7 +7515,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java" - line="464" + line="465" column="20"/> </issue> @@ -7614,7 +7526,7 @@ errorLine2=" ^"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java" - line="282" + line="279" column="46"/> </issue> @@ -7680,7 +7592,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java" - line="391" + line="392" column="20"/> </issue> @@ -7779,7 +7691,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java" - line="79" + line="80" column="9"/> </issue> @@ -7845,7 +7757,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameView.java" - line="130" + line="131" column="20"/> </issue> @@ -7867,7 +7779,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java" - line="232" + line="238" column="46"/> </issue> @@ -7878,7 +7790,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java" - line="446" + line="450" column="20"/> </issue> @@ -7889,7 +7801,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java" - line="540" + line="534" column="20"/> </issue> @@ -7922,7 +7834,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml" - line="51" + line="52" column="17"/> </issue> @@ -7933,7 +7845,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml" - line="75" + line="76" column="17"/> </issue> @@ -7944,7 +7856,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml" - line="99" + line="100" column="17"/> </issue>
diff --git a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected b/chrome/android/expectations/trichrome_chrome_32_bundle.arm64.libs_and_assets.expected similarity index 94% rename from chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected rename to chrome/android/expectations/trichrome_chrome_32_bundle.arm64.libs_and_assets.expected index f6d3181..cf37af6 100644 --- a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected +++ b/chrome/android/expectations/trichrome_chrome_32_bundle.arm64.libs_and_assets.expected
@@ -1,9 +1,8 @@ -apk_path=lib/armeabi-v7a/libchrome.so, compress=False, alignment=4096 -apk_path=lib/armeabi-v7a/libchrome_crashpad_handler.so, compress=True, alignment=0 +apk_path=lib/armeabi-v7a/libchromium_android_linker.so, compress=False, alignment=4096 apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 -apk_path=assets/icudtl.dat, compress=False, alignment=4 apk_path=assets/locales/af.pak, compress=False, alignment=4 apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 apk_path=assets/locales/ar.pak, compress=False, alignment=4 apk_path=assets/locales/as.pak, compress=False, alignment=4 apk_path=assets/locales/az.pak, compress=False, alignment=4 @@ -18,6 +17,7 @@ apk_path=assets/locales/el.pak, compress=False, alignment=4 apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 apk_path=assets/locales/es-419.pak, compress=False, alignment=4 apk_path=assets/locales/es.pak, compress=False, alignment=4 apk_path=assets/locales/et.pak, compress=False, alignment=4 @@ -84,6 +84,5 @@ apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 apk_path=assets/locales/zu.pak, compress=False, alignment=4 apk_path=assets/resources.pak, compress=False, alignment=4 -apk_path=assets/snapshot_blob_32.bin, compress=False, alignment=4 apk_path=assets/webapk8.dex, compress=True, alignment=0 apk_path=assets/webapk_dex_version.txt, compress=True, alignment=0
diff --git a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected b/chrome/android/expectations/trichrome_chrome_64_32_bundle.arm64.libs_and_assets.expected similarity index 94% copy from chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected copy to chrome/android/expectations/trichrome_chrome_64_32_bundle.arm64.libs_and_assets.expected index f6d3181..7e76a5fd 100644 --- a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected +++ b/chrome/android/expectations/trichrome_chrome_64_32_bundle.arm64.libs_and_assets.expected
@@ -1,9 +1,8 @@ -apk_path=lib/armeabi-v7a/libchrome.so, compress=False, alignment=4096 -apk_path=lib/armeabi-v7a/libchrome_crashpad_handler.so, compress=True, alignment=0 +apk_path=lib/arm64-v8a/libchromium_android_linker.so, compress=False, alignment=4096 apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 -apk_path=assets/icudtl.dat, compress=False, alignment=4 apk_path=assets/locales/af.pak, compress=False, alignment=4 apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 apk_path=assets/locales/ar.pak, compress=False, alignment=4 apk_path=assets/locales/as.pak, compress=False, alignment=4 apk_path=assets/locales/az.pak, compress=False, alignment=4 @@ -18,6 +17,7 @@ apk_path=assets/locales/el.pak, compress=False, alignment=4 apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 apk_path=assets/locales/es-419.pak, compress=False, alignment=4 apk_path=assets/locales/es.pak, compress=False, alignment=4 apk_path=assets/locales/et.pak, compress=False, alignment=4 @@ -84,6 +84,5 @@ apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 apk_path=assets/locales/zu.pak, compress=False, alignment=4 apk_path=assets/resources.pak, compress=False, alignment=4 -apk_path=assets/snapshot_blob_32.bin, compress=False, alignment=4 apk_path=assets/webapk8.dex, compress=True, alignment=0 apk_path=assets/webapk_dex_version.txt, compress=True, alignment=0
diff --git a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected b/chrome/android/expectations/trichrome_chrome_64_bundle.arm64.libs_and_assets.expected similarity index 94% copy from chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected copy to chrome/android/expectations/trichrome_chrome_64_bundle.arm64.libs_and_assets.expected index f6d3181..7e76a5fd 100644 --- a/chrome/android/expectations/chrome_modern_public_bundle.arm.libs_and_assets.expected +++ b/chrome/android/expectations/trichrome_chrome_64_bundle.arm64.libs_and_assets.expected
@@ -1,9 +1,8 @@ -apk_path=lib/armeabi-v7a/libchrome.so, compress=False, alignment=4096 -apk_path=lib/armeabi-v7a/libchrome_crashpad_handler.so, compress=True, alignment=0 +apk_path=lib/arm64-v8a/libchromium_android_linker.so, compress=False, alignment=4096 apk_path=assets/chrome_100_percent.pak, compress=False, alignment=4 -apk_path=assets/icudtl.dat, compress=False, alignment=4 apk_path=assets/locales/af.pak, compress=False, alignment=4 apk_path=assets/locales/am.pak, compress=False, alignment=4 +apk_path=assets/locales/ar-XB.pak, compress=False, alignment=4 apk_path=assets/locales/ar.pak, compress=False, alignment=4 apk_path=assets/locales/as.pak, compress=False, alignment=4 apk_path=assets/locales/az.pak, compress=False, alignment=4 @@ -18,6 +17,7 @@ apk_path=assets/locales/el.pak, compress=False, alignment=4 apk_path=assets/locales/en-GB.pak, compress=False, alignment=4 apk_path=assets/locales/en-US.pak, compress=False, alignment=4 +apk_path=assets/locales/en-XA.pak, compress=False, alignment=4 apk_path=assets/locales/es-419.pak, compress=False, alignment=4 apk_path=assets/locales/es.pak, compress=False, alignment=4 apk_path=assets/locales/et.pak, compress=False, alignment=4 @@ -84,6 +84,5 @@ apk_path=assets/locales/zh-TW.pak, compress=False, alignment=4 apk_path=assets/locales/zu.pak, compress=False, alignment=4 apk_path=assets/resources.pak, compress=False, alignment=4 -apk_path=assets/snapshot_blob_32.bin, compress=False, alignment=4 apk_path=assets/webapk8.dex, compress=True, alignment=0 apk_path=assets/webapk_dex_version.txt, compress=True, alignment=0
diff --git a/chrome/android/expectations/trichrome_library_32_apk.arm64.libs_and_assets.expected b/chrome/android/expectations/trichrome_library_32_apk.arm64.libs_and_assets.expected new file mode 100644 index 0000000..45c1cbd9 --- /dev/null +++ b/chrome/android/expectations/trichrome_library_32_apk.arm64.libs_and_assets.expected
@@ -0,0 +1,5 @@ +apk_path=lib/armeabi-v7a/libarcore_sdk_c.so, compress=False, alignment=4096 +apk_path=lib/armeabi-v7a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096 +apk_path=lib/armeabi-v7a/libmonochrome.so, compress=False, alignment=4096 +apk_path=assets/icudtl.dat, compress=False, alignment=4 +apk_path=assets/snapshot_blob_32.bin, compress=False, alignment=4
diff --git a/chrome/android/expectations/trichrome_library_64_32_apk.arm64.libs_and_assets.expected b/chrome/android/expectations/trichrome_library_64_32_apk.arm64.libs_and_assets.expected new file mode 100644 index 0000000..c731b0ed --- /dev/null +++ b/chrome/android/expectations/trichrome_library_64_32_apk.arm64.libs_and_assets.expected
@@ -0,0 +1,5 @@ +apk_path=lib/arm64-v8a/libarcore_sdk_c.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libmonochrome_64.so, compress=False, alignment=4096 +apk_path=assets/icudtl.dat, compress=False, alignment=4 +apk_path=assets/snapshot_blob_64.bin, compress=False, alignment=4
diff --git a/chrome/android/expectations/trichrome_library_64_apk.arm64.libs_and_assets.expected b/chrome/android/expectations/trichrome_library_64_apk.arm64.libs_and_assets.expected new file mode 100644 index 0000000..c731b0ed --- /dev/null +++ b/chrome/android/expectations/trichrome_library_64_apk.arm64.libs_and_assets.expected
@@ -0,0 +1,5 @@ +apk_path=lib/arm64-v8a/libarcore_sdk_c.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libcrashpad_handler_trampoline.so, compress=False, alignment=4096 +apk_path=lib/arm64-v8a/libmonochrome_64.so, compress=False, alignment=4096 +apk_path=assets/icudtl.dat, compress=False, alignment=4 +apk_path=assets/snapshot_blob_64.bin, compress=False, alignment=4
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java index 8bae4a1b..b6cebaf 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.app.feed.FeedActionDelegateImpl; import org.chromium.chrome.browser.bookmarks.BookmarkModel; +import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.feed.FeedReliabilityLogger; import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator; import org.chromium.chrome.browser.feed.FeedSurfaceDelegate; @@ -34,6 +35,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.top.Toolbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.chrome.browser.xsurface.FeedLaunchReliabilityLogger.SurfaceType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.base.WindowAndroid; @@ -139,7 +141,7 @@ ExploreSurfaceActionDelegate(SnackbarManager snackbarManager, BookmarkModel bookmarkModel, CrowButtonDelegate crowButtonDelegate) { super(mActivity, snackbarManager, mExploreSurfaceNavigationDelegate, bookmarkModel, - crowButtonDelegate); + crowButtonDelegate, BrowserUiUtils.HostSurface.START_SURFACE); } @Override @@ -171,4 +173,9 @@ return false; } } + + @VisibleForTesting + public FeedActionDelegate getFeedActionDelegateForTesting() { + return mFeedSurfaceCoordinator.getActionDelegateForTesting(); // IN-TEST + } }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java index 59bc62f..68818f0 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -46,6 +46,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ShareDelegate; import org.chromium.chrome.browser.share.crow.CrowButtonDelegate; +import org.chromium.chrome.browser.suggestions.tile.TileGroupDelegateImpl; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -722,6 +723,11 @@ return mTasksSurface.isMVTilesInitialized(); } + @VisibleForTesting + public TileGroupDelegateImpl getTileGroupDelegateForTesting() { + return mTasksSurface.getTileGroupDelegate(); + } + /** * Called only when Start Surface is enabled. */
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 1da8d7e..70b2c10 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -55,6 +55,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.back_press.BackPressManager; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; +import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.feed.FeedReliabilityLogger; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lens.LensEntryPoint; @@ -1497,4 +1498,11 @@ ? mIsHomepageShown : mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE; } + + @VisibleForTesting + public FeedActionDelegate getFeedActionDelegateForTesting() { + assert mPropertyModel.get(EXPLORE_SURFACE_COORDINATOR) != null; + return mPropertyModel.get(EXPLORE_SURFACE_COORDINATOR) + .getFeedActionDelegateForTesting(); // IN-TEST + } }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java index dcf9b5b..75240e8 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java
@@ -24,6 +24,12 @@ * overview page is showing at the startup. */ private boolean mUnusedTabRestoredAtStartup; + // Whether the singleton instance has been created. + private static boolean sHasInstance; + + private StartSurfaceUserData() { + sHasInstance = true; + } /** * Static class that implements the initialization-on-demand holder idiom. @@ -40,6 +46,15 @@ } /** + * Cleans up any state which should be reset when recreating the ChromeTabbedActivity. + */ + public static void reset() { + if (sHasInstance) { + getInstance().saveFeedInstanceState(null); + } + } + + /** * Sets the flag of whether to keep the given tab in the TabModel without auto deleting when * tapping the back button. This flag is for a tab with launchType * {@link org.chromium.chrome.browser.tab.TabLaunchType.FROM_START_SURFACE}. @@ -125,4 +140,8 @@ public boolean getUnusedTabRestoredAtStartup() { return mUnusedTabRestoredAtStartup; } + + static boolean hasInstanceForTesting() { + return sHasInstance; + } }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java index 94a9131..6159f4a 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.feed.FeedReliabilityLogger; import org.chromium.chrome.browser.omnibox.OmniboxStub; +import org.chromium.chrome.browser.suggestions.tile.TileGroupDelegateImpl; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager; @@ -122,6 +123,10 @@ /** Returns whether the MV tiles has been initialized. */ boolean isMVTilesInitialized(); + @VisibleForTesting + /** Returns the tile group delegate. */ + TileGroupDelegateImpl getTileGroupDelegate(); + /** * TODO(crbug.com/1315676): Remove this API after the bug is resolved. *
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java index 6f08599..f4ba433 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
@@ -51,6 +51,7 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.ui.base.DeviceFormFactor; @@ -226,8 +227,8 @@ new MostVisitedTileNavigationDelegate(mActivity, profile, mParentTabSupplier); mSuggestionsUiDelegate = new MostVisitedSuggestionsUiDelegate(navigationDelegate, profile, mSnackbarManager); - mTileGroupDelegate = - new TileGroupDelegateImpl(mActivity, profile, navigationDelegate, mSnackbarManager); + mTileGroupDelegate = new TileGroupDelegateImpl(mActivity, profile, navigationDelegate, + mSnackbarManager, BrowserUiUtils.HostSurface.START_SURFACE); mMostVisitedCoordinator.initWithNative( mSuggestionsUiDelegate, mTileGroupDelegate, enabled -> {}); @@ -330,6 +331,12 @@ return mIsMVTilesInitialized; } + @VisibleForTesting + @Override + public TileGroupDelegateImpl getTileGroupDelegate() { + return mTileGroupDelegate; + } + @Override public @Nullable TabSwitcherCustomViewManager getTabSwitcherCustomViewManager() { return (mTabSwitcher != null) ? mTabSwitcher.getTabSwitcherCustomViewManager() : null;
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java index b01a91b..0ae2fc00 100644 --- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java +++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinatorUnitTest.java
@@ -4,9 +4,16 @@ package org.chromium.chrome.features.start_surface; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import android.view.View; import androidx.test.filters.MediumTest; +import androidx.test.filters.SmallTest; import org.hamcrest.Matchers; import org.junit.Assert; @@ -14,18 +21,33 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; +import org.chromium.base.Callback; import org.chromium.base.TimeUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.UmaRecorder; import org.chromium.base.metrics.UmaRecorderHolder; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.chrome.browser.suggestions.SiteSuggestion; +import org.chromium.chrome.browser.suggestions.tile.Tile; +import org.chromium.chrome.browser.suggestions.tile.TileGroupDelegateImpl; +import org.chromium.chrome.browser.suggestions.tile.TileSectionType; +import org.chromium.chrome.browser.suggestions.tile.TileSource; +import org.chromium.chrome.browser.suggestions.tile.TileTitleSource; import org.chromium.chrome.browser.tasks.ReturnToChromeUtil; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.chrome.test.util.browser.Features; +import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.PageTransition; +import org.chromium.ui.mojom.WindowOpenDisposition; +import org.chromium.url.GURL; /** Tests for {@link StartSurfaceCoordinator}. */ @RunWith(BaseRobolectricTestRunner.class) @@ -36,6 +58,17 @@ public class StartSurfaceCoordinatorUnitTest { private static final long MILLISECONDS_PER_MINUTE = TimeUtils.SECONDS_PER_MINUTE * 1000; private static final String START_SURFACE_TIME_SPENT = "StartSurface.TimeSpent"; + private static final String HISTOGRAM_START_SURFACE_MODULE_CLICK = "StartSurface.Module.Click"; + private static final String USER_ACTION_START_SURFACE_MVT_CLICK = + "Suggestions.Tile.Tapped.StartSurface"; + private static final String TEST_URL = "https://www.example.com/"; + + @Mock + private UmaRecorder mUmaRecorder; + @Mock + private Callback mOnVisitComplete; + @Mock + private Runnable mOnPageLoaded; @Rule public StartSurfaceCoordinatorUnitTestRule mTestRule = @@ -314,6 +347,180 @@ } /** + * Test whether the clicking action on MV tiles in {@link StartSurface} is been recorded in + * histogram correctly. + */ + @Test + @SmallTest + public void testRecordHistogramMostVisitedItemClick_StartSurface() { + Tile tileForTest = + new Tile(new SiteSuggestion("0 TOP_SITES", new GURL("https://www.foo.com"), + TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, + TileSectionType.PERSONALIZED), + 0); + TileGroupDelegateImpl tileGroupDelegate = mCoordinator.getTileGroupDelegateForTesting(); + + // Test clicking on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.CURRENT_TAB, tileForTest); + Assert.assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when click on MV tiles.", + 1, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in new tab on MV tiles. + tileGroupDelegate.openMostVisitedItem( + WindowOpenDisposition.NEW_BACKGROUND_TAB, tileForTest); + Assert.assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + " is not recorded " + + "correctly when long press then open in new tab on MV tiles.", + 2, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in other window on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.NEW_WINDOW, tileForTest); + Assert.assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " shouldn't be recorded when long press then open in other window " + + "on MV tiles.", + 2, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then download link on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.SAVE_TO_DISK, tileForTest); + Assert.assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when long press then download link " + + "on MV tiles.", + 3, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in Incognito tab on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.OFF_THE_RECORD, tileForTest); + Assert.assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + " is not recorded correctly " + + "when long press then open in Incognito tab on MV tiles.", + 4, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + } + + /** + * Test whether the clicking action on MV tiles in {@link StartSurface} is been recorded + * as user actions correctly. + */ + @Test + @SmallTest + public void testRecordUserActionMostVisitedItemClick_StartSurface() { + UmaRecorderHolder.setNonNativeDelegate(mUmaRecorder); + + Tile tileForTest = + new Tile(new SiteSuggestion("0 TOP_SITES", new GURL("https://www.foo.com"), + TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, + TileSectionType.PERSONALIZED), + 0); + TileGroupDelegateImpl tileGroupDelegate = mCoordinator.getTileGroupDelegateForTesting(); + + // Test clicking on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.CURRENT_TAB, tileForTest); + verify(mUmaRecorder, times(1)) + .recordUserAction(eq(USER_ACTION_START_SURFACE_MVT_CLICK), anyLong()); + + // Test long press then open in new tab on MV tiles. + tileGroupDelegate.openMostVisitedItem( + WindowOpenDisposition.NEW_BACKGROUND_TAB, tileForTest); + verify(mUmaRecorder, times(1)) + .recordUserAction(eq(USER_ACTION_START_SURFACE_MVT_CLICK), anyLong()); + + // Test long press then open in other window on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.NEW_WINDOW, tileForTest); + verify(mUmaRecorder, times(1)) + .recordUserAction(eq(USER_ACTION_START_SURFACE_MVT_CLICK), anyLong()); + + // Test long press then download link on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.SAVE_TO_DISK, tileForTest); + verify(mUmaRecorder, times(1)) + .recordUserAction(eq(USER_ACTION_START_SURFACE_MVT_CLICK), anyLong()); + + // Test long press then open in Incognito tab on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.OFF_THE_RECORD, tileForTest); + verify(mUmaRecorder, times(2)) + .recordUserAction(eq(USER_ACTION_START_SURFACE_MVT_CLICK), anyLong()); + + UmaRecorderHolder.resetForTesting(); + } + + /** + * Test whether the clicking action on Feeds in {@link StartSurface} is been recorded in + * histogram correctly. + */ + @Test + @SmallTest + public void testRecordHistogramFeedClick_StartSurface() { + FeedActionDelegate feedActionDelegate = + mCoordinator.getMediatorForTesting().getFeedActionDelegateForTesting(); + // Test click on Feeds or long press then check about this source & topic on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.CURRENT_TAB, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when click on Feeds or " + + "long press then check about this source & topic on Feeds.", + 1, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test long press then open in new tab on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.NEW_BACKGROUND_TAB, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when long press then open in " + + "new tab on Feeds.", + 2, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test long press then open in incognito tab on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.OFF_THE_RECORD, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when long press then open in incognito tab " + + "on Feeds.", + 3, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test manage activity or manage interests on Feeds. + feedActionDelegate.openUrl(WindowOpenDisposition.CURRENT_TAB, + new LoadUrlParams(TEST_URL, PageTransition.LINK)); + assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " shouldn't be recorded when manage activity or manage interests " + + "on Feeds.", + 3, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test click Learn More button on Feeds. + feedActionDelegate.openHelpPage(); + assertEquals(HISTOGRAM_START_SURFACE_MODULE_CLICK + + " is not recorded correctly when click Learn More button on Feeds.", + 4, + RecordHistogram.getHistogramValueCountForTesting( + HISTOGRAM_START_SURFACE_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + } + + /** * Check that the next decision time is within |numOfDays| from now. * @param numOfDays Number of days to check. */
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index 02e30f9..3ffed607 100644 --- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -1028,6 +1028,18 @@ } @Test + public void testResetFeedInstanceState() { + String instanceState = "state"; + StartSurfaceUserData.getInstance().saveFeedInstanceState(instanceState); + assertTrue(StartSurfaceUserData.hasInstanceForTesting()); + assertEquals(StartSurfaceUserData.getInstance().restoreFeedInstanceState(), instanceState); + + StartSurfaceUserData.reset(); + assertTrue(StartSurfaceUserData.hasInstanceForTesting()); + assertNull(StartSurfaceUserData.getInstance().restoreFeedInstanceState()); + } + + @Test public void defaultStateSinglePane() { doReturn(false).when(mTabModelSelector).isIncognitoSelected(); doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 5ec1a15..b65b450 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -2043,4 +2043,9 @@ } return TabModel.INVALID_TAB_INDEX; } + + @VisibleForTesting + Tab getTabToAddDelayedForTesting() { + return mTabToAddDelayed; + } }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index 1cd5f4e..9b123bc 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -114,6 +114,7 @@ import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.TabObserver; +import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData; import org.chromium.chrome.browser.tab.state.PersistedTabDataConfiguration; import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData; @@ -974,8 +975,8 @@ doReturn(Arrays.asList(newTab)).when(mTabModelFilter).getRelatedTabList(eq(TAB3_ID)); assertThat(mModel.size(), equalTo(2)); - mTabModelObserverCaptor.getValue().didAddTab( - newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false); + mTabModelObserverCaptor.getValue().didAddTab(newTab, TabLaunchType.FROM_TAB_SWITCHER_UI, + TabCreationState.LIVE_IN_FOREGROUND, false); assertThat(mModel.size(), equalTo(3)); assertThat(mModel.get(2).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID)); @@ -983,6 +984,45 @@ } @Test + public void tabAddition_GTS_delayAdd() { + initAndAssertAllProperties(); + doReturn(true).when(mTabModelSelector).isTabStateInitialized(); + + TabImpl newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL); + doReturn(mTab1).when(mTabModelFilter).getTabAt(0); + doReturn(mTab2).when(mTabModelFilter).getTabAt(1); + doReturn(newTab).when(mTabModelFilter).getTabAt(2); + doReturn(Arrays.asList(mTab1, mTab2, newTab)) + .when(mTabModelFilter) + .getRelatedTabList(TAB1_ID); + doReturn(3).when(mTabModelFilter).getCount(); + doReturn(Arrays.asList(newTab)).when(mTabModelFilter).getRelatedTabList(eq(TAB3_ID)); + assertThat(mModel.size(), equalTo(2)); + + TabModelObserver tabModelObserver = mTabModelObserverCaptor.getValue(); + // Add tab marked as delayed + tabModelObserver.didAddTab(newTab, TabLaunchType.FROM_TAB_SWITCHER_UI, + TabCreationState.LIVE_IN_FOREGROUND, true); + + // Verify tab did not get added and delayed tab is captured. + assertThat(mModel.size(), equalTo(2)); + assertThat(mMediator.getTabToAddDelayedForTesting(), equalTo(newTab)); + + // Select delayed tab + tabModelObserver.didSelectTab(newTab, TabSelectionType.FROM_USER, mTab1.getId()); + // Assert old tab is still marked as selected + assertThat(mModel.get(0).model.get(TabProperties.IS_SELECTED), equalTo(true)); + + // Hide GTS to complete tab addition and selection + mMediator.postHiding(); + // Assert tab added and selected. Assert old tab is de-selected. + assertThat(mModel.size(), equalTo(3)); + assertThat(mModel.get(0).model.get(TabProperties.IS_SELECTED), equalTo(false)); + assertThat(mModel.get(2).model.get(TabProperties.IS_SELECTED), equalTo(true)); + assertNull(mMediator.getTabToAddDelayedForTesting()); + } + + @Test public void tabAddition_GTS_Skip() { initAndAssertAllProperties(); mMediator.setActionOnAllRelatedTabsForTesting(true); @@ -996,8 +1036,8 @@ doReturn(Arrays.asList(mTab2, newTab)).when(mTabModelFilter).getRelatedTabList(eq(TAB3_ID)); assertThat(mModel.size(), equalTo(2)); - mTabModelObserverCaptor.getValue().didAddTab( - newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false); + mTabModelObserverCaptor.getValue().didAddTab(newTab, TabLaunchType.FROM_TAB_SWITCHER_UI, + TabCreationState.LIVE_IN_FOREGROUND, false); assertThat(mModel.size(), equalTo(2)); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java index be7216aa..13c0994 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -1096,4 +1096,9 @@ public void clearScrollableContainerDelegateForTesting() { mScrollableContainerDelegate = null; } + + @VisibleForTesting + public FeedActionDelegate getActionDelegateForTesting() { + return mActionDelegate; + } }
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml index 7749fd7..fa57e28 100644 --- a/chrome/android/java/res/menu/main_menu.xml +++ b/chrome/android/java/res/menu/main_menu.xml
@@ -71,6 +71,9 @@ android:icon="@drawable/devices_black_24dp" /> <item android:id="@id/divider_line_id" android:title="@null" /> + <item android:id="@+id/page_zoom_id" + android:title="@string/page_zoom_title" + android:icon="@drawable/ic_zoom" /> <item android:id="@+id/share_row_menu_id" android:title="@null"> <menu> @@ -136,9 +139,6 @@ android:checkable="true" /> </menu> </item> - <item android:id="@+id/page_zoom_id" - android:title="@string/page_zoom_title" - android:icon="@drawable/ic_zoom" /> <item android:id="@+id/paint_preview_show_id" android:title="@string/menu_paint_preview_show" android:icon="@drawable/ic_photo_camera" />
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 be226e4..a1239ca1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -220,9 +220,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; /** * This is the main activity for ChromeMobile when not running in document mode. All the tabs @@ -260,14 +260,9 @@ public static final SettingsLauncher SETTINGS_LAUNCHER = new SettingsLauncherImpl(); - public static final HashSet<String> TABBED_MODE_COMPONENT_NAMES = new HashSet<String>() { - { - add(ChromeTabbedActivity.class.getName()); - add(MultiInstanceChromeTabbedActivity.class.getName()); - add(ChromeTabbedActivity2.class.getName()); - add(MAIN_LAUNCHER_ACTIVITY_NAME); - } - }; + public static final Set<String> TABBED_MODE_COMPONENT_NAMES = Set.of( + ChromeTabbedActivity.class.getName(), MultiInstanceChromeTabbedActivity.class.getName(), + ChromeTabbedActivity2.class.getName(), MAIN_LAUNCHER_ACTIVITY_NAME); /** * Identifies a histogram to use in {@link #maybeDispatchExplicitMainViewIntent(Intent, int)}. @@ -461,6 +456,7 @@ mMultiInstanceManager = MultiInstanceManager.create(this, getTabModelOrchestratorSupplier(), getMultiWindowModeStateDispatcher(), getLifecycleDispatcher(), getModalDialogManagerSupplier(), this); + StartSurfaceUserData.reset(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java index b51ec610..2fc2771d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java
@@ -22,6 +22,15 @@ public WebContentsFactory() {} /** + * For capturing where WebContentsImpl is created. + */ + private static class WebContentsCreationException extends RuntimeException { + WebContentsCreationException() { + super("vvv This is where WebContents was created. vvv"); + } + } + + /** * A factory method to build a {@link WebContents} object. * @param profile The profile with which the {@link WebContents} should be built. * @param initiallyHidden Whether or not the {@link WebContents} should be initially hidden. @@ -29,14 +38,15 @@ */ // TODO(https://crbug.com/1099138): Remove static for unit-testability. public static WebContents createWebContents(Profile profile, boolean initiallyHidden) { - return WebContentsFactoryJni.get().createWebContents(profile, initiallyHidden, false); + return WebContentsFactoryJni.get().createWebContents( + profile, initiallyHidden, false, new WebContentsCreationException()); } // TODO(https://crbug.com/1033955): Remove after check discard error is fixed. private static WebContents createWebContents( Profile profile, boolean initiallyHidden, boolean initializeRenderer) { return WebContentsFactoryJni.get().createWebContents( - profile, initiallyHidden, initializeRenderer); + profile, initiallyHidden, initializeRenderer, new WebContentsCreationException()); } /** @@ -54,7 +64,7 @@ @NativeMethods interface Natives { - WebContents createWebContents( - Profile profile, boolean initiallyHidden, boolean initializeRenderer); + WebContents createWebContents(Profile profile, boolean initiallyHidden, + boolean initializeRenderer, Throwable javaCreator); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java index 10f9264..bf09eef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java
@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tasks.ReturnToChromeUtil; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.common.Referrer; @@ -41,14 +42,18 @@ private final SnackbarManager mSnackbarManager; private final CrowButtonDelegate mCrowButtonDelegate; + @BrowserUiUtils.HostSurface + private int mHostSurface; + public FeedActionDelegateImpl(Context activityContext, SnackbarManager snackbarManager, NativePageNavigationDelegate navigationDelegate, BookmarkModel bookmarkModel, - CrowButtonDelegate crowButtonDelegate) { + CrowButtonDelegate crowButtonDelegate, @BrowserUiUtils.HostSurface int hostSurface) { mActivityContext = activityContext; mNavigationDelegate = navigationDelegate; mBookmarkModel = bookmarkModel; mSnackbarManager = snackbarManager; mCrowButtonDelegate = crowButtonDelegate; + mHostSurface = hostSurface; } @Override public void downloadPage(String url) { @@ -83,6 +88,9 @@ }); } ReturnToChromeUtil.onFeedCardOpened(); + + BrowserUiUtils.recordModuleClickHistogram( + mHostSurface, BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED); } @Override @@ -94,6 +102,9 @@ public void openHelpPage() { mNavigationDelegate.openUrl(WindowOpenDisposition.CURRENT_TAB, new LoadUrlParams(NEW_TAB_URL_HELP, PageTransition.AUTO_BOOKMARK)); + + BrowserUiUtils.recordModuleClickHistogram( + mHostSurface, BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index 4cf7905d..eb0bce8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -43,14 +43,10 @@ * A list of field trial parameters that will be cached when starting minimal browser mode. See * {@link #cacheMinimalBrowserFlags()}. */ - private static final List<CachedFieldTrialParameter> MINIMAL_BROWSER_FIELD_TRIALS = - new ArrayList<CachedFieldTrialParameter>() { - { - // This is used by CustomTabsConnection implementation, which does not - // necessarily start chrome. - add(CustomTabActivity.EXPERIMENTS_FOR_AGSA_PARAMS); - } - }; + private static final List<CachedFieldTrialParameter> MINIMAL_BROWSER_FIELD_TRIALS = List.of( + // This is used by CustomTabsConnection implementation, which does not + // necessarily start chrome. + CustomTabActivity.EXPERIMENTS_FOR_AGSA_PARAMS); /** * @return The {@link ChromeCachedFlags} singleton. @@ -68,134 +64,128 @@ if (mIsFinishedCachingNativeFlags) return; FirstRunUtils.cacheFirstRunPrefs(); - // Workaround for crbug.com/1223545: Do not use Arrays.asList(). - List<CachedFlag> featuresToCache = new ArrayList<CachedFlag>() { - { - add(ChromeFeatureList.sAppMenuMobileSiteOption); - add(ChromeFeatureList.sBackGestureRefactorAndroid); - add(ChromeFeatureList.sBaselineGm3SurfaceColors); - add(ChromeFeatureList.sCctAutoTranslate); - add(ChromeFeatureList.sCctBrandTransparency); - add(ChromeFeatureList.sCctFeatureUsage); - add(ChromeFeatureList.sCctIncognito); - add(ChromeFeatureList.sCctIncognitoAvailableToThirdParty); - add(ChromeFeatureList.sCctIntentFeatureOverrides); - add(ChromeFeatureList.sCctRemoveRemoteViewIds); - add(ChromeFeatureList.sCctResizable90MaximumHeight); - add(ChromeFeatureList.sCctResizableForThirdParties); - add(ChromeFeatureList.sCctResizableSideSheet); - add(ChromeFeatureList.sCctRetainableStateInMemory); - add(ChromeFeatureList.sCctToolbarCustomizations); - add(ChromeFeatureList.sCloseTabSuggestions); - add(ChromeFeatureList.sCommandLineOnNonRooted); - add(ChromeFeatureList.sCommerceCoupons); - add(ChromeFeatureList.sCriticalPersistedTabData); - add(ChromeFeatureList.sDiscoverMultiColumn); - add(ChromeFeatureList.sTabStripRedesign); - add(ChromeFeatureList.sDiscardOccludedBitmaps); - add(ChromeFeatureList.sDownloadsAutoResumptionNative); - add(ChromeFeatureList.sEarlyLibraryLoad); - add(ChromeFeatureList.sFeedLoadingPlaceholder); - add(ChromeFeatureList.sFoldableJankFix); - add(ChromeFeatureList.sGridTabSwitcherForTablets); - add(ChromeFeatureList.sHideNonDisplayableAccountEmail); - add(ChromeFeatureList.sIncognitoReauthenticationForAndroid); - add(ChromeFeatureList.sInstanceSwitcher); - add(ChromeFeatureList.sInstantStart); - add(ChromeFeatureList.sInterestFeedV2); - add(ChromeFeatureList.sOmniboxMatchToolbarAndStatusBarColor); - add(ChromeFeatureList.sOmniboxModernizeVisualUpdate); - add(ChromeFeatureList.sOmniboxMostVisitedTilesAddRecycledViewPool); - add(ChromeFeatureList.sOmniboxRemoveExcessiveRecycledViewClearCalls); - add(ChromeFeatureList.sOptimizationGuidePushNotifications); - add(ChromeFeatureList.sOSKResizesVisualViewportByDefault); - add(ChromeFeatureList.sPaintPreviewDemo); - add(ChromeFeatureList.sQueryTiles); - add(ChromeFeatureList.sQueryTilesOnStart); - add(ChromeFeatureList.sReadLater); - add(ChromeFeatureList.sStartSurfaceAndroid); - add(ChromeFeatureList.sStartSurfaceDisabledFeedImprovement); - add(ChromeFeatureList.sStartSurfaceReturnTime); - add(ChromeFeatureList.sStartSurfaceRefactor); - add(ChromeFeatureList.sStoreHoursAndroid); - add(ChromeFeatureList.sSwapPixelFormatToFixConvertFromTranslucent); - add(ChromeFeatureList.sTabGridLayoutAndroid); - add(ChromeFeatureList.sTabGroupsAndroid); - add(ChromeFeatureList.sTabGroupsContinuationAndroid); - add(ChromeFeatureList.sTabGroupsForTablets); - add(ChromeFeatureList.sTabSelectionEditorV2); - add(ChromeFeatureList.sTabStripImprovements); - add(ChromeFeatureList.sTabToGTSAnimation); - add(ChromeFeatureList.sToolbarUseHardwareBitmapDraw); - add(ChromeFeatureList.sUseChimeAndroidSdk); - add(ChromeFeatureList.sUseLibunwindstackNativeUnwinderAndroid); - add(ChromeFeatureList.sWebApkTrampolineOnInitialIntent); - } - }; + // clang-format off + List<CachedFlag> featuresToCache = List.of(ChromeFeatureList.sAppMenuMobileSiteOption, + ChromeFeatureList.sBackGestureRefactorAndroid, + ChromeFeatureList.sBaselineGm3SurfaceColors, + ChromeFeatureList.sCctAutoTranslate, + ChromeFeatureList.sCctBrandTransparency, + ChromeFeatureList.sCctFeatureUsage, + ChromeFeatureList.sCctIncognito, + ChromeFeatureList.sCctIncognitoAvailableToThirdParty, + ChromeFeatureList.sCctIntentFeatureOverrides, + ChromeFeatureList.sCctRemoveRemoteViewIds, + ChromeFeatureList.sCctResizable90MaximumHeight, + ChromeFeatureList.sCctResizableForThirdParties, + ChromeFeatureList.sCctResizableSideSheet, + ChromeFeatureList.sCctResizableSideSheetForThirdParties, + ChromeFeatureList.sCctRetainableStateInMemory, + ChromeFeatureList.sCctToolbarCustomizations, + ChromeFeatureList.sCloseTabSuggestions, + ChromeFeatureList.sCommandLineOnNonRooted, + ChromeFeatureList.sCommerceCoupons, + ChromeFeatureList.sCriticalPersistedTabData, + ChromeFeatureList.sDiscoverMultiColumn, + ChromeFeatureList.sTabStripRedesign, + ChromeFeatureList.sDiscardOccludedBitmaps, + ChromeFeatureList.sDownloadsAutoResumptionNative, + ChromeFeatureList.sEarlyLibraryLoad, + ChromeFeatureList.sFeedLoadingPlaceholder, + ChromeFeatureList.sFoldableJankFix, + ChromeFeatureList.sGridTabSwitcherForTablets, + ChromeFeatureList.sHideNonDisplayableAccountEmail, + ChromeFeatureList.sIncognitoReauthenticationForAndroid, + ChromeFeatureList.sInstanceSwitcher, + ChromeFeatureList.sInstantStart, + ChromeFeatureList.sInterestFeedV2, + ChromeFeatureList.sOmniboxMatchToolbarAndStatusBarColor, + ChromeFeatureList.sOmniboxModernizeVisualUpdate, + ChromeFeatureList.sOmniboxMostVisitedTilesAddRecycledViewPool, + ChromeFeatureList.sOmniboxRemoveExcessiveRecycledViewClearCalls, + ChromeFeatureList.sOptimizationGuidePushNotifications, + ChromeFeatureList.sOSKResizesVisualViewportByDefault, + ChromeFeatureList.sPaintPreviewDemo, + ChromeFeatureList.sQueryTiles, + ChromeFeatureList.sQueryTilesOnStart, + ChromeFeatureList.sReadLater, + ChromeFeatureList.sStartSurfaceAndroid, + ChromeFeatureList.sStartSurfaceDisabledFeedImprovement, + ChromeFeatureList.sStartSurfaceReturnTime, + ChromeFeatureList.sStartSurfaceRefactor, + ChromeFeatureList.sStoreHoursAndroid, + ChromeFeatureList.sSwapPixelFormatToFixConvertFromTranslucent, + ChromeFeatureList.sTabGridLayoutAndroid, + ChromeFeatureList.sTabGroupsAndroid, + ChromeFeatureList.sTabGroupsContinuationAndroid, + ChromeFeatureList.sTabGroupsForTablets, + ChromeFeatureList.sTabSelectionEditorV2, + ChromeFeatureList.sTabStripImprovements, + ChromeFeatureList.sTabToGTSAnimation, + ChromeFeatureList.sToolbarUseHardwareBitmapDraw, + ChromeFeatureList.sUseChimeAndroidSdk, + ChromeFeatureList.sUseLibunwindstackNativeUnwinderAndroid, + ChromeFeatureList.sWebApkTrampolineOnInitialIntent); + CachedFeatureFlags.cacheNativeFlags(featuresToCache); CachedFeatureFlags.cacheAdditionalNativeFlags(); - List<CachedFieldTrialParameter> fieldTrialsToCache = - new ArrayList<CachedFieldTrialParameter>() { - { - add(BrandingController.BRANDING_CADENCE_MS); - add(BrandingController.MAX_BLANK_TOOLBAR_TIMEOUT_MS); - add(BrandingController.USE_TEMPORARY_STORAGE); - add(BrandingController.ANIMATE_TOOLBAR_ICON_TRANSITION); - add(ChimeFeatures.ALWAYS_REGISTER); - add(StartSurfaceConfiguration.BEHAVIOURAL_TARGETING); - add(FeedPlaceholderLayout.ENABLE_INSTANT_START_ANIMATION); - add(FilePersistedTabDataStorage.DELAY_SAVES_UNTIL_DEFERRED_STARTUP_PARAM); - add(OptimizationGuidePushNotificationManager.MAX_CACHE_SIZE); - add(OmniboxFeatures.ENABLE_MODERNIZE_VISUAL_UPDATE_ON_TABLET); - add(OmniboxFeatures.MODERNIZE_VISUAL_UPDATE_ACTIVE_COLOR_ON_OMNIBOX); - add(OmniboxFeatures.MODERNIZE_VISUAL_UPDATE_SMALL_BOTTOM_MARGIN); - add(PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL); - add(CustomTabIntentDataProvider.AUTO_TRANSLATE_ALLOW_ALL_FIRST_PARTIES); - add(CustomTabIntentDataProvider.AUTO_TRANSLATE_PACKAGE_NAME_ALLOWLIST); - add(CustomTabIntentDataProvider.THIRD_PARTIES_DEFAULT_POLICY); - add(CustomTabIntentDataProvider.DENYLIST_ENTRIES); - add(CustomTabIntentDataProvider.ALLOWLIST_ENTRIES); - add(StartSurfaceConfiguration.IS_DOODLE_SUPPORTED); - add(StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS); - add(StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_USE_MODEL); - add(StartSurfaceConfiguration.NUM_DAYS_KEEP_SHOW_START_AT_STARTUP); - add(StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD); - add(StartSurfaceConfiguration.SHOW_TABS_IN_MRU_ORDER); - add(StartSurfaceConfiguration.SIGNIN_PROMO_NTP_COUNT_LIMIT); - add(StartSurfaceConfiguration - .SIGNIN_PROMO_NTP_SINCE_FIRST_TIME_SHOWN_LIMIT_HOURS); - add(StartSurfaceConfiguration.SIGNIN_PROMO_NTP_RESET_AFTER_HOURS); - add(StartSurfaceConfiguration.START_SURFACE_HIDE_INCOGNITO_SWITCH_NO_TAB); - add(StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY); - add(StartSurfaceConfiguration.START_SURFACE_OPEN_NTP_INSTEAD_OF_START); - add(StartSurfaceConfiguration.START_SURFACE_OPEN_START_AS_HOMEPAGE); - add(StartSurfaceConfiguration.START_SURFACE_VARIATION); - add(StartSurfaceConfiguration.SUPPORT_ACCESSIBILITY); - add(StartSurfaceConfiguration.TAB_COUNT_BUTTON_ON_START_SURFACE); - add(StartSurfaceConfiguration.USER_CLICK_THRESHOLD); - add(TabContentManager.ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION); - add(TabPersistentStore.CRITICAL_PERSISTED_TAB_DATA_SAVE_ONLY_PARAM); - add(TabUiFeatureUtilities.ENABLE_LAUNCH_BUG_FIX); - add(TabUiFeatureUtilities.ENABLE_LAUNCH_POLISH); - add(TabUiFeatureUtilities.DELAY_GTS_CREATION); - add(TabUiFeatureUtilities.ENABLE_TAB_GROUP_AUTO_CREATION); - add(TabUiFeatureUtilities.SHOW_OPEN_IN_TAB_GROUP_MENU_ITEM_FIRST); - add(TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING); - add(TabUiFeatureUtilities.ZOOMING_MIN_MEMORY); - add(TabUiFeatureUtilities.SKIP_SLOW_ZOOMING); - add(TabUiFeatureUtilities.THUMBNAIL_ASPECT_RATIO); - add(TabUiFeatureUtilities.GRID_TAB_SWITCHER_FOR_TABLETS_POLISH); - add(TabUiFeatureUtilities.TAB_STRIP_TAB_WIDTH); - add(TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_LONGPRESS_ENTRY); - add(TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_SHARE); - add(TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_BOOKMARKS); - add(TabUiFeatureUtilities.TAB_STRIP_REDESIGN_ENABLE_FOLIO); - add(TabUiFeatureUtilities.TAB_STRIP_REDESIGN_ENABLE_DETACHED); - add(VersionNumberGetter.MIN_SDK_VERSION); - add(ChromeActivity.CONTENT_VIS_DELAY_MS); - } - }; + List<CachedFieldTrialParameter> fieldTrialsToCache = List.of( + BrandingController.BRANDING_CADENCE_MS, + BrandingController.MAX_BLANK_TOOLBAR_TIMEOUT_MS, + BrandingController.USE_TEMPORARY_STORAGE, + BrandingController.ANIMATE_TOOLBAR_ICON_TRANSITION, + ChimeFeatures.ALWAYS_REGISTER, + StartSurfaceConfiguration.BEHAVIOURAL_TARGETING, + FeedPlaceholderLayout.ENABLE_INSTANT_START_ANIMATION, + FilePersistedTabDataStorage.DELAY_SAVES_UNTIL_DEFERRED_STARTUP_PARAM, + OptimizationGuidePushNotificationManager.MAX_CACHE_SIZE, + OmniboxFeatures.ENABLE_MODERNIZE_VISUAL_UPDATE_ON_TABLET, + OmniboxFeatures.MODERNIZE_VISUAL_UPDATE_ACTIVE_COLOR_ON_OMNIBOX, + OmniboxFeatures.MODERNIZE_VISUAL_UPDATE_SMALL_BOTTOM_MARGIN, + PageAnnotationsServiceConfig.PAGE_ANNOTATIONS_BASE_URL, + CustomTabIntentDataProvider.AUTO_TRANSLATE_ALLOW_ALL_FIRST_PARTIES, + CustomTabIntentDataProvider.AUTO_TRANSLATE_PACKAGE_NAME_ALLOWLIST, + CustomTabIntentDataProvider.THIRD_PARTIES_DEFAULT_POLICY, + CustomTabIntentDataProvider.DENYLIST_ENTRIES, + CustomTabIntentDataProvider.ALLOWLIST_ENTRIES, + StartSurfaceConfiguration.IS_DOODLE_SUPPORTED, + StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS, + StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_USE_MODEL, + StartSurfaceConfiguration.NUM_DAYS_KEEP_SHOW_START_AT_STARTUP, + StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD, + StartSurfaceConfiguration.SHOW_TABS_IN_MRU_ORDER, + StartSurfaceConfiguration.SIGNIN_PROMO_NTP_COUNT_LIMIT, + StartSurfaceConfiguration.SIGNIN_PROMO_NTP_SINCE_FIRST_TIME_SHOWN_LIMIT_HOURS, + StartSurfaceConfiguration.SIGNIN_PROMO_NTP_RESET_AFTER_HOURS, + StartSurfaceConfiguration.START_SURFACE_HIDE_INCOGNITO_SWITCH_NO_TAB, + StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY, + StartSurfaceConfiguration.START_SURFACE_OPEN_NTP_INSTEAD_OF_START, + StartSurfaceConfiguration.START_SURFACE_OPEN_START_AS_HOMEPAGE, + StartSurfaceConfiguration.START_SURFACE_VARIATION, + StartSurfaceConfiguration.SUPPORT_ACCESSIBILITY, + StartSurfaceConfiguration.TAB_COUNT_BUTTON_ON_START_SURFACE, + StartSurfaceConfiguration.USER_CLICK_THRESHOLD, + TabContentManager.ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION, + TabPersistentStore.CRITICAL_PERSISTED_TAB_DATA_SAVE_ONLY_PARAM, + TabUiFeatureUtilities.ENABLE_LAUNCH_BUG_FIX, + TabUiFeatureUtilities.ENABLE_LAUNCH_POLISH, + TabUiFeatureUtilities.DELAY_GTS_CREATION, + TabUiFeatureUtilities.ENABLE_TAB_GROUP_AUTO_CREATION, + TabUiFeatureUtilities.SHOW_OPEN_IN_TAB_GROUP_MENU_ITEM_FIRST, + TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING, + TabUiFeatureUtilities.ZOOMING_MIN_MEMORY, + TabUiFeatureUtilities.SKIP_SLOW_ZOOMING, + TabUiFeatureUtilities.THUMBNAIL_ASPECT_RATIO, + TabUiFeatureUtilities.GRID_TAB_SWITCHER_FOR_TABLETS_POLISH, + TabUiFeatureUtilities.TAB_STRIP_TAB_WIDTH, + TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_LONGPRESS_ENTRY, + TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_SHARE, + TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_BOOKMARKS, + TabUiFeatureUtilities.TAB_STRIP_REDESIGN_ENABLE_FOLIO, + TabUiFeatureUtilities.TAB_STRIP_REDESIGN_ENABLE_DETACHED, + VersionNumberGetter.MIN_SDK_VERSION, + ChromeActivity.CONTENT_VIS_DELAY_MS); + // clang-format on tryToCatchMissingParameters(fieldTrialsToCache); CachedFeatureFlags.cacheFieldTrialParameters(fieldTrialsToCache); @@ -231,9 +221,7 @@ CachedFeatureFlags.cacheMinimalBrowserFlagsTimeFromNativeTime(); // TODO(crbug.com/995355): Move other related flags from cacheNativeFlags() to here. - List<CachedFlag> featuresToCache = new ArrayList<CachedFlag>() { - { add(ChromeFeatureList.sExperimentsForAgsa); } - }; + List<CachedFlag> featuresToCache = List.of(ChromeFeatureList.sExperimentsForAgsa); CachedFeatureFlags.cacheNativeFlags(featuresToCache); CachedFeatureFlags.cacheFieldTrialParameters(MINIMAL_BROWSER_FIELD_TRIALS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java index cf3c5d3..91e62dc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -666,15 +666,14 @@ * @param cardTagEnum The {@link CardTag} that the server returned if there was a card, * or {@code 0}. * @param relatedSearchesInBar Related Searches suggestions to be displayed in the Bar. - * @param showDefaultSearchInBar Whether the first query is the default query in the bar. */ @VisibleForTesting @Override public void onSearchTermResolved(String searchTerm, String thumbnailUrl, String quickActionUri, int quickActionCategory, @CardTag int cardTagEnum, - @Nullable List<String> relatedSearchesInBar, boolean showDefaultSearchInBar) { + @Nullable List<String> relatedSearchesInBar) { onSearchTermResolved(searchTerm, null, thumbnailUrl, quickActionUri, quickActionCategory, - cardTagEnum, relatedSearchesInBar, showDefaultSearchInBar); + cardTagEnum, relatedSearchesInBar); } /** @@ -687,16 +686,13 @@ * @param cardTagEnum The {@link CardTag} that the server returned if there was a card, * or {@code 0}. * @param relatedSearchesInBar Related Searches suggestions to be displayed in the Bar. - * @param showDefaultSearchInBar Whether the first query is the default query in the bar. */ @Override public void onSearchTermResolved(String searchTerm, @Nullable String pronunciation, String thumbnailUrl, String quickActionUri, int quickActionCategory, - @CardTag int cardTagEnum, @Nullable List<String> relatedSearchesInBar, - boolean showDefaultSearchInBar) { + @CardTag int cardTagEnum, @Nullable List<String> relatedSearchesInBar) { boolean hadInBarSuggestions = getRelatedSearchesInBarControl().hasReleatedSearchesToShow(); - getRelatedSearchesInBarControl().setRelatedSearchesSuggestions( - relatedSearchesInBar, showDefaultSearchInBar); + getRelatedSearchesInBarControl().setRelatedSearchesSuggestions(relatedSearchesInBar); if (ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES_IN_BAR)) { if (getRelatedSearchesInBarControl().hasReleatedSearchesToShow() != hadInBarSuggestions) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelCoordinator.java index 9a0c922..906d9f72 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelCoordinator.java
@@ -163,13 +163,13 @@ @VisibleForTesting @Override public void onSearchTermResolved(String searchTerm, String thumbnailUrl, String quickActionUri, - int quickActionCategory, int cardTagEnum, @Nullable List<String> inBarRelatedSearches, - boolean showDefaultSearchInBar) {} + int quickActionCategory, int cardTagEnum, @Nullable List<String> inBarRelatedSearches) { + } @Override public void onSearchTermResolved(String searchTerm, @Nullable String pronunciation, String thumbnailUrl, String quickActionUri, int quickActionCategory, int cardTagEnum, - @Nullable List<String> inBarRelatedSearches, boolean showDefaultSearchInBar) {} + @Nullable List<String> inBarRelatedSearches) {} @Override public void setCaption(String caption) {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelInterface.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelInterface.java index 006077d7..21e187e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelInterface.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelInterface.java
@@ -37,11 +37,10 @@ @VisibleForTesting void onSearchTermResolved(String searchTerm, String thumbnailUrl, String quickActionUri, int quickActionCategory, @CardTag int cardTagEnum, - @Nullable List<String> inBarRelatedSearches, boolean showDefaultSearchInBar); + @Nullable List<String> inBarRelatedSearches); void onSearchTermResolved(String searchTerm, @Nullable String pronunciation, String thumbnailUrl, String quickActionUri, int quickActionCategory, - @CardTag int cardTagEnum, @Nullable List<String> inBarRelatedSearches, - boolean showDefaultSearchInBar); + @CardTag int cardTagEnum, @Nullable List<String> inBarRelatedSearches); void setCaption(String caption); void ensureCaption(); void hideCaption();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java index ba0eb50..3145210 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/RelatedSearchesControl.java
@@ -43,6 +43,11 @@ public class RelatedSearchesControl { private static final int INVALID_VIEW_ID = 0; private static final int NO_SELECTED_CHIP = -1; + /** + * In the carousel UI, the first chip is the default search, so the related search start from + * the index 1. + */ + public static final int INDEX_OF_THE_FIRST_RELATED_SEARCHES = 1; /** The Android {@link Context} used to inflate the View. */ private final Context mContext; @@ -71,9 +76,6 @@ /** The query suggestions for this feature, or {@code null} if we don't have any. */ private @Nullable List<String> mRelatedSearchesSuggestions; - /** Whether the first query is the default query. */ - private boolean mDisplayDefaultQuery; - /** Whether the view is visible. */ private boolean mIsVisible; @@ -169,7 +171,7 @@ /** Returns whether the SERP is showing due to a Related Searches suggestion. */ public boolean isShowingRelatedSearchSerp() { if (!mIsEnabled) return false; - return mSelectedChip >= firstRelatedSearchesCarouselIndex(); + return mSelectedChip >= INDEX_OF_THE_FIRST_RELATED_SEARCHES; } // ============================================================================================ @@ -204,10 +206,8 @@ /** * Sets the Related Searches suggestions to show in this view. * @param relatedSearches An {@code List} of suggested queries or {@code null} when none. - * @param firstQueryIsDefault Whether the first query is the default query. */ - void setRelatedSearchesSuggestions( - @Nullable List<String> relatedSearches, boolean displayDefaultQuery) { + void setRelatedSearchesSuggestions(@Nullable List<String> relatedSearches) { if (mControlView == null) { mControlView = new RelatedSearchesControlView(mOverlayPanel, mContext, mViewContainer, mResourceLoader, R.layout.contextual_search_related_searches_view, @@ -217,7 +217,6 @@ assert mChipsSelected == 0 || hasReleatedSearchesToShow(); mRelatedSearchesSuggestions = relatedSearches; mChips.clear(); - mDisplayDefaultQuery = displayDefaultQuery; if (hasReleatedSearchesToShow()) { show(); } else { @@ -396,7 +395,7 @@ offsetX = -offsetX; } - if (mDisplayDefaultQuery && mSelectedChip == NO_SELECTED_CHIP && !fromCloseToPeek) { + if (mSelectedChip == NO_SELECTED_CHIP && !fromCloseToPeek) { mSelectedChip = 0; mChips.get(mSelectedChip).model.set(ChipProperties.SELECTED, true); } @@ -460,20 +459,15 @@ mPanelSectionHost.onSuggestionClicked(suggestionIndex); // TODO(donnd): add infrastructure to check if the suggestion is an RS before logging. RelatedSearchesUma.logSelectedCarouselIndex(suggestionIndex); - RelatedSearchesUma.logSelectedSuggestionIndex( - suggestionIndex + (mDisplayDefaultQuery ? 0 : 1)); + RelatedSearchesUma.logSelectedSuggestionIndex(suggestionIndex); mChipsSelected++; - boolean isRelatedSearchesSuggestion = suggestionIndex > 0 || !mDisplayDefaultQuery; + boolean isRelatedSearchesSuggestion = + suggestionIndex >= INDEX_OF_THE_FIRST_RELATED_SEARCHES; ContextualSearchUma.logAllSearches(isRelatedSearchesSuggestion); mControlView.smoothScrollToPosition(suggestionIndex); } - /** The position of the first Related Searches suggestion in the carousel UI. */ - private int firstRelatedSearchesCarouselIndex() { - return mDisplayDefaultQuery ? 1 : 0; - } - // ============================================================================================ // Chips // ============================================================================================ @@ -487,7 +481,7 @@ ListItem chip = ChipsCoordinator.buildChipListItem(index, suggestion, selectedCallback); - if (index == 0 && mDisplayDefaultQuery) { + if (index < INDEX_OF_THE_FIRST_RELATED_SEARCHES) { chip.model.set(ChipProperties.TEXT_MAX_WIDTH_PX, mContext.getResources().getDimensionPixelSize( R.dimen.contextual_search_chip_max_width));
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 e076d07..2c33c706 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
@@ -1510,10 +1510,15 @@ StripLayoutTab tab = new StripLayoutTab( mContext, id, this, mTabLoadTrackerHost, mRenderHost, mUpdateHost, mIncognito); tab.setHeight(mHeight); - if (id == mModel.getTabAt(mModel.index()).getId()) { - tab.setContainerOpacity(TAB_OPACITY_VISIBLE_FOREGROUND); - } pushStackerPropertiesToTab(tab); + + if (ChromeFeatureList.sTabStripRedesign.isEnabled()) { + Tab selectedTab = mModel.getTabAt(mModel.index()); + if (selectedTab != null && id == selectedTab.getId()) { + tab.setContainerOpacity(TAB_OPACITY_VISIBLE_FOREGROUND); + } + } + return tab; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java index 5273ebd..713ee0f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.share.LensUtils; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.ui.text.SpanApplier; @@ -158,7 +159,7 @@ R.string.contextmenu_open_image_in_ephemeral_tab, // Item.OPEN_IMAGE_IN_EPHEMERAL_TAB: R.string.contextmenu_copy_image, // Item.COPY_IMAGE: R.string.contextmenu_search_web_for_image, // Item.SEARCH_BY_IMAGE: - R.string.contextmenu_search_image_with_google_lens, // Item.SEARCH_WITH_GOOGLE_LENS: + LensUtils.getLensContextMenuText(), // Item.SEARCH_WITH_GOOGLE_LENS: R.string.contextmenu_shop_image_with_google_lens, // Item.SHOP_IMAGE_WITH_GOOGLE_LENS: R.string.contextmenu_share_image, // Item.SHARE_IMAGE 0, // Item.DIRECT_SHARE_IMAGE is not handled by this mapping.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index 782d3b4..e257521 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -32,8 +32,6 @@ private static final String RELATED_SEARCHES_CONFIG_STAMP_PARAM_NAME = "stamp"; private static final String RELATED_SEARCHES_CONFIG_DEFAULT_STAMP = "1Rs"; - static final String RELATED_SEARCHES_SHOW_DEFAULT_QUERY_CHIP_PARAM_NAME = "default_query_chip"; - static final String CONTEXTUAL_SEARCH_MINIMUM_PAGE_HEIGHT_NAME = "contextual_search_minimum_page_height_dp"; @@ -85,12 +83,6 @@ ChromeFeatureList.RELATED_SEARCHES, relatedSearchesParamName, false); } - static boolean showDefaultChipInBar() { - return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( - ChromeFeatureList.RELATED_SEARCHES_IN_BAR, - RELATED_SEARCHES_SHOW_DEFAULT_QUERY_CHIP_PARAM_NAME, true); - } - /** Return The minimum height dp for the contextual search page. */ static int getContextualSearchMinimumBasePageHeightDp() { return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index e0fde2d..5a9e355 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanelCoordinator; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanelInterface; +import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.RelatedSearchesControl; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl; import org.chromium.chrome.browser.contextualsearch.ContextualSearchInternalStateController.InternalState; import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType; @@ -806,9 +807,7 @@ doPreventPreload = true; } - boolean showDefaultSearchInBar = ContextualSearchFieldTrial.showDefaultChipInBar(); - List<String> inBarRelatedSearches = - buildRelatedSearches(searchTerm, showDefaultSearchInBar); + List<String> inBarRelatedSearches = buildRelatedSearches(searchTerm); // Check if the searchTerm is a composite (used for Definitions for pronunciation). // The middle-dot character is returned by the server and marks the beginning of the @@ -829,7 +828,7 @@ mSearchPanel.onSearchTermResolved(message, pronunciation, resolvedSearchTerm.thumbnailUrl(), resolvedSearchTerm.quickActionUri(), resolvedSearchTerm.quickActionCategory(), - resolvedSearchTerm.cardTagEnum(), inBarRelatedSearches, showDefaultSearchInBar); + resolvedSearchTerm.cardTagEnum(), inBarRelatedSearches); if (!TextUtils.isEmpty(resolvedSearchTerm.caption())) { setCaption(resolvedSearchTerm.caption()); } @@ -1301,8 +1300,9 @@ @Override public void onRelatedSearchesSuggestionClicked(int suggestionIndex) { - boolean showDefaultSearch = ContextualSearchFieldTrial.showDefaultChipInBar(); - int defaultSearchAdjustment = showDefaultSearch ? 1 : 0; + // The first suggestion is the default search, so the actual related searches start from + // index 1. + int defaultSearchAdjustment = RelatedSearchesControl.INDEX_OF_THE_FIRST_RELATED_SEARCHES; assert mRelatedSearches != null : "There is no valid list of Related Searches for this click! " + "Please update crbug.com/1307267 with this repro."; @@ -1314,7 +1314,7 @@ if (mSearchPanel.isPeeking()) { mSearchPanel.expandPanel(StateChangeReason.CLICK); } - if (showDefaultSearch && suggestionIndex == 0) { + if (suggestionIndex < RelatedSearchesControl.INDEX_OF_THE_FIRST_RELATED_SEARCHES) { // Click on the default query mSearchRequest = new ContextualSearchRequest(mResolvedSearchTerm.searchTerm(), mResolvedSearchTerm.alternateTerm(), mResolvedSearchTerm.mid(), @@ -1839,18 +1839,16 @@ /** * Build the searches suggestions for the Bar or Panel. * @param defaultSearch The resolved search term.. - * @param showDefaultSearch Whether the default query should been shown. * @return A {@code List<String>} of search suggestions in the bar or the Panel, or {@code null} * if the feature for showing chips is not enabled. */ - private @Nullable List<String> buildRelatedSearches( - String defaultSearch, boolean showDefaultSearch) { + private @Nullable List<String> buildRelatedSearches(String defaultSearch) { if (!ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES_IN_BAR)) { return null; } List<String> queries = mRelatedSearches.getQueries(); - if (!showDefaultSearch || queries.size() == 0) { + if (queries.size() == 0) { return queries; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java index ea7f748..c377c86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java
@@ -808,7 +808,8 @@ mToastFadeAnimation.cancel(); mToastFadeAnimation.alpha(0) .setDuration(TOAST_FADE_MS) - .withEndAction(this::hideImmediatelyNotificationToast); + .withEndAction(this::hideImmediatelyNotificationToast) + .start(); } // ActivityStateListener
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java index 1e8f3b8..10ffe4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaUtils.java
@@ -70,7 +70,8 @@ */ @IntDef({StandbyBucketStatus.ACTIVE, StandbyBucketStatus.WORKING_SET, StandbyBucketStatus.FREQUENT, StandbyBucketStatus.RARE, StandbyBucketStatus.RESTRICTED, - StandbyBucketStatus.UNSUPPORTED, StandbyBucketStatus.COUNT}) + StandbyBucketStatus.UNSUPPORTED, StandbyBucketStatus.EXEMPTED, + StandbyBucketStatus.COUNT}) private @interface StandbyBucketStatus { int ACTIVE = 0; int WORKING_SET = 1; @@ -78,7 +79,8 @@ int RARE = 3; int RESTRICTED = 4; int UNSUPPORTED = 5; - int COUNT = 6; + int EXEMPTED = 6; + int COUNT = 7; } /** @@ -199,6 +201,8 @@ return "Restricted"; case StandbyBucketStatus.UNSUPPORTED: return "Unsupported"; + case StandbyBucketStatus.EXEMPTED: + return "Exempted"; default: assert false : "Unexpected standby bucket " + standbyBucket; return "Unknown"; @@ -229,6 +233,9 @@ case UsageStatsManager.STANDBY_BUCKET_RESTRICTED: standbyBucketUma = StandbyBucketStatus.RESTRICTED; break; + case 5: // STANDBY_BUCKET_EXEMPTED + standbyBucketUma = StandbyBucketStatus.EXEMPTED; + break; default: assert false : "Unexpected standby bucket " + standbyBucket; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 0b18523..fcb9e08 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -82,6 +82,7 @@ import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.chrome.browser.ui.native_page.NativePageHost; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.chrome.browser.xsurface.FeedLaunchReliabilityLogger.SurfaceType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.settings.SettingsLauncher; @@ -283,7 +284,8 @@ private class NewTabPageTileGroupDelegate extends TileGroupDelegateImpl { private NewTabPageTileGroupDelegate(Context context, Profile profile, SuggestionsNavigationDelegate navigationDelegate, SnackbarManager snackbarManager) { - super(context, profile, navigationDelegate, snackbarManager); + super(context, profile, navigationDelegate, snackbarManager, + BrowserUiUtils.HostSurface.NEW_TAB_PAGE); } @Override @@ -494,7 +496,7 @@ FeedActionDelegate actionDelegate = new FeedActionDelegateImpl(activity, snackbarManager, mNewTabPageManager.getNavigationDelegate(), BookmarkModel.getForProfile(profile), - crowButtonDelegate) { + crowButtonDelegate, BrowserUiUtils.HostSurface.NEW_TAB_PAGE) { @Override public void openHelpPage() { NewTabPageUma.recordAction(NewTabPageUma.ACTION_CLICKED_LEARN_MORE); @@ -992,6 +994,17 @@ return mNewTabPageManager; } + @VisibleForTesting + public TileGroup.Delegate getTileGroupDelegateForTesting() { + return mTileGroupDelegate; + } + + @VisibleForTesting + public FeedActionDelegate getFeedActionDelegateForTesting() { + return ((FeedSurfaceCoordinator) mFeedSurfaceProvider) + .getActionDelegateForTesting(); // IN-TEST + } + /** * @param isTopMargin True to return the top margin; False to return bottom margin. * @return The top margin or bottom margin of the logo.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java index 2219902b..140cf46 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
@@ -8,6 +8,7 @@ import android.os.Build; import android.text.TextUtils; +import org.chromium.chrome.R; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.gsa.GSAState; @@ -25,6 +26,11 @@ private static final String DISABLE_ON_INCOGNITO_PARAM_NAME = "disableOnIncognito"; private static final String ORDER_SHARE_IMAGE_BEFORE_LENS_PARAM_NAME = "orderShareImageBeforeLens"; + private static final String USE_LENS_CONTEXT_MENU_ALTERNATE_TEXT_1_PARAM_NAME = + "useLensContextMenuAlternateText1"; + private static final String USE_LENS_CONTEXT_MENU_ALTERNATE_TEXT_2_PARAM_NAME = + "useLensContextMenuAlternateText2"; + private static final String MIN_AGSA_VERSION_NAME_FOR_LENS_POSTCAPTURE = "10.65"; /** @@ -191,4 +197,23 @@ } return false; } + + /** + * Check if experiment to get context menu alternate name text. + */ + public static int getLensContextMenuText() { + if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_SEARCH_OPTIMIZATIONS, + USE_LENS_CONTEXT_MENU_ALTERNATE_TEXT_1_PARAM_NAME, false)) { + return R.string.contextmenu_search_image_with_google_lens_alt_text_1; + } + + if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_SEARCH_OPTIMIZATIONS, + USE_LENS_CONTEXT_MENU_ALTERNATE_TEXT_2_PARAM_NAME, false)) { + return R.string.contextmenu_search_image_with_google_lens_alt_text_2; + } + + return R.string.contextmenu_search_image_with_google_lens; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java index 4e65d597..3696106 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java
@@ -20,16 +20,23 @@ import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.ui.mojom.WindowOpenDisposition; import org.chromium.url.GURL; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Reusable implementation of {@link TileGroup.Delegate}. Performs work in parts of the system that * the {@link TileGroup} should not know about. */ public class TileGroupDelegateImpl implements TileGroup.Delegate { + private static final Set<Integer> MVTilesClickForUserAction = new HashSet<>( + Arrays.asList(WindowOpenDisposition.CURRENT_TAB, WindowOpenDisposition.OFF_THE_RECORD)); + private final Context mContext; private final SnackbarManager mSnackbarManager; private final SuggestionsNavigationDelegate mNavigationDelegate; @@ -37,14 +44,18 @@ private boolean mIsDestroyed; private SnackbarController mTileRemovedSnackbarController; + @BrowserUiUtils.HostSurface + private int mHostSurface; public TileGroupDelegateImpl(Context context, Profile profile, - SuggestionsNavigationDelegate navigationDelegate, SnackbarManager snackbarManager) { + SuggestionsNavigationDelegate navigationDelegate, SnackbarManager snackbarManager, + @BrowserUiUtils.HostSurface int hostSurface) { mContext = context; mSnackbarManager = snackbarManager; mNavigationDelegate = navigationDelegate; mMostVisitedSites = SuggestionsDependencyFactory.getInstance().createMostVisitedSites(profile); + mHostSurface = hostSurface; } @Override @@ -59,6 +70,8 @@ public void openMostVisitedItem(int windowDisposition, Tile item) { assert !mIsDestroyed; + recordClickMvTiles(windowDisposition, mHostSurface); + String url = item.getUrl().getSpec(); // TODO(treib): Should we call recordOpenedMostVisitedItem here? @@ -74,6 +87,8 @@ public void openMostVisitedItemInGroup(int windowDisposition, Tile item) { assert !mIsDestroyed; + recordClickMvTiles(windowDisposition, mHostSurface); + String url = item.getUrl().getSpec(); recordOpenedTile(item); @@ -148,4 +163,23 @@ ReturnToChromeUtil.onMVTileOpened(); mMostVisitedSites.recordOpenedMostVisitedItem(tile); } + + /** + * Records user clicking on MV tiles in New tab page or Start surface. + * @param windowDisposition How to open (new window, current tab, etc). + * @param hostSurface The corresponding item of the host name in {@link + * BrowserUiUtils.HostSurface} which indicates the page + * where the Mv tiles located. + */ + private void recordClickMvTiles( + int windowDisposition, @BrowserUiUtils.HostSurface int hostSurface) { + if (windowDisposition != WindowOpenDisposition.NEW_WINDOW) { + BrowserUiUtils.recordModuleClickHistogram( + hostSurface, BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES); + } + if (MVTilesClickForUserAction.contains(windowDisposition)) { + RecordUserAction.record( + "Suggestions.Tile.Tapped." + BrowserUiUtils.getHostName(hostSurface)); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java index ef235d0..52f7baf5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java
@@ -51,7 +51,6 @@ import org.chromium.chrome.features.start_surface.StartSurfaceState; import org.chromium.chrome.features.start_surface.StartSurfaceUserData; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; -import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.segmentation_platform.SegmentSelectionResult; import org.chromium.components.segmentation_platform.SegmentationPlatformService; @@ -287,17 +286,12 @@ StartSurfaceUserData.setOpenedFromStart(newTab); } - if (params.getTransitionType() == PageTransition.AUTO_BOOKMARK) { - if (!TextUtils.equals(UrlConstants.RECENT_TABS_URL, params.getUrl()) - && params.getReferrer() == null) { - RecordUserAction.record("Suggestions.Tile.Tapped.StartSurface"); - } - } else if (url == null) { - RecordUserAction.record("MobileMenuNewTab.StartSurfaceFinale"); - } else { + int transitionAfterMask = params.getTransitionType() & PageTransition.CORE_MASK; + if (transitionAfterMask == PageTransition.TYPED + || transitionAfterMask == PageTransition.GENERATED) { RecordUserAction.record("MobileOmniboxUse.StartSurface"); - // These are duplicated here but would have been recorded by LocationBarLayout#loadUrl. + // These are not duplicated here with the recording in LocationBarLayout#loadUrl. RecordUserAction.record("MobileOmniboxUse"); LocaleManager.getInstance().recordLocaleBasedSearchMetrics( false, url, params.getTransitionType());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index d4965f7..2ec1301d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -704,6 +704,7 @@ // the tab is non-interactive (e.g. when entering the TabSwitcher or Start surface). // In those cases we actually still want to use the most recently selected tab, but // will update the URL. + onBackPressStateChanged(); if (tab == null) { mLocationBarModel.notifyUrlChanged(); return; @@ -2115,7 +2116,8 @@ } private void onBackPressStateChanged() { - mBackPressStateSupplier.set(mToolbarTabController.canGoBack()); + Tab tab = mActivityTabProvider.get(); + mBackPressStateSupplier.set(tab != null && mToolbarTabController.canGoBack()); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS index 2e22e01a..3f3a939 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -1,5 +1 @@ -dominickn@chromium.org -eirage@chromium.org -hartmanng@chromium.org -peconn@chromium.org -peter@chromium.org +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java index 3d8bfe4..2b29be7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
@@ -37,7 +37,10 @@ import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.back_press.BackPressManager; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabObserver; @@ -45,13 +48,16 @@ import org.chromium.chrome.browser.tab.TabUtils.UseDesktopUserAgentCaller; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelUtils; +import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; import org.chromium.chrome.browser.toolbar.ToolbarManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; +import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.TabLoadObserver; +import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.ContentFeatureList; import org.chromium.content_public.browser.LoadUrlParams; @@ -564,6 +570,51 @@ onView(withId(R.id.back_button)).check(matches(Matchers.not(isEnabled()))); } + /** + * Test back with tab switcher. + */ + @Test + @MediumTest + @Feature({"Navigation"}) + @Features.DisableFeatures({ChromeFeatureList.BACK_GESTURE_REFACTOR}) + public void testNavigateBackWithTabSwitcher() throws Exception { + final String[] urls = {mTestServer.getURL("/chrome/test/data/android/navigate/one.html"), + mTestServer.getURL("/chrome/test/data/android/navigate/two.html"), + mTestServer.getURL("/chrome/test/data/android/navigate/three.html")}; + + for (String url : urls) { + navigateAndObserve(url); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + TabUiTestHelper.enterTabSwitcher(cta); + Assert.assertTrue(cta.getLayoutManager().isLayoutVisible(LayoutType.TAB_SWITCHER)); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mActivityTestRule.getActivity().getOnBackPressedDispatcher().onBackPressed(); + }); + CriteriaHelper.pollInstrumentationThread(() -> { + int type = mActivityTestRule.getActivity().getLayoutManager().getActiveLayoutType(); + Assert.assertEquals(LayoutType.BROWSING, type); + }); + } + + /** + * Test back with tab switcher. + */ + @Test + @MediumTest + @Feature({"Navigation"}) + @Features.EnableFeatures({ChromeFeatureList.BACK_GESTURE_REFACTOR}) + public void testNavigateBackWithTabSwitcher_BackPressRefactor() throws Exception { + // Disable iph + TestThreadUtils.runOnUiThreadBlocking(() -> { + BackPressManager backPressManager = + mActivityTestRule.getActivity().getBackPressManagerForTesting(); + backPressManager.removeHandler(BackPressHandler.Type.TEXT_BUBBLE); + }); + testNavigateBackWithTabSwitcher(); + } + @Test @DisableIf.Build(hardware_is = "sprout", message = "fails on android-one: crbug.com/540723") @DisabledTest(message = "https://crbug.com/1269027")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 43ef946..7a5cc03 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -794,6 +794,64 @@ @Test @SmallTest @Feature({"Browser", "ContextMenu"}) + @CommandLineFlags. + Add({"enable-features=" + ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_SEARCH_OPTIMIZATIONS + + "<FakeStudyName", + "force-fieldtrials=FakeStudyName/Enabled", + "force-fieldtrial-params=FakeStudyName.Enabled:useLensContextMenuAlternateText1/true"}) + @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) + public void + testSearchImageWithGoogleLensAltText1MenuItemName() throws Throwable { + Tab tab = mDownloadTestRule.getActivity().getActivityTab(); + + LensUtils.setFakePassableLensEnvironmentForTesting(true); + ShareHelper.setIgnoreActivityNotFoundExceptionForTesting(true); + hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION); + + ContextMenuCoordinator menu = ContextMenuUtils.openContextMenu(tab, "testImage"); + Integer[] expectedItems = {R.id.contextmenu_save_image, + R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image, + R.id.contextmenu_copy_image, R.id.contextmenu_search_with_google_lens}; + expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, + new Integer[] {R.id.contextmenu_open_image_in_ephemeral_tab}); + String title = getMenuTitleFromItem(menu, R.id.contextmenu_search_with_google_lens); + Assert.assertTrue("Context menu item name should be \'Search image with Google\'.", + title.startsWith("Search image with Google")); + assertMenuItemsAreEqual(menu, expectedItems); + } + + @Test + @SmallTest + @Feature({"Browser", "ContextMenu"}) + @CommandLineFlags. + Add({"enable-features=" + ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_SEARCH_OPTIMIZATIONS + + "<FakeStudyName", + "force-fieldtrials=FakeStudyName/Enabled", + "force-fieldtrial-params=FakeStudyName.Enabled:useLensContextMenuAlternateText2/true"}) + @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) + public void + testSearchImageWithGoogleLensAltText2MenuItemName() throws Throwable { + Tab tab = mDownloadTestRule.getActivity().getActivityTab(); + + LensUtils.setFakePassableLensEnvironmentForTesting(true); + ShareHelper.setIgnoreActivityNotFoundExceptionForTesting(true); + hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION); + + ContextMenuCoordinator menu = ContextMenuUtils.openContextMenu(tab, "testImage"); + Integer[] expectedItems = {R.id.contextmenu_save_image, + R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image, + R.id.contextmenu_copy_image, R.id.contextmenu_search_with_google_lens}; + expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, + new Integer[] {R.id.contextmenu_open_image_in_ephemeral_tab}); + String title = getMenuTitleFromItem(menu, R.id.contextmenu_search_with_google_lens); + Assert.assertTrue("Context menu item name should be \'Search inside image with Google\'.", + title.startsWith("Search inside image with Google")); + assertMenuItemsAreEqual(menu, expectedItems); + } + + @Test + @SmallTest + @Feature({"Browser", "ContextMenu"}) public void testCopyImage() throws Throwable { // Clear the clipboard. Clipboard.getInstance().setText("");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index becc710..135ac06 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -547,8 +547,7 @@ () -> mPanel.onSearchTermResolved("search", null, "tel:555-555-5555", QuickActionCategory.PHONE, CardTag.CT_CONTACT, - null /* relatedSearchesInBar */, - false /* showDefaultSearchInBar */)); + null /* relatedSearchesInBar */)); ContextualSearchBarControl barControl = mPanel.getSearchBarControl(); ContextualSearchQuickActionControl quickActionControl = barControl.getQuickActionControl(); @@ -613,8 +612,7 @@ () -> mPanel.onSearchTermResolved("search", null, "tel:555-555-5555", QuickActionCategory.PHONE, CardTag.CT_CONTACT, - null /* relatedSearchesInBar */, - false /* showDefaultSearchInBar */)); + null /* relatedSearchesInBar */)); sActivityTestRule.getActivity().onUserInteraction(); retryPanelBarInteractions(() -> { @@ -647,8 +645,7 @@ () -> mPanel.onSearchTermResolved("search", null, testUrl, QuickActionCategory.WEBSITE, CardTag.CT_URL, - null /* relatedSearchesInBar */, - false /* showDefaultSearchInBar */)); + null /* relatedSearchesInBar */)); retryPanelBarInteractions(() -> { // Tap on the portion of the bar that should trigger the quick action. clickPanelBar(); @@ -665,8 +662,8 @@ TestThreadUtils.runOnUiThreadBlocking( () -> mPanel.onSearchTermResolved("obscure · əbˈskyo͝or", null, null, - QuickActionCategory.NONE, cardTag, null /* relatedSearchesInBar */, - false /* showDefaultSearchInBar */)); + QuickActionCategory.NONE, cardTag, + null /* relatedSearchesInBar */)); expandPanelAndAssert(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java index 43a9c3d7..f3e1d82 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
@@ -113,9 +113,6 @@ public void testRelatedSearchesInBarWithDefaultQuery() throws Exception { FeatureList.TestValues testValues = new FeatureList.TestValues(); testValues.setFeatureFlagsOverride(ENABLE_RELATED_SEARCHES_IN_BAR); - testValues.addFieldTrialParamOverride(ChromeFeatureList.RELATED_SEARCHES_IN_BAR, - ContextualSearchFieldTrial.RELATED_SEARCHES_SHOW_DEFAULT_QUERY_CHIP_PARAM_NAME, - "true"); FeatureList.setTestValues(testValues); mFakeServer.reset(); @@ -147,9 +144,6 @@ public void testRelatedSearchesInBarWithDefaultQuery_HighlightDefaultQuery() throws Exception { FeatureList.TestValues testValues = new FeatureList.TestValues(); testValues.setFeatureFlagsOverride(ENABLE_RELATED_SEARCHES_IN_BAR); - testValues.addFieldTrialParamOverride(ChromeFeatureList.RELATED_SEARCHES_IN_BAR, - ContextualSearchFieldTrial.RELATED_SEARCHES_SHOW_DEFAULT_QUERY_CHIP_PARAM_NAME, - "true"); FeatureList.setTestValues(testValues); mFakeServer.reset(); @@ -179,9 +173,6 @@ public void testRelatedSearchesInBarWithDefaultQuery_Ellipsize() throws Exception { FeatureList.TestValues testValues = new FeatureList.TestValues(); testValues.setFeatureFlagsOverride(ENABLE_RELATED_SEARCHES_IN_BAR); - testValues.addFieldTrialParamOverride(ChromeFeatureList.RELATED_SEARCHES_IN_BAR, - ContextualSearchFieldTrial.RELATED_SEARCHES_SHOW_DEFAULT_QUERY_CHIP_PARAM_NAME, - "true"); FeatureList.setTestValues(testValues); mFakeServer.reset(); @@ -224,7 +215,7 @@ () -> mPanel.onSearchTermResolved("obscure · əbˈskyo͝or", null, null, QuickActionCategory.NONE, ResolvedSearchTerm.CardTag.CT_DEFINITION, - inBarSuggestions, false /* showDefaultSearchInBar */)); + inBarSuggestions)); boolean didPanelGetTaller = mPanel.getHeight() > normalHeight; Assert.assertTrue( "Related Searches should show in a taller Bar when there's a definition card, "
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java index 58f64e3..7e50932 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -178,9 +178,17 @@ BASE_PATH + "navigation_from_long_timeout.html"; private static final String NAVIGATION_FROM_PAGE_SHOW = BASE_PATH + "navigation_from_page_show.html"; + private static final String NAVIGATION_TO_SELF_PARENT_FRAME_PAGE = + BASE_PATH + "navigation_to_self_with_fallback_parent.html"; + private static final String NAVIGATION_TO_SELF_PAGE = + BASE_PATH + "navigation_to_self_with_fallback.html"; private static final String OTHER_BROWSER_PACKAGE = "com.other.browser"; - private static final String NON_BROWSER_PACKAGE = "not.a.browser"; + // Needs to be a real package on the device so we can get an icon from it. It will not be + // launched. + private static final String NON_BROWSER_PACKAGE = "com.android.settings"; + + private static final String EXTERNAL_APP_SCHEME = "externalappscheme"; @Mock private RedirectHandler mRedirectHandler; @@ -224,7 +232,9 @@ private static class TestContext extends ContextWrapper { private boolean mResolveToNonBrowserPackage; private String mHostToMatch; + private String mSchemeToMatch; private IntentFilter mFilterForHostMatch; + private IntentFilter mFilterForSchemeMatch; public TestContext(Context baseContext) { super(baseContext); @@ -248,6 +258,11 @@ mFilterForHostMatch = filter; } + private void setIntentFilterForScheme(String scheme, IntentFilter filter) { + mSchemeToMatch = scheme; + mFilterForSchemeMatch = filter; + } + @Override public PackageManager getPackageManager() { return new PackageManagerWrapper(super.getPackageManager()) { @@ -270,6 +285,13 @@ return Arrays.asList(info); } + if (mSchemeToMatch != null && intent.getScheme() != null + && intent.getScheme().equals(mSchemeToMatch)) { + ResolveInfo info = newResolveInfo(NON_BROWSER_PACKAGE); + info.filter = mFilterForSchemeMatch; + return Arrays.asList(info); + } + return TestContext.super.getPackageManager().queryIntentActivities( intent, flags); } @@ -284,6 +306,13 @@ return newResolveInfo(OTHER_BROWSER_PACKAGE); } + if (mSchemeToMatch != null && intent.getScheme() != null + && intent.getScheme().equals(mSchemeToMatch)) { + ResolveInfo info = newResolveInfo(NON_BROWSER_PACKAGE); + info.filter = mFilterForSchemeMatch; + return info; + } + // Behave as though play store is not installed - this matches bot emulator // images. if (targetsPlay(intent)) return null; @@ -307,10 +336,11 @@ ContextUtils.initApplicationContextForTests(mTestContext); IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW); filter.addCategory(Intent.CATEGORY_BROWSABLE); - filter.addDataScheme("externalappscheme"); + filter.addDataScheme(EXTERNAL_APP_SCHEME); mActivityMonitor = InstrumentationRegistry.getInstrumentation().addMonitor( filter, new Instrumentation.ActivityResult(Activity.RESULT_OK, null), true); mTestServer = mActivityTestRule.getTestServer(); + mTestContext.setIntentFilterForScheme(EXTERNAL_APP_SCHEME, filter); } @After @@ -537,15 +567,15 @@ private void assertMessagePresent() throws Exception { PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); - ApplicationInfo selfInfo = ContextUtils.getApplicationContext().getApplicationInfo(); - CharSequence selfLabel = pm.getApplicationLabel(selfInfo); + ApplicationInfo applicationInfo = pm.getApplicationInfo(NON_BROWSER_PACKAGE, 0); + CharSequence label = pm.getApplicationLabel(applicationInfo); PropertyModel message = getCurrentExternalNavigationMessage(); Assert.assertNotNull(message); Assert.assertThat(message.get(MessageBannerProperties.TITLE), - Matchers.containsString(selfLabel.toString())); + Matchers.containsString(label.toString())); Assert.assertThat(message.get(MessageBannerProperties.DESCRIPTION).toString(), - Matchers.containsString(selfLabel.toString())); + Matchers.containsString(label.toString())); Assert.assertNotNull(message.get(MessageBannerProperties.ICON)); } @@ -1171,7 +1201,8 @@ @LargeTest public void testServerRedirectionFromIntent() throws Exception { TestWebServer webServer = TestWebServer.start(); - final String redirectTargetUrl = "intent://test/#Intent;scheme=externalappscheme;end"; + final String redirectTargetUrl = + "intent://test/#Intent;scheme=" + EXTERNAL_APP_SCHEME + ";end"; final String redirectUrl = webServer.setRedirect("/302.html", redirectTargetUrl); Context context = ContextUtils.getApplicationContext(); @@ -1347,4 +1378,64 @@ Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(1)); }, 10000L, CriteriaHelper.DEFAULT_POLLING_INTERVAL); } + + @Test + @SmallTest + @Features.EnableFeatures({ExternalIntentsFeatures.EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME, + ExternalIntentsFeatures.BLOCK_SUBFRAME_INTENT_TO_SELF_NAME}) + public void + testSubframeNavigationToSelf() throws Exception { + mActivityTestRule.startMainActivityOnBlankPage(); + + String targetUrl = mTestServer.getURL(HELLO_PAGE); + // Strip off the https: from the URL. + String strippedTargetUrl = targetUrl.substring(6); + String subframeTarget = "intent:" + strippedTargetUrl + "#Intent;scheme=https;package=" + + ContextUtils.getApplicationContext().getPackageName() + ";S.browser_fallback_url=" + + "https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.android.chrome" + + ";end"; + + // The replace_text parameters for NAVIGATION_TO_SELF_PAGE, which is loaded in + // the iframe in NAVIGATION_TO_SELF_PARENT_FRAME_PAGE, have to go through the + // embedded test server twice and, as such, have to be base64-encoded twice. + byte[] paramBase64Name = ApiCompatibilityUtils.getBytesUtf8("PARAM_BASE64_NAME"); + byte[] base64ParamTargetUrl = Base64.encode( + ApiCompatibilityUtils.getBytesUtf8("PARAM_SELF_URL"), Base64.URL_SAFE); + byte[] paramBase64Value = ApiCompatibilityUtils.getBytesUtf8("PARAM_BASE64_VALUE"); + byte[] base64TargetUrl = + Base64.encode(ApiCompatibilityUtils.getBytesUtf8(subframeTarget), Base64.URL_SAFE); + + String originalUrl = mTestServer.getURL(NAVIGATION_TO_SELF_PARENT_FRAME_PAGE + + "?replace_text=" + Base64.encodeToString(paramBase64Name, Base64.URL_SAFE) + ":" + + Base64.encodeToString(base64ParamTargetUrl, Base64.URL_SAFE) + + "&replace_text=" + Base64.encodeToString(paramBase64Value, Base64.URL_SAFE) + ":" + + Base64.encodeToString(base64TargetUrl, Base64.URL_SAFE)); + + final Tab tab = mActivityTestRule.getActivity().getActivityTab(); + + final CallbackHelper subframeRedirect = new CallbackHelper(); + EmptyTabObserver observer = new EmptyTabObserver() { + @Override + public void onDidStartNavigationInPrimaryMainFrame( + Tab tab, NavigationHandle navigation) { + Assert.assertEquals(originalUrl, navigation.getUrl().getSpec()); + } + + @Override + public void onDidRedirectNavigation(Tab tab, NavigationHandle navigation) { + Assert.assertFalse(navigation.isInPrimaryMainFrame()); + if (targetUrl.equals(navigation.getUrl().getSpec())) { + subframeRedirect.notifyCalled(); + } + } + }; + TestThreadUtils.runOnUiThreadBlocking(() -> { tab.addObserver(observer); }); + + // Fallback URL from a subframe will not trigger main navigation. + OverrideUrlLoadingResult result = + loadUrlAndWaitForIntentUrl(originalUrl, true, false, false, originalUrl, false); + Assert.assertEquals( + OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, result.getResultType()); + subframeRedirect.waitForFirst(); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index ffe28f78..3f65b4e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -34,16 +34,20 @@ import org.junit.Assert; import org.junit.Assume; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.chromium.base.Callback; import org.chromium.base.FeatureList; import org.chromium.base.GarbageCollectionTestUtils; import org.chromium.base.MemoryPressureListener; import org.chromium.base.memory.MemoryPressureCallback; +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.test.metrics.HistogramTestRule; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterProvider; import org.chromium.base.test.params.ParameterSet; @@ -57,6 +61,7 @@ import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.feed.FeedReliabilityLogger; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -66,8 +71,11 @@ import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.suggestions.SiteSuggestion; +import org.chromium.chrome.browser.suggestions.tile.Tile; +import org.chromium.chrome.browser.suggestions.tile.TileGroup; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeRenderTestRule; @@ -83,12 +91,14 @@ import org.chromium.components.policy.test.annotations.Policies; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.test.NativeLibraryTestUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.content_public.browser.test.util.TouchCommon; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.util.TestWebServer; import org.chromium.ui.base.PageTransition; +import org.chromium.ui.mojom.WindowOpenDisposition; import org.chromium.url.GURL; import java.io.IOException; @@ -128,12 +138,16 @@ private static final int RENDER_TEST_REVISION = 5; + private static final String HISTOGRAM_NTP_MODULE_CLICK = "NewTabPage.Module.Click"; + @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @Rule public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule(); @Rule public SigninTestRule mSigninTestRule = new SigninTestRule(); + @Rule + public HistogramTestRule mHistogramTestRule = new HistogramTestRule(); @Rule public ChromeRenderTestRule mRenderTestRule = @@ -149,10 +163,15 @@ FeedReliabilityLogger mFeedReliabilityLogger; @Mock private TemplateUrlService mTemplateUrlService; + @Mock + private Callback mOnVisitComplete; + @Mock + private Runnable mOnPageLoaded; private static final String TEST_PAGE = "/chrome/test/data/android/navigate/simple.html"; private static final String TEST_FEED = UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/hello_world.gcl.bin"); + private static final String TEST_URL = "https://www.example.com/"; private Tab mTab; private NewTabPage mNtp; @@ -173,6 +192,14 @@ FeatureList.setTestValues(testValuesOverride); } + @BeforeClass + public static void setUpBeforeActivityLaunched() { + // Only needs to be loaded once and needs to be loaded before HistogramTestRule. + // TODO(https://crbug.com/1211884): Revise after HistogramTestRule is revised to not require + // native loading. + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -307,6 +334,10 @@ } }); Assert.assertEquals(mSiteSuggestions.get(0).url, ChromeTabUtils.getUrlOnUiThread(mTab)); + + assertEquals(1, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); } /** @@ -339,6 +370,10 @@ mMvTilesLayout.getChildAt(0), ContextMenuManager.ContextMenuItemId.OPEN_IN_INCOGNITO_TAB, true, mSiteSuggestions.get(0).url.getSpec()); + + assertEquals(1, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); } /** @@ -641,6 +676,138 @@ }); } + /** + * Test whether the clicking action on MV tiles in {@link NewTabPage} is been recorded in + * histogram correctly. + */ + @Test + @SmallTest + public void testRecordHistogramMostVisitedItemClick_Ntp() { + Tile tileForTest = new Tile(mSiteSuggestions.get(0), 0); + TestThreadUtils.runOnUiThreadBlocking(() -> { + TileGroup.Delegate tileGroupDelegate = mNtp.getTileGroupDelegateForTesting(); + + // Test clicking on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.CURRENT_TAB, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when click on MV tiles.", + 1, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in new tab in group on MV tiles. + tileGroupDelegate.openMostVisitedItemInGroup( + WindowOpenDisposition.NEW_BACKGROUND_TAB, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then open in new tab in " + + "group on MV tiles.", + 2, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in new tab on MV tiles. + tileGroupDelegate.openMostVisitedItem( + WindowOpenDisposition.NEW_BACKGROUND_TAB, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then open in new tab " + + "on MV tiles.", + 3, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in other window on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.NEW_WINDOW, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " shouldn't be recorded when long press then open in other " + + "window on MV tiles.", + 3, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then download link on MV tiles. + tileGroupDelegate.openMostVisitedItem(WindowOpenDisposition.SAVE_TO_DISK, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then download link on " + + "MV tiles.", + 4, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + + // Test long press then open in Incognito tab on MV tiles. + tileGroupDelegate.openMostVisitedItem( + WindowOpenDisposition.OFF_THE_RECORD, tileForTest); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then open in Incognito " + + "tab on MV tiles.", + 5, + mHistogramTestRule.getHistogramValueCount(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.MOST_VISITED_TILES)); + }); + } + + /** + * Test whether the clicking action on Feeds in {@link NewTabPage} is been recorded in + * histogram correctly. + */ + @Test + @SmallTest + public void testRecordHistogramFeedClick_Ntp() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + FeedActionDelegate feedActionDelegate = mNtp.getFeedActionDelegateForTesting(); + + // Test click on Feeds or long press then check about this source & topic on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.CURRENT_TAB, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when click on Feeds " + + "or long press then check about this source & topic on Feeds.", + 1, + RecordHistogram.getHistogramValueCountForTesting(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test long press then open in new tab on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.NEW_BACKGROUND_TAB, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then open in " + + "new tab on Feeds.", + 2, + RecordHistogram.getHistogramValueCountForTesting(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test long press then open in incognito tab on Feeds. + feedActionDelegate.openSuggestionUrl(WindowOpenDisposition.OFF_THE_RECORD, + new LoadUrlParams(TEST_URL, PageTransition.AUTO_BOOKMARK), false, mOnPageLoaded, + mOnVisitComplete); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when long press then open " + + "in incognito tab on Feeds.", + 3, + RecordHistogram.getHistogramValueCountForTesting(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test manage activity or manage interests on Feeds. + feedActionDelegate.openUrl(WindowOpenDisposition.CURRENT_TAB, + new LoadUrlParams(TEST_URL, PageTransition.LINK)); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " shouldn't be recorded when manage activity or manage interests " + + "on Feeds.", + 3, + RecordHistogram.getHistogramValueCountForTesting(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + + // Test click Learn More button on Feeds. + feedActionDelegate.openHelpPage(); + assertEquals(HISTOGRAM_NTP_MODULE_CLICK + + " is not recorded correctly when click Learn More button on Feeds.", + 4, + RecordHistogram.getHistogramValueCountForTesting(HISTOGRAM_NTP_MODULE_CLICK, + BrowserUiUtils.ModuleTypeOnStartAndNTP.FEED)); + }); + } + private void assertThumbnailInvalidAndRecapture() { Assert.assertTrue(mNtp.shouldCaptureThumbnail()); captureThumbnail();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesTest.java index c9bbbbd..2d30e27 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesTest.java
@@ -15,7 +15,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_EXPANDED_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_WITH_HEADER; import android.view.KeyEvent; import android.view.View; @@ -168,8 +168,8 @@ mTile3 = new SuggestTile( "Test Server", new GURL(mTestServer.getURL("/echo/tile3.html")), false); - AutocompleteResult autocompleteResult = AutocompleteResult.fromCache(null, - GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_EXPANDED_WITH_HEADER).build()); + AutocompleteResult autocompleteResult = AutocompleteResult.fromCache( + null, GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_WITH_HEADER).build()); AutocompleteMatchBuilder builder = new AutocompleteMatchBuilder(); // First suggestion is the current content of the Omnibox.
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 6bf40ee..0376704a 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
@@ -255,6 +255,7 @@ mSigninTestRule.addAccount( CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); + when(mPolicyLoadListenerMock.get()).thenReturn(true); checkFragmentWithChildAccount( /* hasDisplayableFullName= */ true, /* hasDisplayableEmail= */ true); @@ -315,7 +316,7 @@ launchActivityWithFragment(); checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); - onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); + onView(withId(R.id.fre_browser_managed_by)).check(matches(not(isDisplayed()))); } @Test @@ -434,7 +435,7 @@ onView(withText(TEST_EMAIL2)).inRoot(isDialog()).perform(click()); checkFragmentWithSelectedAccount(TEST_EMAIL2, /* fullName= */ null, /* givenName= */ null); - onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); + onView(withId(R.id.fre_browser_managed_by)).check(matches(not(isDisplayed()))); } @Test @@ -446,7 +447,7 @@ launchActivityWithFragment(); checkFragmentWithSelectedAccount(TEST_EMAIL1, FULL_NAME1, GIVEN_NAME1); - onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(isDisplayed())); + onView(withId(R.id.fre_browser_managed_by)).check(matches(isDisplayed())); } @Test @@ -454,9 +455,9 @@ public void testFragmentWithChildAccount() { mSigninTestRule.addAccount( CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null); + when(mPolicyLoadListenerMock.get()).thenReturn(true); launchActivityWithFragment(); - checkFragmentWithChildAccount( /* hasDisplayableFullName= */ true, /* hasDisplayableEmail= */ true); } @@ -467,6 +468,7 @@ ChromeFeatureList.sHideNonDisplayableAccountEmail.setForTesting(true); mSigninTestRule.addAccount(CHILD_ACCOUNT_EMAIL, CHILD_FULL_NAME, /* givenName= */ null, /* avatar= */ null, SigninTestRule.NON_DISPLAYABLE_EMAIL_ACCOUNT_CAPABILITIES); + when(mPolicyLoadListenerMock.get()).thenReturn(true); launchActivityWithFragment(); @@ -480,6 +482,7 @@ ChromeFeatureList.sHideNonDisplayableAccountEmail.setForTesting(true); mSigninTestRule.addAccount(CHILD_ACCOUNT_EMAIL, /* fullName= */ null, /* givenName= */ null, /* avatar= */ null, SigninTestRule.NON_DISPLAYABLE_EMAIL_ACCOUNT_CAPABILITIES); + when(mPolicyLoadListenerMock.get()).thenReturn(true); launchActivityWithFragment(); @@ -1172,7 +1175,9 @@ onView(withText(continueAsText)).check(matches(isDisplayed())); onView(withId(R.id.signin_fre_footer)).check(matches(isDisplayed())); onView(withText(R.string.signin_fre_dismiss_button)).check(matches(not(isDisplayed()))); - onView(withId(R.id.fre_browser_managed_by_organization)).check(matches(not(isDisplayed()))); + onView(withId(R.id.fre_browser_managed_by)).check(matches(isDisplayed())); + onView(withId(R.id.privacy_disclaimer)).check(matches(isDisplayed())); + onView(withText(R.string.fre_browser_managed_by_parents)).check(matches(isDisplayed())); } private void checkContinueButtonWithChildAccount(boolean hasFullNameInButtonText) { @@ -1197,7 +1202,7 @@ return !mFragment.getView().findViewById(R.id.signin_fre_selected_account).isShown(); }); verify(mFirstRunPageDelegateMock).recordNativePolicyAndChildStatusLoadedHistogram(); - ViewUtils.waitForView(withId(R.id.fre_browser_managed_by_organization)); + ViewUtils.waitForView(withId(R.id.fre_browser_managed_by)); ViewUtils.waitForView(withText(R.string.continue_button)); ViewUtils.waitForView(withId(R.id.signin_fre_footer)); onView(withId(R.id.signin_fre_dismiss_button)).check(matches(not(isDisplayed())));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java index 46f798b8..60f413c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesLayoutTest.java
@@ -59,6 +59,7 @@ import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.ui.native_page.TouchEnabledDelegate; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ActivityTestUtils; @@ -355,7 +356,8 @@ SuggestionsUiDelegate uiDelegate = new SuggestionsUiDelegateImpl(null, profile, null, activity.getSnackbarManager()); - TileGroup.Delegate delegate = new TileGroupDelegateImpl(activity, profile, null, null) { + TileGroup.Delegate delegate = new TileGroupDelegateImpl( + activity, profile, null, null, BrowserUiUtils.HostSurface.NOT_SET) { @Override public void onLoadingComplete(List<Tile> tiles) { super.onLoadingComplete(tiles);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS index 7b6517c..3f3a939 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -1 +1 @@ -file://chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java index 1e6ff18..c13dd61 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java
@@ -38,7 +38,6 @@ import org.chromium.components.offline_items_collection.PendingState; import org.chromium.ui.permissions.ContextualNotificationPermissionRequester; -import java.util.ArrayList; import java.util.List; /** @@ -103,17 +102,14 @@ new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier); verify(mProvider, times(1)).addObserver(bridge); - ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() { - { - add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS)); - add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING)); - add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE)); - add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED)); - add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED)); - add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED)); - add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); - } - }; + List<OfflineItem> items = List.of( + buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS), + buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING), + buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE), + buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED), + buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED), + buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED), + buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); bridge.onItemsAdded(items); @@ -156,17 +152,14 @@ new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier); verify(mProvider, times(1)).addObserver(bridge); - ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() { - { - add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS)); - add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING)); - add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE)); - add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED)); - add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED)); - add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED)); - add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); - } - }; + List<OfflineItem> items = List.of( + buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS), + buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING), + buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE), + buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED), + buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED), + buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED), + buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); for (int i = 0; i < items.size(); i++) bridge.onItemUpdated(items.get(i), null); @@ -297,21 +290,15 @@ new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier); verify(mProvider, times(1)).addObserver(bridge); - ArrayList<OfflineItem> interestingItems = new ArrayList<OfflineItem>() { - { - add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS)); - add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING)); - add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE)); - add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED)); - add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); - } - }; + List<OfflineItem> interestingItems = + List.of(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS), + buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING), + buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE), + buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED), + buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED)); - ArrayList<OfflineItem> uninterestingItems = new ArrayList<OfflineItem>() { - { - add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED)); - } - }; + List<OfflineItem> uninterestingItems = + List.of(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED)); for (int i = 0; i < interestingItems.size(); i++) { OfflineItem item = interestingItems.get(i);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedActionDelegateImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedActionDelegateImplTest.java index 23c20234..2bfb20f7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedActionDelegateImplTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedActionDelegateImplTest.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.signin.SyncConsentActivityLauncher; +import org.chromium.chrome.browser.util.BrowserUiUtils; import org.chromium.components.signin.metrics.SigninAccessPoint; /** Tests for FeedActionDelegateImpl. */ @@ -57,7 +58,7 @@ SyncConsentActivityLauncherImpl.setLauncherForTest(mMockSyncConsentActivityLauncher); mFeedActionDelegateImpl = new FeedActionDelegateImpl(ContextUtils.getApplicationContext(), mMockSnackbarManager, mMockNavigationDelegate, mMockBookmarkModel, - mMockCrowButtonDelegate); + mMockCrowButtonDelegate, BrowserUiUtils.HostSurface.NOT_SET); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/OWNERS index 7b6517c..3f3a939 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/OWNERS +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -1 +1 @@ -file://chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/android/modules/chrome_bundle_tmpl.gni b/chrome/android/modules/chrome_bundle_tmpl.gni index 2f3ce985..8f460c0 100644 --- a/chrome/android/modules/chrome_bundle_tmpl.gni +++ b/chrome/android/modules/chrome_bundle_tmpl.gni
@@ -27,14 +27,6 @@ _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome - # TODO(crbug.com/1408322): Delete once removed downstream. - if (defined(invoker.is_monochrome_or_trichrome)) { - not_needed(invoker, [ "is_monochrome_or_trichrome" ]) - _is_monochrome = - string_replace(target_name, "monochrome", "") != target_name - _is_trichrome = string_replace(target_name, "trichrome", "") != target_name - } - _enable_chrome_module = _is_monochrome || _is_trichrome # If enable_chrome_module is true, //chrome Java code and resources will be @@ -100,8 +92,6 @@ _is_multi_abi = (_is_64_bit_browser && _include_32_bit_webview) || (!_is_64_bit_browser && _include_64_bit_webview) } else { - # TODO(crbug.com/1408322): Delete once removed downstream. - not_needed(invoker, [ "include_32_bit_webview" ]) _is_multi_abi = false }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index cfcf144..6dc321c 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-111.0.5557.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-111.0.5558.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/webapk/OWNERS b/chrome/android/webapk/OWNERS index 3c94597..cfeaa1f 100644 --- a/chrome/android/webapk/OWNERS +++ b/chrome/android/webapk/OWNERS
@@ -1 +1,6 @@ -file://chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS \ No newline at end of file +dominickn@chromium.org +eirage@chromium.org +hartmanng@chromium.org +peconn@chromium.org +peter@chromium.org +yfriedman@chromium.org \ No newline at end of file
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 30bb919..d7b21d2a 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -65,6 +65,9 @@ #define IDC_MAXIMIZE_WINDOW 34047 #define IDC_ALL_WINDOWS_FRONT 34048 #define IDC_NAME_WINDOW 34049 +#if BUILDFLAG(IS_CHROMEOS) +#define IDC_TOGGLE_MULTITASK_MENU 34050 +#endif // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch of lacros-chrome is complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 89328d2..e828413 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5233,6 +5233,9 @@ <message name="IDS_MANAGE_EXTENSIONS" desc="The text of the button in the extensions toolbar menu used to open the chrome://extensions page and manage all extensions (sentence case)."> Manage extensions </message> + <message name="IDS_VIEW_WEB_PERMISSIONS" desc="The text for the button in the extension context menu used to open the chrome://settings/content/siteDetails?site=xxx page and view the site details for a specific extension (sentence case)."> + View web permissions + </message> <message name="IDS_EXTENSION_ACTION_INSPECT_POPUP" desc="The text for the right-click menu of page and browser actions which shows the popup and opens the developer tools (sentence case)."> Inspect popup </message> @@ -5316,6 +5319,9 @@ <message name="IDS_MANAGE_EXTENSIONS" desc="The text for the button in the extensions toolbar menu used to open the chrome://extensions page and manage all extensions (title case)."> Manage Extensions </message> + <message name="IDS_VIEW_WEB_PERMISSIONS" desc="The text for the button in the extension context menu used to open the chrome://settings/content/siteDetails?site=xxx page and view the site details for a specific extension (title case)."> + View Web Permissions + </message> <message name="IDS_EXTENSION_ACTION_INSPECT_POPUP" desc="The text for the right-click menu of page and browser actions which shows the popup and opens the developer tools (title case)."> Inspect Popup </message> @@ -5908,6 +5914,10 @@ Create shortcut </message> + <message name="IDS_APP_HOME_INSTALL_LOCALLY" desc="Menu entry label for installing the app on this device from context menu on App Home"> + Install on this device + </message> + <message name="IDS_APP_HOME_UNINSTALL_APP" desc="Menu entry label for uninstalling an app from context menu on App Home"> Uninstall </message>
diff --git a/chrome/app/generated_resources_grd/IDS_APP_HOME_INSTALL_LOCALLY.png.sha1 b/chrome/app/generated_resources_grd/IDS_APP_HOME_INSTALL_LOCALLY.png.sha1 new file mode 100644 index 0000000..cd4b270d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_APP_HOME_INSTALL_LOCALLY.png.sha1
@@ -0,0 +1 @@ +6bc27550b41495ff6b48e18599d57e9b4f9d6d4d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_VIEW_WEB_PERMISSIONS.png.sha1 b/chrome/app/generated_resources_grd/IDS_VIEW_WEB_PERMISSIONS.png.sha1 new file mode 100644 index 0000000..45b256a --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_VIEW_WEB_PERMISSIONS.png.sha1
@@ -0,0 +1 @@ +359a94f689a29e7441090ede0a3b7f7afa4509c6 \ No newline at end of file
diff --git a/chrome/app/password_manager_ui_strings.grdp b/chrome/app/password_manager_ui_strings.grdp index 44141cf..4787d8b 100644 --- a/chrome/app/password_manager_ui_strings.grdp +++ b/chrome/app/password_manager_ui_strings.grdp
@@ -242,4 +242,10 @@ <message name="IDS_PASSWORD_MANAGER_UI_MUTED_COMPROMISED_PASSWORDS" desc="Label which is shown for dismissed compromised passwords."> Dismissed warnings </message> + <message name="IDS_PASSWORD_MANAGER_UI_MUTE_ISSUE" desc="Action menu item for a row which displays a compromised password. It will mute/dismiss the compromised password warning."> + Dismiss warning + </message> + <message name="IDS_PASSWORD_MANAGER_UI_UNMUTE_ISSUE" desc="Action menu item for a row which displays a muted/dismissed compromised password. It will unmute/restore the compromised password and reenable the warning."> + Restore warning + </message> </grit-part>
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MUTE_ISSUE.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MUTE_ISSUE.png.sha1 new file mode 100644 index 0000000..a040fa8 --- /dev/null +++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_MUTE_ISSUE.png.sha1
@@ -0,0 +1 @@ +e35f12d9c54d33866f9e0c5192a22922cd3e994d \ No newline at end of file
diff --git a/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_UNMUTE_ISSUE.png.sha1 b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_UNMUTE_ISSUE.png.sha1 new file mode 100644 index 0000000..ec8058d --- /dev/null +++ b/chrome/app/password_manager_ui_strings_grdp/IDS_PASSWORD_MANAGER_UI_UNMUTE_ISSUE.png.sha1
@@ -0,0 +1 @@ +00dbf14e9b1c8a6eed246d2fbddc2554ee3dd9dd \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 92a1ab72..49942cf 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -49,8 +49,6 @@ "drag_handle.icon", "eol.icon", "extension_crashed.icon", - "eye.icon", - "eye_crossed.icon", "file_download_shelf.icon", "fingerprint.icon", "forward_arrow_touch.icon",
diff --git a/chrome/app_shim/app_mode_loader_mac.mm b/chrome/app_shim/app_mode_loader_mac.mm index d30c14f..be2a4ee2 100644 --- a/chrome/app_shim/app_mode_loader_mac.mm +++ b/chrome/app_shim/app_mode_loader_mac.mm
@@ -18,7 +18,6 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/mac/foundation_util.h" -#import "base/mac/launch_services_util.h" #include "base/process/launch.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" @@ -234,9 +233,8 @@ cr_command_line.AppendSwitchPath(switches::kProfileDirectory, profile_dir); cr_command_line.AppendSwitchASCII(switches::kAppId, app_mode_id); - // Launch the executable directly since base::mac::OpenApplicationWithPath - // doesn't pass command line arguments if the application is already - // running. + // Launch the executable directly since base::mac::LaunchApplication doesn't + // pass command line arguments if the application is already running. if (!base::LaunchProcess(cr_command_line, base::LaunchOptions()) .IsValid()) { NSLog(@"Could not launch Chrome: %s",
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm index 1aaa3a7..0df1f4aa 100644 --- a/chrome/app_shim/app_shim_controller.mm +++ b/chrome/app_shim/app_shim_controller.mm
@@ -16,7 +16,7 @@ #include "base/hash/md5.h" #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" -#include "base/mac/launch_services_util.h" +#include "base/mac/launch_application.h" #include "base/mac/mac_util.h" #include "base/mac/mach_logging.h" #include "base/memory/raw_ptr.h" @@ -218,9 +218,9 @@ app_command_line->GetSwitchValueASCII(switches::kDisableFeatures)); } - base::mac::OpenApplication( + base::mac::LaunchApplication( chrome_bundle_path, browser_command_line, /*url_specs=*/{}, - /*options=*/{.create_new_instance = true}, + {.create_new_instance = true}, base::BindOnce( [](AppShimController* shim_controller, base::expected<NSRunningApplication*, NSError*> result) {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 6fd94d13..42712ea 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2263,6 +2263,7 @@ "//components/safe_browsing/core/browser:safe_browsing_metrics_collector", "//components/safe_browsing/core/browser:verdict_cache_manager", "//components/safe_browsing/core/browser/db:database_manager", + "//components/safe_browsing/core/browser/hashprefix_realtime:hash_realtime_service", "//components/safe_browsing/core/browser/password_protection:password_protection_metrics_util", "//components/safe_browsing/core/browser/realtime:policy_engine", "//components/safe_browsing/core/browser/realtime:url_lookup_service", @@ -2324,6 +2325,7 @@ "//components/subresource_filter/content/browser", "//components/subresource_filter/core/browser", "//components/subresource_filter/core/common", + "//components/supervised_user/core/common", "//components/sync", "//components/sync_bookmarks", "//components/sync_preferences", @@ -3464,7 +3466,6 @@ deps += [ "//chrome/browser/supervised_user:jni_headers", "//components/supervised_user/core/browser", - "//components/supervised_user/core/common", ] } @@ -3484,12 +3485,6 @@ "accessibility/caption_bubble_context_browser.h", "accessibility/invert_bubble_prefs.cc", "accessibility/invert_bubble_prefs.h", - "accessibility/live_caption_controller_factory.cc", - "accessibility/live_caption_controller_factory.h", - "accessibility/live_caption_speech_recognition_host.cc", - "accessibility/live_caption_speech_recognition_host.h", - "accessibility/live_caption_unavailability_notifier.cc", - "accessibility/live_caption_unavailability_notifier.h", "accessibility/live_translate_controller_factory.cc", "accessibility/live_translate_controller_factory.h", "apps/intent_helper/apps_navigation_throttle.cc", @@ -4544,6 +4539,23 @@ "//chrome/browser/enterprise/connectors/device_trust/key_management/browser", ] } + + if (!is_chromeos_lacros) { + sources += [ + "accessibility/live_caption_controller_factory.cc", + "accessibility/live_caption_controller_factory.h", + "accessibility/live_caption_speech_recognition_host.cc", + "accessibility/live_caption_speech_recognition_host.h", + ] + } + + if (is_win) { + sources += [ + "accessibility/live_caption_unavailability_notifier.cc", + "accessibility/live_caption_unavailability_notifier.h", + ] + } + if (enable_extensions) { deps += [ "//extensions/browser", @@ -7394,8 +7406,6 @@ "supervised_user/parental_control_metrics.cc", "supervised_user/parental_control_metrics.h", "supervised_user/permission_request_creator.h", - "supervised_user/supervised_user_constants.cc", - "supervised_user/supervised_user_constants.h", "supervised_user/supervised_user_denylist.cc", "supervised_user/supervised_user_denylist.h", "supervised_user/supervised_user_google_auth_navigation_throttle.cc", @@ -7694,8 +7704,6 @@ deps = [ ":chrome_internal_resources_gen", - "//device/bluetooth/public/mojom:deprecated_experimental_interfaces_js", - "//device/bluetooth/public/mojom:mojom_js", "//url/mojom:url_mojom_gurl_js", "//url/mojom:url_mojom_origin_js", ] @@ -7749,7 +7757,6 @@ "//chrome/browser/ui/webui/ash/crostini_upgrader:mojo_bindings_js", "//chrome/browser/ui/webui/ash/parent_access:mojo_bindings_js", "//chrome/browser/ui/webui/ash/vm:mojo_bindings_js__generator", - "//chrome/browser/ui/webui/settings/ash:mojom_js", ] }
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 305f12f..5b73cdb 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -397,8 +397,7 @@ "+media/audio", # For media audio hang monitor. "+media/base", # For media switches "+media/capabilities", # For InMemoryVideoDecodeStatsDB - "+media/cdm/cdm_paths.h", - "+media/cdm/win/media_foundation_cdm.h", + "+media/cdm", "+media/remoting/device_capability_checker.h", "+media/capture", "+media/midi", # For midi switches
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0e5a3fc1..ef02cc02 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1159,7 +1159,6 @@ }; const FeatureEntry::FeatureParam kJourneysHiddenVisitsParams[] = { {"JourneysLocaleOrLanguageAllowlist", "*"}, - {"drop_hidden_visits", "false"}, }; const FeatureEntry::FeatureParam kJourneysShowAllVisitsParams[] = { {"JourneysLocaleOrLanguageAllowlist", "*"}, @@ -1167,7 +1166,6 @@ // high number. We drop the rest above this very high number because we // definitely don't want to surface a Show More UI after that number. {"JourneysNumVisitsToAlwaysShowAboveTheFold", "200"}, - {"drop_hidden_visits", "true"}, }; const FeatureEntry::FeatureParam kJourneysAllLocalesParams[] = { {"JourneysLocaleOrLanguageAllowlist", "*"}, @@ -1270,21 +1268,29 @@ kSidePanelJourneysOpensFromOmniboxParams, std::size(kSidePanelJourneysOpensFromOmniboxParams), nullptr}, }; -const FeatureEntry::FeatureParam kJourneysJaccardSimilarityParams[] = { - {"collections_blocklist", "/collection/it_glossary,/collection/software"}, - {"exclude_entities_that_have_no_collections", "true"}, - {"use_content_clustering_cosine_similarity", "false"}, +const FeatureEntry::FeatureParam + kJourneysCosineSimilarityNoPairwiseMergeParams[] = { + {"collections_blocklist", + "/collection/it_glosssary,/collection/software"}, + {"exclude_entities_that_have_no_collections", "true"}, + {"use_content_clustering_cosine_similarity", "true"}, + {"use_pairwise_merge", "false"}, }; -const FeatureEntry::FeatureParam kJourneysCosineSimilarityParams[] = { - {"collections_blocklist", "/collection/it_glosssary,/collection/software"}, - {"exclude_entities_that_have_no_collections", "true"}, - {"use_content_clustering_cosine_similarity", "true"}, +const FeatureEntry::FeatureParam + kJourneysCosineSimilarityWithPairwiseMergeParams[] = { + {"collections_blocklist", + "/collection/it_glosssary,/collection/software"}, + {"exclude_entities_that_have_no_collections", "true"}, + {"use_content_clustering_cosine_similarity", "true"}, + {"use_pairwise_merge", "true"}, }; const FeatureEntry::FeatureVariation kJourneysContentClusteringVariations[] = { - {"Jaccard Similarity With Blocklist", kJourneysJaccardSimilarityParams, - std::size(kJourneysJaccardSimilarityParams), nullptr}, - {"Cosine Similarity With Blocklist", kJourneysCosineSimilarityParams, - std::size(kJourneysCosineSimilarityParams), nullptr}, + {"Cosine Similarity With Blocklist and No Pairwise Merge", + kJourneysCosineSimilarityNoPairwiseMergeParams, + std::size(kJourneysCosineSimilarityNoPairwiseMergeParams), nullptr}, + {"Cosine Similarity With Blocklist and Pairwise Merge", + kJourneysCosineSimilarityWithPairwiseMergeParams, + std::size(kJourneysCosineSimilarityWithPairwiseMergeParams), nullptr}, }; const FeatureEntry::FeatureParam kJourneysLabelsWithEntitiesParams[] = { {"labels_from_entities", "true"}, @@ -1908,17 +1914,6 @@ {"extreme", &kRelatedSearchesUiExtreme, 1, nullptr}, }; -const FeatureEntry::FeatureParam kRelatedSearchesInBarNoShowDefaultChip = { - "default_query_chip", "false"}; -const FeatureEntry::FeatureParam kRelatedSearchesInBarShowDefaultChip = { - "default_query_chip", "true"}; -const FeatureEntry::FeatureVariation kRelatedSearchesInBarVariations[] = { - {"without default query chip", &kRelatedSearchesInBarNoShowDefaultChip, 1, - nullptr}, - {"with default query chip", &kRelatedSearchesInBarShowDefaultChip, 1, - nullptr}, -}; - const FeatureEntry::FeatureParam kContextualSearchSuppressShortViewWith300Dp[] = {{"contextual_search_minimum_page_height_dp", "300"}}; const FeatureEntry::FeatureParam kContextualSearchSuppressShortViewWith400Dp[] = @@ -2307,6 +2302,22 @@ std::size(kLensContextMenuSearchOnTablet), nullptr}, }; +const FeatureEntry::FeatureParam kContextMenuSearchImageWithGoogle[] = { + {"useLensContextMenuAlternateText1", "true"}}; + +const FeatureEntry::FeatureParam kContextMenuSearchInsideImageWithGoogle[] = { + {"useLensContextMenuAlternateText2", "true"}}; + +const FeatureEntry::FeatureVariation + kContextMenuGoogleLensSearchOptimizationVariations[] = { + {"Context Menu: Search image With Google", + kContextMenuSearchImageWithGoogle, + std::size(kContextMenuSearchImageWithGoogle), nullptr}, + {"Context Menu: Search inside image With Google", + kContextMenuSearchInsideImageWithGoogle, + std::size(kContextMenuSearchInsideImageWithGoogle), nullptr}, +}; + #endif // BUILDFLAG(IS_ANDROID) const FeatureEntry::Choice kNotificationSchedulerChoices[] = { @@ -3335,9 +3346,7 @@ "RelatedSearchesUi")}, {"related-searches-in-bar", flag_descriptions::kRelatedSearchesInBarName, flag_descriptions::kRelatedSearchesInBarDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kRelatedSearchesInBar, - kRelatedSearchesInBarVariations, - "RelatedSearchesInBar")}, + FEATURE_VALUE_TYPE(chrome::android::kRelatedSearchesInBar)}, #endif // BUILDFLAG(IS_ANDROID) {"show-autofill-type-predictions", flag_descriptions::kShowAutofillTypePredictionsName, @@ -4110,6 +4119,9 @@ flag_descriptions::kEnableServiceWorkersForChromeUntrustedDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kEnableServiceWorkersForChromeUntrusted)}, + {"enterprise-reporting-ui", flag_descriptions::kEnterpriseReportingUIName, + flag_descriptions::kEnterpriseReportingUIDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kEnterpriseReportingUI)}, {"crostini-reset-lxd-db", flag_descriptions::kCrostiniResetLxdDbName, flag_descriptions::kCrostiniResetLxdDbDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kCrostiniResetLxdDb)}, @@ -4260,6 +4272,16 @@ flag_descriptions::kDesktopPWAsDetailedInstallDialogName, flag_descriptions::kDesktopPWAsDetailedInstallDialogDescription, kOsAll, FEATURE_VALUE_TYPE(webapps::features::kDesktopPWAsDetailedInstallDialog)}, + {"enable-skip-service-worker-check-install-only", + flag_descriptions::kSkipServiceWorkerCheckInstallOnlyName, + flag_descriptions::kSkipServiceWorkerCheckInstallOnlyDescription, + kOsDesktop, + FEATURE_VALUE_TYPE(webapps::features::kSkipServiceWorkerCheckInstallOnly)}, + {"enable-skip-service-worker-check-install-for-promotion", + flag_descriptions::kSkipServiceWorkerForInstallPromptName, + flag_descriptions::kSkipServiceWorkerForInstallPromptDescription, + kOsDesktop, + FEATURE_VALUE_TYPE(webapps::features::kSkipServiceWorkerForInstallPrompt)}, {"record-web-app-debug-info", flag_descriptions::kRecordWebAppDebugInfoName, flag_descriptions::kRecordWebAppDebugInfoDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kRecordWebAppDebugInfo)}, @@ -6169,6 +6191,12 @@ {"cct-resizable-side-sheet", flag_descriptions::kCCTResizableSideSheetName, flag_descriptions::kCCTResizableSideSheetDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kCCTResizableSideSheet)}, + {"cct-resizable-side-sheet-for-third-parties", + flag_descriptions::kCCTResizableSideSheetForThirdPartiesName, + flag_descriptions::kCCTResizableSideSheetForThirdPartiesDescription, + kOsAndroid, + FEATURE_VALUE_TYPE( + chrome::android::kCCTResizableSideSheetForThirdParties)}, {"cct-retaining-state-in-memory", flag_descriptions::kCCTRetainingStateInMemoryName, flag_descriptions::kCCTRetainingStateInMemoryDescription, kOsAndroid, @@ -6628,6 +6656,11 @@ FEATURE_VALUE_TYPE( features::kAccessibilityAcceleratorNotificationsTimeout)}, + {"enable-chromevox-q1-fast-track-features", + flag_descriptions::kChromeVoxQ1FastTrackFeaturesName, + flag_descriptions::kChromeVoxQ1FastTrackFeaturesDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kChromeVoxQ1FastTrackFeatures)}, + {"enable-accessibility-service", flag_descriptions::kAccessibilityServiceName, flag_descriptions::kAccessibilityServiceDescription, kOsCrOS, @@ -6694,14 +6727,12 @@ browsing_data::features::kEnableRemovingAllThirdPartyCookies)}, {"enable-unsafe-webgpu", flag_descriptions::kUnsafeWebGPUName, - flag_descriptions::kUnsafeWebGPUDescription, - kOsMac | kOsLinux | kOsCrOS | kOsLacros | kOsWin | kOsFuchsia, + flag_descriptions::kUnsafeWebGPUDescription, kOsAll, SINGLE_VALUE_TYPE(switches::kEnableUnsafeWebGPU)}, {"enable-webgpu-developer-features", flag_descriptions::kWebGpuDeveloperFeaturesName, - flag_descriptions::kWebGpuDeveloperFeaturesDescription, - kOsMac | kOsLinux | kOsCrOS | kOsLacros | kOsWin | kOsFuchsia, + flag_descriptions::kWebGpuDeveloperFeaturesDescription, kOsAll, SINGLE_VALUE_TYPE(switches::kEnableWebGPUDeveloperFeatures)}, #if BUILDFLAG(IS_ANDROID) @@ -6892,6 +6923,15 @@ kLensContextMenuSearchVariations, "ContextMenuSearchWithGoogleLens")}, + {"context-menu-google-lens-search-optimizations", + flag_descriptions::kContextMenuGoogleLensSearchOptimizationsName, + flag_descriptions::kContextMenuGoogleLensSearchOptimizationsDescription, + kOsAndroid, + FEATURE_WITH_PARAMS_VALUE_TYPE( + chrome::android::kContextMenuGoogleLensSearchOptimizations, + kContextMenuGoogleLensSearchOptimizationVariations, + "ContextMenuGoogleLensSearchOptimizations")}, + {"lens-camera-assisted-search", flag_descriptions::kLensCameraAssistedSearchName, flag_descriptions::kLensCameraAssistedSearchDescription, kOsAndroid, @@ -7628,6 +7668,10 @@ flag_descriptions::kChromeLabsDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kChromeLabs)}, + {"chrome-refresh-2023", flag_descriptions::kChromeRefresh2023Name, + flag_descriptions::kChromeRefresh2023Description, kOsDesktop, + FEATURE_VALUE_TYPE(features::kChromeRefresh2023)}, + {"enable-first-party-sets", flag_descriptions::kEnableFirstPartySetsName, flag_descriptions::kEnableFirstPartySetsDescription, kOsAll, FEATURE_VALUE_TYPE(features::kFirstPartySets)},
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc index 45b2ac8b..8aed5e5 100644 --- a/chrome/browser/android/signin/signin_manager_android.cc +++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -28,8 +28,8 @@ #include "chrome/browser/signin/account_id_from_account_info.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "components/google/core/common/google_util.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/browser_context.h" @@ -111,7 +111,9 @@ // Returns whether the user is a managed user or not. bool ShouldLoadPolicyForUser(const std::string& username) { - return !policy::BrowserPolicyConnector::IsNonEnterpriseUser(username); + return signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + username) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus::kUnknown; } } // namespace
diff --git a/chrome/browser/android/web_contents_factory.cc b/chrome/browser/android/web_contents_factory.cc index d8f36e6..c30008b 100644 --- a/chrome/browser/android/web_contents_factory.cc +++ b/chrome/browser/android/web_contents_factory.cc
@@ -17,7 +17,8 @@ JNIEnv* env, const JavaParamRef<jobject>& j_profile, jboolean initially_hidden, - jboolean initialize_renderer) { + jboolean initialize_renderer, + const JavaParamRef<jthrowable>& j_creator_location) { Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); content::WebContents::CreateParams params(profile); params.initially_hidden = static_cast<bool>(initially_hidden); @@ -26,6 +27,7 @@ ? content::WebContents::CreateParams:: kInitializeAndWarmupRendererProcess : content::WebContents::CreateParams::kOkayToHaveRendererProcess; + params.java_creator_location = j_creator_location; // Ownership is passed into java, and then to TabAndroid::InitWebContents. return content::WebContents::Create(params).release()->GetJavaWebContents();
diff --git a/chrome/browser/android/webapk/OWNERS b/chrome/browser/android/webapk/OWNERS index dae53b3..3f3a939 100644 --- a/chrome/browser/android/webapk/OWNERS +++ b/chrome/browser/android/webapk/OWNERS
@@ -1,4 +1 @@ -file://components/webapk/OWNERS - -# Additional owners: -dominickn@chromium.org +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/browser/android/webapps/OWNERS b/chrome/browser/android/webapps/OWNERS index 9094dac..3f3a939 100644 --- a/chrome/browser/android/webapps/OWNERS +++ b/chrome/browser/android/webapps/OWNERS
@@ -1,3 +1 @@ -dominickn@chromium.org -eirage@chromium.org -hartmanng@chromium.org +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc index 96ecc49..6919bc61 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc +++ b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "extensions/grit/extensions_browser_resources.h" #include "services/data_decoder/public/cpp/data_decoder.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/codec/png_codec.h" @@ -68,6 +69,38 @@ host_.DiscardDecodeRequest(); } +AppIconDecoder::FakeDecodeRequestForTesting::FakeDecodeRequestForTesting( + ui::ResourceScaleFactor scale_factor, + AppIconDecoder& host, + gfx::ImageSkia& image_skia, + std::set<ui::ResourceScaleFactor>& incomplete_scale_factors) + : scale_factor_(scale_factor), + host_(host), + image_skia_(image_skia), + incomplete_scale_factors_(incomplete_scale_factors) {} + +void AppIconDecoder::FakeDecodeRequestForTesting::Start( + std::vector<uint8_t> icon_data) { + CompressedDataToSkBitmap( + std::move(icon_data), + base::BindOnce( + &AppIconDecoder::FakeDecodeRequestForTesting::DecodeRequestReply, + weak_ptr_factory_.GetWeakPtr())); +} + +AppIconDecoder::FakeDecodeRequestForTesting::~FakeDecodeRequestForTesting() = + default; + +void AppIconDecoder::FakeDecodeRequestForTesting::DecodeRequestReply( + SkBitmap bitmap) { + if (!bitmap.isNull()) { + host_.UpdateImageSkia(scale_factor_, bitmap, image_skia_, + incomplete_scale_factors_); + } else { + host_.DiscardDecodeRequest(); + } +} + AppIconDecoder::AppIconDecoder( const base::FilePath& base_path, const std::string& app_id, @@ -148,33 +181,35 @@ if (!is_adaptive_icon_) { // If we can't generate the adaptive icon for all scales, decode the // foreground images only to fill in `image_skia_`. - DecodeImage(scale_factor, iv->foreground_icon_png_data, image_skia_, - incomplete_scale_factors_); + DecodeImage(scale_factor, std::move(iv->foreground_icon_png_data), + image_skia_, incomplete_scale_factors_); continue; } // Decode for the foreground and background image. - DecodeImage(scale_factor, iv->foreground_icon_png_data, + DecodeImage(scale_factor, std::move(iv->foreground_icon_png_data), foreground_image_skia_, foreground_incomplete_scale_factors_); - DecodeImage(scale_factor, iv->background_icon_png_data, + DecodeImage(scale_factor, std::move(iv->background_icon_png_data), background_image_skia_, background_incomplete_scale_factors_); continue; } is_maskable_icon_ = iv->is_maskable_icon; - DecodeImage(scale_factor, iv->compressed, image_skia_, + DecodeImage(scale_factor, std::move(iv->compressed), image_skia_, incomplete_scale_factors_); } } void AppIconDecoder::DecodeImage( ui::ResourceScaleFactor scale_factor, - const std::vector<uint8_t>& icon_data, + std::vector<uint8_t> icon_data, gfx::ImageSkia& image_skia, std::set<ui::ResourceScaleFactor>& incomplete_scale_factors) { if (g_decode_request_for_testing) { - DecodeRequestForTesting(scale_factor, icon_data, image_skia, - incomplete_scale_factors); + fake_decode_requests_for_testing_.emplace_back( + std::make_unique<FakeDecodeRequestForTesting>( + scale_factor, *this, image_skia, incomplete_scale_factors)); + fake_decode_requests_for_testing_.back().get()->Start(std::move(icon_data)); return; } @@ -237,22 +272,6 @@ std::move(callback_).Run(this, std::move(iv)); } -void AppIconDecoder::DecodeRequestForTesting( - ui::ResourceScaleFactor scale_factor, - const std::vector<uint8_t>& icon_data, - gfx::ImageSkia& image_skia, - std::set<ui::ResourceScaleFactor>& incomplete_scale_factors) { - SkBitmap bitmap; - if (!icon_data.empty() && - gfx::PNGCodec::Decode( - reinterpret_cast<const unsigned char*>(&icon_data.front()), - icon_data.size(), &bitmap)) { - UpdateImageSkia(scale_factor, bitmap, image_skia, incomplete_scale_factors); - } else { - DiscardDecodeRequest(); - } -} - ScopedDecodeRequestForTesting::ScopedDecodeRequestForTesting() { g_decode_request_for_testing = true; }
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h index f2b3239..a0baf03f 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h +++ b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h
@@ -85,13 +85,39 @@ std::set<ui::ResourceScaleFactor>& incomplete_scale_factors_; }; + class FakeDecodeRequestForTesting { + public: + FakeDecodeRequestForTesting( + ui::ResourceScaleFactor scale_factor, + AppIconDecoder& host, + gfx::ImageSkia& image_skia, + std::set<ui::ResourceScaleFactor>& incomplete_scale_factors); + + FakeDecodeRequestForTesting(const FakeDecodeRequestForTesting&) = delete; + FakeDecodeRequestForTesting& operator=(const FakeDecodeRequestForTesting&) = + delete; + + ~FakeDecodeRequestForTesting(); + + void Start(std::vector<uint8_t> icon_data); + + private: + void DecodeRequestReply(SkBitmap bitmap); + + ui::ResourceScaleFactor scale_factor_; + AppIconDecoder& host_; + gfx::ImageSkia& image_skia_; + std::set<ui::ResourceScaleFactor>& incomplete_scale_factors_; + base::WeakPtrFactory<FakeDecodeRequestForTesting> weak_ptr_factory_{this}; + }; + bool SetScaleFactors( const std::map<ui::ResourceScaleFactor, IconValuePtr>& icon_datas); void OnIconRead(std::map<ui::ResourceScaleFactor, IconValuePtr> icon_datas); void DecodeImage(ui::ResourceScaleFactor scale_factor, - const std::vector<uint8_t>& icon_data, + std::vector<uint8_t> icon_data, gfx::ImageSkia& image_skia, std::set<ui::ResourceScaleFactor>& incomplete_scale_factors); @@ -105,12 +131,6 @@ void CompleteWithImageSkia(const gfx::ImageSkia& image_skia); - void DecodeRequestForTesting( - ui::ResourceScaleFactor scale_factor, - const std::vector<uint8_t>& icon_data, - gfx::ImageSkia& image_skia, - std::set<ui::ResourceScaleFactor>& incomplete_scale_factors); - const base::FilePath base_path_; const std::string app_id_; int32_t size_in_dip_; @@ -130,6 +150,9 @@ // Contains pending image decode requests. std::vector<std::unique_ptr<DecodeRequest>> decode_requests_; + std::vector<std::unique_ptr<FakeDecodeRequestForTesting>> + fake_decode_requests_for_testing_; + base::WeakPtrFactory<AppIconDecoder> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm b/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm index e6f7091d..1c129ff 100644 --- a/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm +++ b/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm
@@ -8,6 +8,8 @@ #import <SafariServices/SafariServices.h> #include "base/feature_list.h" +#include "base/functional/callback_helpers.h" +#include "base/mac/launch_application.h" #include "base/no_destructor.h" #include "base/strings/sys_string_conversions.h" #include "chrome/browser/browser_features.h" @@ -84,22 +86,9 @@ } void LaunchMacApp(const GURL& url, const std::string& launch_name) { - if (@available(macOS 10.15, *)) { - [[NSWorkspace sharedWorkspace] - openURLs:@[ net::NSURLWithGURL(url) ] - withApplicationAtURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString( - launch_name)] - configuration:[NSWorkspaceOpenConfiguration configuration] - completionHandler:nil]; - } else { - [[NSWorkspace sharedWorkspace] - openURLs:@[ net::NSURLWithGURL(url) ] - withApplicationAtURL:[NSURL fileURLWithPath:base::SysUTF8ToNSString( - launch_name)] - options:0 - configuration:@{} - error:nil]; - } + base::mac::LaunchApplication(base::FilePath(launch_name), + /*command_line_args=*/{}, {url.spec()}, + /*options=*/{}, base::DoNothing()); } void OverrideMacAppForUrlForTesting(bool fake, const std::string& app_path) {
diff --git a/chrome/browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm b/chrome/browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm index f2d0280..b23ebc61 100644 --- a/chrome/browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm +++ b/chrome/browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm
@@ -13,7 +13,7 @@ #include "base/auto_reset.h" #include "base/functional/bind.h" #include "base/mac/foundation_util.h" -#import "base/mac/launch_services_util.h" +#import "base/mac/launch_application.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/raw_ptr.h" @@ -370,8 +370,8 @@ base::test::TestFuture<base::expected<NSRunningApplication*, NSError*>> open_result; - base::mac::OpenApplication(shim_path_, shim_cmdline, /*url_specs=*/{}, - /*options=*/{}, open_result.GetCallback()); + base::mac::LaunchApplication(shim_path_, shim_cmdline, /*url_specs=*/{}, + /*options=*/{}, open_result.GetCallback()); ASSERT_TRUE(open_result.Get<0>().has_value()); NSRunningApplication* shim_app = open_result.Get<0>().value(); ASSERT_TRUE(shim_app); @@ -447,8 +447,8 @@ base::test::TestFuture<base::expected<NSRunningApplication*, NSError*>> open_result; - base::mac::OpenApplication(shim_path_, shim_cmdline, /*url_specs=*/{}, - /*options=*/{}, open_result.GetCallback()); + base::mac::LaunchApplication(shim_path_, shim_cmdline, /*url_specs=*/{}, + /*options=*/{}, open_result.GetCallback()); ASSERT_TRUE(open_result.Get<0>().has_value()); NSRunningApplication* shim_app = open_result.Get<0>().value(); ASSERT_TRUE(shim_app); @@ -673,8 +673,8 @@ base::test::TestFuture<base::expected<NSRunningApplication*, NSError*>> open_result; - base::mac::OpenApplication(shim_path, shim_cmdline, /*url_specs=*/{}, - /*options=*/{}, open_result.GetCallback()); + base::mac::LaunchApplication(shim_path, shim_cmdline, /*url_specs=*/{}, + /*options=*/{}, open_result.GetCallback()); ASSERT_TRUE(open_result.Get<0>().has_value()); NSRunningApplication* shim_app = open_result.Get<0>().value(); ASSERT_TRUE(shim_app);
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index aac7dfb..13c96d3e 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -266,6 +266,10 @@ "arc/bluetooth/arc_bluetooth_bridge.h", "arc/bluetooth/arc_bluetooth_task_queue.cc", "arc/bluetooth/arc_bluetooth_task_queue.h", + "arc/bluetooth/arc_bluez_bridge.cc", + "arc/bluetooth/arc_bluez_bridge.h", + "arc/bluetooth/arc_floss_bridge.cc", + "arc/bluetooth/arc_floss_bridge.h", "arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc", "arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h", "arc/enterprise/arc_data_snapshotd_delegate.cc", @@ -580,6 +584,8 @@ "arc/user_session/arc_user_session_service.h", "arc/video/gpu_arc_video_service_host.cc", "arc/video/gpu_arc_video_service_host.h", + "arc/vmm/arc_vmm_manager.cc", + "arc/vmm/arc_vmm_manager.h", "arc/wallpaper/arc_wallpaper_service.cc", "arc/wallpaper/arc_wallpaper_service.h", "arc/window_predictor/arc_predictor_app_launch_handler.cc", @@ -4225,10 +4231,10 @@ "app_list/test/test_app_list_controller_delegate.h", "app_mode/fake_cws.cc", "app_mode/fake_cws.h", + "app_mode/fake_kiosk_app_launcher.cc", + "app_mode/fake_kiosk_app_launcher.h", "app_mode/test_kiosk_extension_builder.cc", "app_mode/test_kiosk_extension_builder.h", - "app_mode/web_app/mock_web_kiosk_app_launcher.cc", - "app_mode/web_app/mock_web_kiosk_app_launcher.h", "arc/extensions/fake_arc_support.cc", "arc/extensions/fake_arc_support.h", "arc/tracing/arc_app_performance_tracing_test_helper.cc", @@ -4447,8 +4453,8 @@ "policy/core/fake_device_cloud_policy_manager.h", "policy/core/user_policy_test_helper.cc", "policy/core/user_policy_test_helper.h", - "policy/enrollment/psm/fake_rlwe_client.cc", - "policy/enrollment/psm/fake_rlwe_client.h", + "policy/enrollment/psm/rlwe_test_support.cc", + "policy/enrollment/psm/rlwe_test_support.h", "policy/external_data/cloud_external_data_manager_base_test_util.cc", "policy/external_data/cloud_external_data_manager_base_test_util.h", "policy/handlers/fake_device_name_policy_handler.cc", @@ -4621,6 +4627,7 @@ "//extensions/browser", "//extensions/common:common_constants", "//skia", + "//third_party/private_membership", "//third_party/re2", "//ui/base", "//ui/chromeos/resources", @@ -4631,6 +4638,12 @@ "//ui/views/controls/webview", "//ui/wm", ] + + data = [ + # TODO(crbug/1393862): Script should create binarypb from textpb. + # Required for policy/enrollment/psm/rlwe_test_support.cc + "//third_party/private_membership/src/internal/testing/regression_test_data/test_data.binarypb", + ] } source_set("unit_tests") { @@ -4814,6 +4827,7 @@ "arc/arc_util_unittest.cc", "arc/bluetooth/arc_bluetooth_bridge_unittest.cc", "arc/bluetooth/arc_bluetooth_task_queue_unittest.cc", + "arc/bluetooth/arc_floss_bridge_unittest.cc", "arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc", "arc/enterprise/arc_data_snapshotd_delegate_unittest.cc", "arc/enterprise/arc_enterprise_reporting_service_unittest.cc", @@ -5353,6 +5367,7 @@ "policy/enrollment/enrollment_config_unittest.cc", "policy/enrollment/psm/construct_rlwe_id_unittest.cc", "policy/enrollment/psm/rlwe_dmserver_client_impl_unittest.cc", + "policy/enrollment/psm/rlwe_test_support_unittest.cc", "policy/enrollment/tpm_enrollment_key_signing_service_unittest.cc", "policy/external_data/cloud_external_data_manager_base_unittest.cc", "policy/external_data/cloud_external_data_policy_observer_unittest.cc",
diff --git a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc index fc30240..395d356 100644 --- a/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc +++ b/chrome/browser/ash/accessibility/accessibility_manager_browsertest.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_test_util.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" @@ -39,6 +38,7 @@ #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/session_manager/core/session_manager.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/user_manager/user_names.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc index c6eb3d3..57f0dfb 100644 --- a/chrome/browser/ash/accessibility/dictation_browsertest.cc +++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -1026,6 +1026,12 @@ ::testing::Values(TestConfig(speech::SpeechRecognitionType::kNetwork, EditableType::kInput))); +INSTANTIATE_TEST_SUITE_P( + NetworkContentEditable, + DictationJaTest, + ::testing::Values(TestConfig(speech::SpeechRecognitionType::kNetwork, + EditableType::kContentEditable))); + IN_PROC_BROWSER_TEST_P(DictationJaTest, NoSmartSpacingOrCapitalization) { ToggleDictationWithKeystroke(); WaitForRecognitionStarted();
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc index d1a956d..4de63da 100644 --- a/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc +++ b/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc
@@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> +#include <string> +#include <utility> +#include <vector> + #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/test/bind.h" @@ -10,19 +15,21 @@ #include "chrome/browser/ash/account_manager/account_manager_policy_controller_factory.h" #include "chrome/browser/ash/account_manager/child_account_type_changed_user_data.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" +#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" +#include "components/account_id/account_id.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/pref_names.h" #include "components/signin/public/base/consent_level.h" +#include "components/user_manager/fake_user_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" @@ -52,7 +59,10 @@ // Prep private fields. ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); TestingProfile::Builder profile_builder; - profile_builder.SetPath(temp_dir_.GetPath().AppendASCII("TestProfile")); + profile_builder.SetPath(temp_dir_.GetPath().AppendASCII( + BrowserContextHelper::GetUserBrowserContextDirName( + user_manager::FakeUserManager::GetFakeUsernameHash( + AccountId::FromUserEmail(kFakePrimaryUsername))))); profile_builder.SetProfileName(kFakePrimaryUsername); profile_ = IdentityTestEnvironmentProfileAdaptor:: CreateProfileForIdentityTestEnvironment(profile_builder); @@ -73,9 +83,8 @@ auto user_manager = std::make_unique<FakeChromeUserManager>(); primary_account_id_ = AccountId::FromUserEmailGaiaId( primary_account_info.email, primary_account_info.gaia); - const user_manager::User* user = user_manager->AddUser(primary_account_id_); + user_manager->AddUser(primary_account_id_); user_manager->LoginUser(primary_account_id_); - ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, profile()); scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( std::move(user_manager)); @@ -179,20 +188,16 @@ base::RunLoop().RunUntilIdle(); // Secondary Accounts must be removed. + const std::string& gaia_id = BrowserContextHelper::Get() + ->GetUserByBrowserContext(profile()) + ->GetAccountId() + .GetGaiaId(); accounts = GetAccountManagerAccounts(); ASSERT_EQ(accounts.size(), 1UL); - EXPECT_EQ(ProfileHelper::Get() - ->GetUserByProfile(profile()) - ->GetAccountId() - .GetGaiaId(), - identity_manager() - ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) - .gaia); - EXPECT_EQ(ProfileHelper::Get() - ->GetUserByProfile(profile()) - ->GetAccountId() - .GetGaiaId(), - accounts[0].key.id()); + EXPECT_EQ(gaia_id, accounts[0].key.id()); + EXPECT_EQ(gaia_id, identity_manager() + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) + .gaia); } IN_PROC_BROWSER_TEST_F( @@ -211,21 +216,16 @@ base::RunLoop().RunUntilIdle(); // Secondary Accounts must be removed. + const std::string& gaia_id = BrowserContextHelper::Get() + ->GetUserByBrowserContext(profile()) + ->GetAccountId() + .GetGaiaId(); accounts = GetAccountManagerAccounts(); ASSERT_EQ(accounts.size(), 1UL); - - EXPECT_EQ(ProfileHelper::Get() - ->GetUserByProfile(profile()) - ->GetAccountId() - .GetGaiaId(), - identity_manager() - ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) - .gaia); - EXPECT_EQ(ProfileHelper::Get() - ->GetUserByProfile(profile()) - ->GetAccountId() - .GetGaiaId(), - accounts[0].key.id()); + EXPECT_EQ(gaia_id, accounts[0].key.id()); + EXPECT_EQ(gaia_id, identity_manager() + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin) + .gaia); } } // namespace ash
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc index 7323203..aa74e6b2b 100644 --- a/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc +++ b/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc
@@ -6,11 +6,11 @@ #include "base/no_destructor.h" #include "chrome/browser/ash/account_manager/account_manager_policy_controller.h" -#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/profiles/profile.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" +#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/user_manager/user.h" @@ -55,8 +55,8 @@ if (!account_manager_facade) return nullptr; - user_manager::User* const user = - ProfileHelper::Get()->GetUserByProfile(profile); + const user_manager::User* const user = + BrowserContextHelper::Get()->GetUserByBrowserContext(profile); if (!user) return nullptr;
diff --git a/chrome/browser/ash/account_manager/account_manager_util.cc b/chrome/browser/ash/account_manager/account_manager_util.cc index ab62b20..df94662 100644 --- a/chrome/browser/ash/account_manager/account_manager_util.cc +++ b/chrome/browser/ash/account_manager/account_manager_util.cc
@@ -6,15 +6,17 @@ #include <utility> +#include "base/functional/bind.h" +#include "base/functional/callback.h" #include "chrome/browser/ash/account_manager/account_manager_ui_impl.h" #include "chrome/browser/ash/net/delay_network_call.h" -#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profiles_state.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" +#include "chromeos/ash/components/browser_context_helper/browser_context_types.h" #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_mojo_service.h" #include "components/account_manager_core/chromeos/account_manager_ui.h" @@ -23,12 +25,13 @@ namespace ash { -bool IsAccountManagerAvailable(const Profile* const profile) { +bool IsAccountManagerAvailable(Profile* profile) { // Signin Profile does not have any accounts associated with it, // LockScreenAppProfile and LockScreenProfile do not link to the user's // cryptohome. - if (!ProfileHelper::IsUserProfile(profile)) + if (!IsUserBrowserContext(profile)) { return false; + } // Account Manager is unavailable on Guest (Incognito) Sessions. if (profile->IsGuestSession() || profile->IsOffTheRecord())
diff --git a/chrome/browser/ash/account_manager/account_manager_util.h b/chrome/browser/ash/account_manager/account_manager_util.h index 011e110b..584fad0 100644 --- a/chrome/browser/ash/account_manager/account_manager_util.h +++ b/chrome/browser/ash/account_manager/account_manager_util.h
@@ -6,13 +6,13 @@ #define CHROME_BROWSER_ASH_ACCOUNT_MANAGER_ACCOUNT_MANAGER_UTIL_H_ #include "base/files/file_path.h" -#include "base/functional/bind.h" +#include "base/functional/callback_forward.h" class Profile; namespace ash { -bool IsAccountManagerAvailable(const Profile* const profile); +bool IsAccountManagerAvailable(Profile* profile); // Initializes account manager if it has not been initialized yet. Safe to call // multiple times. |cryptohome_root_dir| is root of user's home partition (same
diff --git a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc index 4695edce..013682ab 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
@@ -1196,20 +1196,19 @@ } // Update the icon key to fetch the new icon and avoid icon catch, - // TODO(crbug.com/1253250): Remove apps::mojom related code. apps_util::IncrementingIconKeyFactory icon_key_factory; std::vector<apps::AppPtr> apps; for (const auto& app_id : app_ids) { auto app = std::make_unique<apps::App>(apps::AppType::kArc, app_id); app->icon_key = std::move(*icon_key_factory.CreateIconKey(apps::IconEffects::kNone)); + app->icon_key->raw_icon_updated = true; apps.push_back(std::move(app)); } - apps::AppServiceProxyFactory::GetForProfile(profile()) - ->AppRegistryCache() - .OnApps(std::move(apps), apps::AppType::kArc, - false /* should_notify_initialized */); + apps::AppServiceProxyFactory::GetForProfile(profile())->OnApps( + std::move(apps), apps::AppType::kArc, + false /* should_notify_initialized */); } // Set FakeArcAppIconFactory to use FakeArcAppIcon for Arc app icon loading to
diff --git a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc index eea68a4b..8be57e9 100644 --- a/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc +++ b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" #include "ash/public/cpp/keyboard_shortcut_viewer.h" #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h" @@ -44,23 +45,25 @@ const std::vector<InternalApp>& GetInternalAppListImpl(bool get_all, const Profile* profile) { DCHECK(get_all || profile); - static const base::NoDestructor<std::vector<InternalApp>> - internal_app_list_static( - {{ash::kInternalAppIdKeyboardShortcutViewer, - IDS_INTERNAL_APP_KEYBOARD_SHORTCUT_VIEWER, - IDR_SHORTCUT_VIEWER_LOGO_192, - /*recommendable=*/false, - /*searchable=*/true, - /*show_in_launcher=*/false, - apps::BuiltInAppName::kKeyboardShortcutViewer, - IDS_LAUNCHER_SEARCHABLE_KEYBOARD_SHORTCUT_VIEWER}, + static base::NoDestructor<std::vector<InternalApp>> internal_app_list_static( + {{ash::kInternalAppIdContinueReading, IDS_INTERNAL_APP_CONTINUOUS_READING, + IDR_PRODUCT_LOGO_256, + /*recommendable=*/true, + /*searchable=*/false, + /*show_in_launcher=*/false, apps::BuiltInAppName::kContinueReading, + /*searchable_string_resource_id=*/0}}); - {ash::kInternalAppIdContinueReading, - IDS_INTERNAL_APP_CONTINUOUS_READING, IDR_PRODUCT_LOGO_256, - /*recommendable=*/true, - /*searchable=*/false, - /*show_in_launcher=*/false, apps::BuiltInAppName::kContinueReading, - /*searchable_string_resource_id=*/0}}); + if (!ash::features::ShouldOnlyShowNewShortcutApp()) { + internal_app_list_static->push_back( + {ash::kInternalAppIdKeyboardShortcutViewer, + IDS_INTERNAL_APP_KEYBOARD_SHORTCUT_VIEWER, + IDR_SHORTCUT_VIEWER_LOGO_192, + /*recommendable=*/false, + /*searchable=*/true, + /*show_in_launcher=*/false, + apps::BuiltInAppName::kKeyboardShortcutViewer, + IDS_LAUNCHER_SEARCHABLE_KEYBOARD_SHORTCUT_VIEWER}); + } return *internal_app_list_static; }
diff --git a/chrome/browser/ash/app_list/search/keyboard_shortcut_result.cc b/chrome/browser/ash/app_list/search/keyboard_shortcut_result.cc index 09618ec7..7235c49d 100644 --- a/chrome/browser/ash/app_list/search/keyboard_shortcut_result.cc +++ b/chrome/browser/ash/app_list/search/keyboard_shortcut_result.cc
@@ -7,6 +7,7 @@ #include <string> #include "ash/accelerators/keyboard_code_util.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h" #include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h" @@ -18,6 +19,7 @@ #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/app_list/search/common/icon_constants.h" #include "chrome/browser/ash/app_list/search/common/search_result_util.h" +#include "chrome/browser/ui/chrome_pages.h" #include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/string_matching/tokenized_string.h" #include "chromeos/ash/components/string_matching/tokenized_string_match.h" @@ -264,6 +266,10 @@ KeyboardShortcutResult::~KeyboardShortcutResult() = default; void KeyboardShortcutResult::Open(int event_flags) { + if (ash::features::ShouldOnlyShowNewShortcutApp()) { + chrome::ShowShortcutCustomizationApp(profile_); + return; + } apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); proxy->Launch(ash::kInternalAppIdKeyboardShortcutViewer, event_flags,
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc index 954ac4b..441b354 100644 --- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc +++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc
@@ -13,10 +13,15 @@ #include "chrome/browser/ash/app_list/search/system_info/cpu_data.h" #include "chrome/browser/ash/app_list/search/system_info/cpu_usage_data.h" #include "chrome/browser/ash/app_list/search/system_info/system_info_util.h" +#include "chrome/common/channel_info.h" #include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h" #include "chromeos/ash/services/cros_healthd/public/cpp/service_connection.h" #include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h" #include "chromeos/ash/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h" +#include "components/strings/grit/components_strings.h" +#include "components/version_info/version_info.h" +#include "components/version_info/version_string.h" +#include "ui/base/l10n/l10n_util.h" namespace app_list { namespace { @@ -79,6 +84,15 @@ break; } } + + std::vector<std::u16string> version_keywords = {u"version", u"my device", + u"about"}; + for (std::u16string keyword : version_keywords) { + if (CalculateRelevance(query, keyword) > kRelevanceThreshold) { + UpdateChromeOsVersion(); + break; + } + } } void SystemInfoCardProvider::StopQuery() { @@ -240,4 +254,19 @@ power_supply_properties)); } +void SystemInfoCardProvider::UpdateChromeOsVersion() { + std::string version = version_info::GetVersionStringWithModifier(""); + std::string official = l10n_util::GetStringUTF8( + version_info::IsOfficialBuild() ? IDS_VERSION_UI_OFFICIAL + : IDS_VERSION_UI_UNOFFICIAL); + std::string processorVariation = l10n_util::GetStringUTF8( + sizeof(void*) == 8 ? IDS_VERSION_UI_64BIT : IDS_VERSION_UI_32BIT); + + // TODO(b/263994165): Replace this with the correct translation string. + chromeOS_version_ = + std::string("Version " + version + " (" + official + ") " + + chrome::GetChannelName(chrome::WithExtendedStable(true)) + + " " + processorVariation); +} + } // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h index cafd495..49adb35 100644 --- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h +++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h
@@ -65,9 +65,12 @@ void PowerChanged(const power_manager::PowerSupplyProperties& power_supply_properties) override; + void UpdateChromeOsVersion(); + Profile* const profile_; mojo::Remote<ash::cros_healthd::mojom::CrosHealthdProbeService> probe_service_; + std::string chromeOS_version_{""}; CpuUsageData previous_cpu_usage_data_{CpuUsageData()}; ash::cros_healthd::mojom::MemoryInfo* memory_info_{nullptr}; std::unique_ptr<CpuData> cpu_usage_{nullptr};
diff --git a/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.cc new file mode 100644 index 0000000..ac529b4 --- /dev/null +++ b/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.cc
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h" +#include "chrome/browser/ash/app_mode/kiosk_app_launcher.h" + +namespace ash { + +FakeKioskAppLauncher::FakeKioskAppLauncher() = default; +FakeKioskAppLauncher::~FakeKioskAppLauncher() = default; + +void FakeKioskAppLauncher::AddObserver(KioskAppLauncher::Observer* observer) { + observers_.AddObserver(observer); +} + +void FakeKioskAppLauncher::RemoveObserver( + KioskAppLauncher::Observer* observer) { + observers_.RemoveObserver(observer); +} + +void FakeKioskAppLauncher::Initialize() { + ++initialize_called_; +} + +void FakeKioskAppLauncher::ContinueWithNetworkReady() { + ++continue_with_network_ready_called_; +} + +void FakeKioskAppLauncher::LaunchApp() { + ++launch_app_called_; +} + +void FakeKioskAppLauncher::RestartLauncher() {} + +} // namespace ash
diff --git a/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h new file mode 100644 index 0000000..88ca48e --- /dev/null +++ b/chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h
@@ -0,0 +1,49 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef CHROME_BROWSER_ASH_APP_MODE_FAKE_KIOSK_APP_LAUNCHER_H_ +#define CHROME_BROWSER_ASH_APP_MODE_FAKE_KIOSK_APP_LAUNCHER_H_ + +#include "chrome/browser/ash/app_mode/kiosk_app_launcher.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace ash { + +class FakeKioskAppLauncher : public KioskAppLauncher { + public: + FakeKioskAppLauncher(); + ~FakeKioskAppLauncher() override; + + // `KioskAppLauncher`: + void AddObserver(KioskAppLauncher::Observer* observer) override; + void RemoveObserver(KioskAppLauncher::Observer* observer) override; + void Initialize() override; + void ContinueWithNetworkReady() override; + void LaunchApp() override; + void RestartLauncher() override; + + void ResetAppLaunched(); + + bool IsInitialized() const { return initialize_called_ > 0; } + bool HasAppLaunched() const { return launch_app_called_ > 0; } + bool HasContinueWithNetworkReadyBeenCalled() const { + return continue_with_network_ready_called_ > 0; + } + int initialize_called() { return initialize_called_; } + int launch_app_called() { return launch_app_called_; } + int continue_with_network_ready_called() { + return continue_with_network_ready_called_; + } + + KioskAppLauncher::ObserverList& observers() { return observers_; } + + private: + KioskAppLauncher::ObserverList observers_; + int initialize_called_ = 0; + int launch_app_called_ = 0; + int continue_with_network_ready_called_ = 0; +}; + +} // namespace ash + +#endif // CHROME_BROWSER_ASH_APP_MODE_FAKE_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc deleted file mode 100644 index fce601b..0000000 --- a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.cc +++ /dev/null
@@ -1,34 +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/app_mode/web_app/mock_web_kiosk_app_launcher.h" - -namespace ash { - -MockWebKioskAppLauncher::MockWebKioskAppLauncher() = default; -MockWebKioskAppLauncher::~MockWebKioskAppLauncher() = default; - -void MockWebKioskAppLauncher::AddObserver( - KioskAppLauncher::Observer* observer) { - observers_.AddObserver(observer); -} - -void MockWebKioskAppLauncher::RemoveObserver( - KioskAppLauncher::Observer* observer) { - observers_.RemoveObserver(observer); -} - -void MockWebKioskAppLauncher::CallOnAppInstalling() { - observers_.NotifyAppInstalling(); -} - -void MockWebKioskAppLauncher::CallOnAppPrepared() { - observers_.NotifyAppPrepared(); -} - -void MockWebKioskAppLauncher::CallOnAppLaunched() { - observers_.NotifyAppLaunched(); -} - -} // namespace ash
diff --git a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h deleted file mode 100644 index 59ae4d4..0000000 --- a/chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h +++ /dev/null
@@ -1,36 +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_ASH_APP_MODE_WEB_APP_MOCK_WEB_KIOSK_APP_LAUNCHER_H_ -#define CHROME_BROWSER_ASH_APP_MODE_WEB_APP_MOCK_WEB_KIOSK_APP_LAUNCHER_H_ - -#include "chrome/browser/ash/app_mode/kiosk_app_launcher.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace ash { - -class MockWebKioskAppLauncher : public KioskAppLauncher { - public: - MockWebKioskAppLauncher(); - ~MockWebKioskAppLauncher() override; - - // `KioskAppLauncher`: - void AddObserver(KioskAppLauncher::Observer* observer) override; - void RemoveObserver(KioskAppLauncher::Observer* observer) override; - MOCK_METHOD0(Initialize, void()); - MOCK_METHOD0(ContinueWithNetworkReady, void()); - MOCK_METHOD0(LaunchApp, void()); - MOCK_METHOD0(RestartLauncher, void()); - - void CallOnAppInstalling(); - void CallOnAppPrepared(); - void CallOnAppLaunched(); - - private: - KioskAppLauncher::ObserverList observers_; -}; - -} // namespace ash - -#endif // CHROME_BROWSER_ASH_APP_MODE_WEB_APP_MOCK_WEB_KIOSK_APP_LAUNCHER_H_
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc index 8ccdcbc4..f0bc71e 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -32,6 +32,8 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h" +#include "chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h" @@ -161,8 +163,6 @@ // Copied from Android at system/bt/stack/btm/btm_ble_int.h // https://goo.gl/k7PM6u constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; -// Bluetooth SDP Service Class ID List Attribute identifier -constexpr uint16_t kServiceClassIDListAttributeID = 0x0001; // Timeout for Bluetooth Discovery (scan) // 120 seconds is used here as the upper bound of the time need to do device // discovery once, 20 seconds for inquiry scan and 100 seconds for page scan @@ -191,13 +191,6 @@ // Client name for logging in BLE scanning. constexpr char kScanClientName[] = "ARC"; -using GattReadCallback = - base::OnceCallback<void(arc::mojom::BluetoothGattValuePtr)>; -using CreateSdpRecordCallback = - base::OnceCallback<void(arc::mojom::BluetoothCreateSdpRecordResultPtr)>; -using RemoveSdpRecordCallback = - base::OnceCallback<void(arc::mojom::BluetoothStatus)>; - device::BluetoothGattCharacteristic::Permissions ConvertToBlueZGattPermissions( int32_t permissions) { device::BluetoothGattCharacteristic::Permissions result = @@ -303,7 +296,7 @@ // Common callback (success and error) for ReadGattCharacteristic and // ReadGattDescriptor. void OnGattRead( - GattReadCallback callback, + arc::ArcBluetoothBridge::GattReadCallback callback, absl::optional<device::BluetoothGattService::GattErrorCode> error_code, const std::vector<uint8_t>& result) { arc::mojom::BluetoothGattValuePtr gattValue = @@ -362,48 +355,6 @@ return arc::mojom::BluetoothProperty::NewDiscoveryTimeout(timeout); } -void OnCreateServiceRecordDone(CreateSdpRecordCallback callback, - uint32_t service_handle) { - arc::mojom::BluetoothCreateSdpRecordResultPtr result = - arc::mojom::BluetoothCreateSdpRecordResult::New(); - result->status = arc::mojom::BluetoothStatus::SUCCESS; - result->service_handle = service_handle; - - std::move(callback).Run(std::move(result)); -} - -void OnCreateServiceRecordError( - CreateSdpRecordCallback callback, - bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { - arc::mojom::BluetoothCreateSdpRecordResultPtr result = - arc::mojom::BluetoothCreateSdpRecordResult::New(); - if (error_code == - bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) { - result->status = arc::mojom::BluetoothStatus::NOT_READY; - } else { - result->status = arc::mojom::BluetoothStatus::FAIL; - } - - std::move(callback).Run(std::move(result)); -} - -void OnRemoveServiceRecordDone(RemoveSdpRecordCallback callback) { - std::move(callback).Run(arc::mojom::BluetoothStatus::SUCCESS); -} - -void OnRemoveServiceRecordError( - RemoveSdpRecordCallback callback, - bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { - arc::mojom::BluetoothStatus status; - if (error_code == - bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) - status = arc::mojom::BluetoothStatus::NOT_READY; - else - status = arc::mojom::BluetoothStatus::FAIL; - - std::move(callback).Run(status); -} - const device::BluetoothLocalGattDescriptor* FindCCCD( const device::BluetoothLocalGattCharacteristic* characteristic) { for (const auto& descriptor : @@ -434,22 +385,41 @@ namespace { // Singleton factory for ArcAccessibilityHelperBridge. -class ArcBluetoothBridgeFactory +class ArcBluezBridgeFactory : public internal::ArcBrowserContextKeyedServiceFactoryBase< - ArcBluetoothBridge, - ArcBluetoothBridgeFactory> { + ArcBluezBridge, + ArcBluezBridgeFactory> { public: // Factory name used by ArcBrowserContextKeyedServiceFactoryBase. - static constexpr const char* kName = "ArcBluetoothBridgeFactory"; + static constexpr const char* kName = "ArcBluezBridgeFactory"; - static ArcBluetoothBridgeFactory* GetInstance() { - return base::Singleton<ArcBluetoothBridgeFactory>::get(); + static ArcBluezBridgeFactory* GetInstance() { + return base::Singleton<ArcBluezBridgeFactory>::get(); } private: - friend base::DefaultSingletonTraits<ArcBluetoothBridgeFactory>; - ArcBluetoothBridgeFactory() = default; - ~ArcBluetoothBridgeFactory() override = default; + friend base::DefaultSingletonTraits<ArcBluezBridgeFactory>; + ArcBluezBridgeFactory() = default; + ~ArcBluezBridgeFactory() override = default; +}; + +// Singleton factory for ArcAccessibilityHelperBridge. +class ArcFlossBridgeFactory + : public internal::ArcBrowserContextKeyedServiceFactoryBase< + ArcFlossBridge, + ArcFlossBridgeFactory> { + public: + // Factory name used by ArcBrowserContextKeyedServiceFactoryBase. + static constexpr const char* kName = "ArcFlossBridgeFactory"; + + static ArcFlossBridgeFactory* GetInstance() { + return base::Singleton<ArcFlossBridgeFactory>::get(); + } + + private: + friend base::DefaultSingletonTraits<ArcFlossBridgeFactory>; + ArcFlossBridgeFactory() = default; + ~ArcFlossBridgeFactory() override = default; }; } // namespace @@ -457,7 +427,11 @@ // static ArcBluetoothBridge* ArcBluetoothBridge::GetForBrowserContext( content::BrowserContext* context) { - return ArcBluetoothBridgeFactory::GetForBrowserContext(context); + if (floss::features::IsFlossEnabled()) { + return ArcFlossBridgeFactory::GetForBrowserContext(context); + } else { + return ArcBluezBridgeFactory::GetForBrowserContext(context); + } } ArcBluetoothBridge::ArcBluetoothBridge(content::BrowserContext* context, @@ -467,11 +441,6 @@ arc_bridge_service_->app()->AddObserver(this); arc_bridge_service_->intent_helper()->AddObserver(this); - if (floss::features::IsFlossEnabled()) { - VLOG(1) << "Disabling ArcBluetoothBridge, Floss not yet supported."; - return; - } - if (BluetoothAdapterFactory::IsBluetoothSupported()) { VLOG(1) << "Registering bluetooth adapter."; BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce( @@ -497,10 +466,7 @@ DCHECK(adapter); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // We can downcast here because we are always running on Chrome OS, and - // so our adapter uses BlueZ. - bluetooth_adapter_ = - static_cast<bluez::BluetoothAdapterBlueZ*>(adapter.get()); + bluetooth_adapter_ = adapter; if (!bluetooth_adapter_->HasObserver(this)) bluetooth_adapter_->AddObserver(this); @@ -512,6 +478,10 @@ arc_bridge_service_->bluetooth()->SetHost(this); } +bluez::BluetoothAdapterBlueZ* ArcBluetoothBridge::GetBluezAdapter() const { + return static_cast<bluez::BluetoothAdapterBlueZ*>(bluetooth_adapter_.get()); +} + void ArcBluetoothBridge::AdapterPoweredChanged(BluetoothAdapter* adapter, bool powered) { AdapterPowerState power_change = @@ -2148,66 +2118,6 @@ std::move(callback).Run(mojom::BluetoothGattStatus::GATT_FAILURE); } -void ArcBluetoothBridge::GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, - const BluetoothUUID& target_uuid) { - BluetoothDevice* device = - bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); - if (!device) { - OnGetServiceRecordsError(std::move(remote_addr), target_uuid, - bluez::BluetoothServiceRecordBlueZ::ErrorCode:: - ERROR_DEVICE_DISCONNECTED); - return; - } - - bluez::BluetoothDeviceBlueZ* device_bluez = - static_cast<bluez::BluetoothDeviceBlueZ*>(device); - - mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); - - device_bluez->GetServiceRecords( - base::BindOnce(&ArcBluetoothBridge::OnGetServiceRecordsDone, - weak_factory_.GetWeakPtr(), std::move(remote_addr), - target_uuid), - base::BindOnce(&ArcBluetoothBridge::OnGetServiceRecordsError, - weak_factory_.GetWeakPtr(), std::move(remote_addr_clone), - target_uuid)); -} - -void ArcBluetoothBridge::CreateSdpRecord( - mojom::BluetoothSdpRecordPtr record_mojo, - CreateSdpRecordCallback callback) { - auto record = record_mojo.To<bluez::BluetoothServiceRecordBlueZ>(); - - // Check if ServiceClassIDList attribute (attribute ID 0x0001) is included - // after type conversion, since it is mandatory for creating a service record. - if (!record.IsAttributePresented(kServiceClassIDListAttributeID)) { - mojom::BluetoothCreateSdpRecordResultPtr result = - mojom::BluetoothCreateSdpRecordResult::New(); - result->status = mojom::BluetoothStatus::FAIL; - std::move(callback).Run(std::move(result)); - return; - } - - auto split_callback = base::SplitOnceCallback(std::move(callback)); - bluetooth_adapter_->CreateServiceRecord( - record, - base::BindOnce(&OnCreateServiceRecordDone, - std::move(split_callback.first)), - base::BindOnce(&OnCreateServiceRecordError, - std::move(split_callback.second))); -} - -void ArcBluetoothBridge::RemoveSdpRecord(uint32_t service_handle, - RemoveSdpRecordCallback callback) { - auto split_callback = base::SplitOnceCallback(std::move(callback)); - bluetooth_adapter_->RemoveServiceRecord( - service_handle, - base::BindOnce(&OnRemoveServiceRecordDone, - std::move(split_callback.first)), - base::BindOnce(&OnRemoveServiceRecordError, - std::move(split_callback.second))); -} - bool ArcBluetoothBridge::GetAdvertisementHandle(int32_t* adv_handle) { for (int i = 0; i < kMaxAdvertisements; i++) { if (advertisements_.find(i) == advertisements_.end()) { @@ -2755,7 +2665,7 @@ if (type == mojom::BluetoothPropertyType::ALL || type == mojom::BluetoothPropertyType::ADAPTER_DISCOVERY_TIMEOUT) { properties.push_back(mojom::BluetoothProperty::NewDiscoveryTimeout( - bluetooth_adapter_->GetDiscoverableTimeout())); + GetBluezAdapter()->GetDiscoverableTimeout())); } if (type == mojom::BluetoothPropertyType::ALL || type == mojom::BluetoothPropertyType::LOCAL_LE_FEATURES) { @@ -2855,53 +2765,6 @@ return advertising_data; } -void ArcBluetoothBridge::OnGetServiceRecordsDone( - mojom::BluetoothAddressPtr remote_addr, - const BluetoothUUID& target_uuid, - const std::vector<bluez::BluetoothServiceRecordBlueZ>& records_bluez) { - auto* sdp_bluetooth_instance = ARC_GET_INSTANCE_FOR_METHOD( - arc_bridge_service_->bluetooth(), OnGetSdpRecords); - if (!sdp_bluetooth_instance) - return; - - std::vector<mojom::BluetoothSdpRecordPtr> records; - for (const auto& r : records_bluez) - records.push_back(mojom::BluetoothSdpRecord::From(r)); - - sdp_bluetooth_instance->OnGetSdpRecords(mojom::BluetoothStatus::SUCCESS, - std::move(remote_addr), target_uuid, - std::move(records)); -} - -void ArcBluetoothBridge::OnGetServiceRecordsError( - mojom::BluetoothAddressPtr remote_addr, - const BluetoothUUID& target_uuid, - bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { - auto* sdp_bluetooth_instance = ARC_GET_INSTANCE_FOR_METHOD( - arc_bridge_service_->bluetooth(), OnGetSdpRecords); - if (!sdp_bluetooth_instance) - return; - - mojom::BluetoothStatus status; - - switch (error_code) { - case bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY: - status = mojom::BluetoothStatus::NOT_READY; - break; - case bluez::BluetoothServiceRecordBlueZ::ErrorCode:: - ERROR_DEVICE_DISCONNECTED: - status = mojom::BluetoothStatus::RMT_DEV_DOWN; - break; - default: - status = mojom::BluetoothStatus::FAIL; - break; - } - - sdp_bluetooth_instance->OnGetSdpRecords( - status, std::move(remote_addr), target_uuid, - std::vector<mojom::BluetoothSdpRecordPtr>()); -} - void ArcBluetoothBridge::SetPrimaryUserBluetoothPowerSetting( bool enabled) const { const user_manager::User* const user =
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h index f1fa608b..2ae078b 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h
@@ -66,6 +66,12 @@ base::OnceCallback<void(mojom::BluetoothGattStatus)>; using AdapterStateCallback = base::OnceCallback<void(mojom::BluetoothAdapterState)>; + using GattReadCallback = + base::OnceCallback<void(arc::mojom::BluetoothGattValuePtr)>; + using CreateSdpRecordCallback = + base::OnceCallback<void(arc::mojom::BluetoothCreateSdpRecordResultPtr)>; + using RemoveSdpRecordCallback = + base::OnceCallback<void(arc::mojom::BluetoothStatus)>; // Returns singleton instance for the given BrowserContext, // or nullptr if the browser |context| is not allowed to use ARC. @@ -308,14 +314,6 @@ const std::vector<uint8_t>& value, SendIndicationCallback callback) override; - // Bluetooth Mojo host interface - Bluetooth SDP functions - void GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, - const device::BluetoothUUID& target_uuid) override; - void CreateSdpRecord(mojom::BluetoothSdpRecordPtr record_mojo, - CreateSdpRecordCallback callback) override; - void RemoveSdpRecord(uint32_t service_handle, - RemoveSdpRecordCallback callback) override; - // Bluetooth Mojo host interface - Bluetooth socket functions void BluetoothSocketListen(mojom::BluetoothSocketType sock_type, mojom::BluetoothSocketFlagsPtr sock_flags, @@ -340,7 +338,9 @@ int32_t adv_handle, ReleaseAdvertisementHandleCallback callback) override; - private: + protected: + bluez::BluetoothAdapterBlueZ* GetBluezAdapter() const; + void ReserveAdvertisementHandleImpl( ReserveAdvertisementHandleCallback callback); void EnableAdvertisementImpl( @@ -477,15 +477,6 @@ void OnSetDiscoverable(bool discoverable, bool success, uint32_t timeout); void SetDiscoverable(bool discoverable, uint32_t timeout); - void OnGetServiceRecordsDone( - mojom::BluetoothAddressPtr remote_addr, - const device::BluetoothUUID& target_uuid, - const std::vector<bluez::BluetoothServiceRecordBlueZ>& records_bluez); - void OnGetServiceRecordsError( - mojom::BluetoothAddressPtr remote_addr, - const device::BluetoothUUID& target_uuid, - bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code); - void OnSetAdapterProperty(mojom::BluetoothStatus success, mojom::BluetoothPropertyPtr property); @@ -606,7 +597,7 @@ ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager. - scoped_refptr<bluez::BluetoothAdapterBlueZ> bluetooth_adapter_; + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; scoped_refptr<device::BluetoothAdvertisement> advertisment_; // Discovery session created by StartDiscovery(). std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_;
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc index 897a514..47e1b11d 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
@@ -19,6 +19,7 @@ #include "base/system/sys_info.h" #include "base/test/scoped_chromeos_version_info.h" #include "base/test/task_environment.h" +#include "chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" #include "device/bluetooth/dbus/fake_bluetooth_device_client.h" @@ -40,6 +41,7 @@ constexpr int kFailureAdvHandle = -1; +// This unittest defaults to testing BlueZ. For Floss, use |ArcFlossBridgeTest|. class ArcBluetoothBridgeTest : public testing::Test { protected: void AddTestDevice() { @@ -115,8 +117,8 @@ arc_bridge_service_ = std::make_unique<ArcBridgeService>(); // TODO(hidehiko): Use Singleton instance tied to BrowserContext. - arc_bluetooth_bridge_ = std::make_unique<ArcBluetoothBridge>( - nullptr, arc_bridge_service_.get()); + arc_bluetooth_bridge_ = + std::make_unique<ArcBluezBridge>(nullptr, arc_bridge_service_.get()); fake_bluetooth_instance_ = std::make_unique<FakeBluetoothInstance>(); arc_bridge_service_->bluetooth()->SetInstance( fake_bluetooth_instance_.get(), 20);
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.cc new file mode 100644 index 0000000..ef1038c57 --- /dev/null +++ b/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.cc
@@ -0,0 +1,207 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h" + +#include "ash/components/arc/bluetooth/bluetooth_type_converters.h" +#include "ash/components/arc/session/arc_bridge_service.h" +#include "device/bluetooth/bluetooth_common.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluez/bluetooth_device_bluez.h" + +using device::BluetoothAdapter; +using device::BluetoothAdapterFactory; +using device::BluetoothAdvertisement; +using device::BluetoothDevice; +using device::BluetoothDiscoveryFilter; +using device::BluetoothDiscoverySession; +using device::BluetoothGattCharacteristic; +using device::BluetoothGattConnection; +using device::BluetoothGattDescriptor; +using device::BluetoothGattNotifySession; +using device::BluetoothGattService; +using device::BluetoothLocalGattCharacteristic; +using device::BluetoothLocalGattDescriptor; +using device::BluetoothLocalGattService; +using device::BluetoothRemoteGattCharacteristic; +using device::BluetoothRemoteGattDescriptor; +using device::BluetoothRemoteGattService; +using device::BluetoothTransport; +using device::BluetoothUUID; + +namespace { + +// Bluetooth SDP Service Class ID List Attribute identifier +constexpr uint16_t kServiceClassIDListAttributeID = 0x0001; + +void OnCreateServiceRecordDone( + arc::ArcBluetoothBridge::CreateSdpRecordCallback callback, + uint32_t service_handle) { + arc::mojom::BluetoothCreateSdpRecordResultPtr result = + arc::mojom::BluetoothCreateSdpRecordResult::New(); + result->status = arc::mojom::BluetoothStatus::SUCCESS; + result->service_handle = service_handle; + + std::move(callback).Run(std::move(result)); +} + +void OnCreateServiceRecordError( + arc::ArcBluetoothBridge::CreateSdpRecordCallback callback, + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { + arc::mojom::BluetoothCreateSdpRecordResultPtr result = + arc::mojom::BluetoothCreateSdpRecordResult::New(); + if (error_code == + bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) { + result->status = arc::mojom::BluetoothStatus::NOT_READY; + } else { + result->status = arc::mojom::BluetoothStatus::FAIL; + } + + std::move(callback).Run(std::move(result)); +} + +void OnRemoveServiceRecordDone( + arc::ArcBluetoothBridge::RemoveSdpRecordCallback callback) { + std::move(callback).Run(arc::mojom::BluetoothStatus::SUCCESS); +} + +void OnRemoveServiceRecordError( + arc::ArcBluetoothBridge::RemoveSdpRecordCallback callback, + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { + arc::mojom::BluetoothStatus status; + if (error_code == + bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) { + status = arc::mojom::BluetoothStatus::NOT_READY; + } else { + status = arc::mojom::BluetoothStatus::FAIL; + } + + std::move(callback).Run(status); +} + +} // namespace + +namespace arc { + +ArcBluezBridge::ArcBluezBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service) + : ArcBluetoothBridge(context, bridge_service) {} + +ArcBluezBridge::~ArcBluezBridge() = default; + +bluez::BluetoothAdapterBlueZ* ArcBluezBridge::GetAdapter() const { + return static_cast<bluez::BluetoothAdapterBlueZ*>(bluetooth_adapter_.get()); +} + +void ArcBluezBridge::GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, + const BluetoothUUID& target_uuid) { + BluetoothDevice* device = + GetAdapter()->GetDevice(remote_addr->To<std::string>()); + if (!device) { + OnGetServiceRecordsError(std::move(remote_addr), target_uuid, + bluez::BluetoothServiceRecordBlueZ::ErrorCode:: + ERROR_DEVICE_DISCONNECTED); + return; + } + + bluez::BluetoothDeviceBlueZ* device_bluez = + static_cast<bluez::BluetoothDeviceBlueZ*>(device); + + mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); + + device_bluez->GetServiceRecords( + base::BindOnce(&ArcBluezBridge::OnGetServiceRecordsDone, + weak_factory_.GetWeakPtr(), std::move(remote_addr), + target_uuid), + base::BindOnce(&ArcBluezBridge::OnGetServiceRecordsError, + weak_factory_.GetWeakPtr(), std::move(remote_addr_clone), + target_uuid)); +} + +void ArcBluezBridge::CreateSdpRecord( + mojom::BluetoothSdpRecordPtr record_mojo, + arc::ArcBluetoothBridge::CreateSdpRecordCallback callback) { + auto record = record_mojo.To<bluez::BluetoothServiceRecordBlueZ>(); + + // Check if ServiceClassIDList attribute (attribute ID 0x0001) is included + // after type conversion, since it is mandatory for creating a service record. + if (!record.IsAttributePresented(kServiceClassIDListAttributeID)) { + mojom::BluetoothCreateSdpRecordResultPtr result = + mojom::BluetoothCreateSdpRecordResult::New(); + result->status = mojom::BluetoothStatus::FAIL; + std::move(callback).Run(std::move(result)); + return; + } + + auto split_callback = base::SplitOnceCallback(std::move(callback)); + GetAdapter()->CreateServiceRecord( + record, + base::BindOnce(&OnCreateServiceRecordDone, + std::move(split_callback.first)), + base::BindOnce(&OnCreateServiceRecordError, + std::move(split_callback.second))); +} + +void ArcBluezBridge::RemoveSdpRecord(uint32_t service_handle, + RemoveSdpRecordCallback callback) { + auto split_callback = base::SplitOnceCallback(std::move(callback)); + GetAdapter()->RemoveServiceRecord( + service_handle, + base::BindOnce(&OnRemoveServiceRecordDone, + std::move(split_callback.first)), + base::BindOnce(&OnRemoveServiceRecordError, + std::move(split_callback.second))); +} + +void ArcBluezBridge::OnGetServiceRecordsDone( + mojom::BluetoothAddressPtr remote_addr, + const BluetoothUUID& target_uuid, + const std::vector<bluez::BluetoothServiceRecordBlueZ>& records_bluez) { + auto* sdp_bluetooth_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_bridge_service_->bluetooth(), OnGetSdpRecords); + if (!sdp_bluetooth_instance) { + return; + } + + std::vector<mojom::BluetoothSdpRecordPtr> records; + for (const auto& r : records_bluez) { + records.push_back(mojom::BluetoothSdpRecord::From(r)); + } + + sdp_bluetooth_instance->OnGetSdpRecords(mojom::BluetoothStatus::SUCCESS, + std::move(remote_addr), target_uuid, + std::move(records)); +} + +void ArcBluezBridge::OnGetServiceRecordsError( + mojom::BluetoothAddressPtr remote_addr, + const BluetoothUUID& target_uuid, + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { + auto* sdp_bluetooth_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_bridge_service_->bluetooth(), OnGetSdpRecords); + if (!sdp_bluetooth_instance) { + return; + } + + mojom::BluetoothStatus status; + + switch (error_code) { + case bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY: + status = mojom::BluetoothStatus::NOT_READY; + break; + case bluez::BluetoothServiceRecordBlueZ::ErrorCode:: + ERROR_DEVICE_DISCONNECTED: + status = mojom::BluetoothStatus::RMT_DEV_DOWN; + break; + default: + status = mojom::BluetoothStatus::FAIL; + break; + } + + sdp_bluetooth_instance->OnGetSdpRecords( + status, std::move(remote_addr), target_uuid, + std::vector<mojom::BluetoothSdpRecordPtr>()); +} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h b/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h new file mode 100644 index 0000000..d03cd81 --- /dev/null +++ b/chrome/browser/ash/arc/bluetooth/arc_bluez_bridge.h
@@ -0,0 +1,52 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_BLUEZ_BRIDGE_H_ +#define CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_BLUEZ_BRIDGE_H_ + +#include "ash/components/arc/mojom/bluetooth.mojom.h" +#include "chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h" +#include "device/bluetooth/bluez/bluetooth_adapter_bluez.h" + +namespace arc { + +// Bluez specialization for Arc Bluetooth bridge. Use this class whenever the +// common |device::BluetoothAdapter| or |device::BluetoothDevice| class apis are +// insufficient. +class ArcBluezBridge : public ArcBluetoothBridge { + public: + ArcBluezBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service); + ~ArcBluezBridge() override; + + ArcBluezBridge(const ArcBluezBridge&) = delete; + ArcBluezBridge& operator=(const ArcBluezBridge&) = delete; + + // Bluetooth Mojo host interface - Bluetooth SDP functions + void GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, + const device::BluetoothUUID& target_uuid) override; + void CreateSdpRecord(mojom::BluetoothSdpRecordPtr record_mojo, + CreateSdpRecordCallback callback) override; + void RemoveSdpRecord(uint32_t service_handle, + RemoveSdpRecordCallback callback) override; + + protected: + bluez::BluetoothAdapterBlueZ* GetAdapter() const; + + void OnGetServiceRecordsDone( + mojom::BluetoothAddressPtr remote_addr, + const device::BluetoothUUID& target_uuid, + const std::vector<bluez::BluetoothServiceRecordBlueZ>& records_bluez); + void OnGetServiceRecordsError( + mojom::BluetoothAddressPtr remote_addr, + const device::BluetoothUUID& target_uuid, + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code); + + private: + // WeakPtrFactory to use for callbacks. + base::WeakPtrFactory<ArcBluezBridge> weak_factory_{this}; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_BLUEZ_BRIDGE_H_
diff --git a/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.cc new file mode 100644 index 0000000..2dfef9d --- /dev/null +++ b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.cc
@@ -0,0 +1,42 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h" + +using device::BluetoothUUID; + +namespace arc { + +ArcFlossBridge::ArcFlossBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service) + : ArcBluetoothBridge(context, bridge_service) {} + +ArcFlossBridge::~ArcFlossBridge() = default; + +floss::BluetoothAdapterFloss* ArcFlossBridge::GetAdapter() const { + return static_cast<floss::BluetoothAdapterFloss*>(bluetooth_adapter_.get()); +} + +void ArcFlossBridge::GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, + const BluetoothUUID& target_uuid) { + NOTIMPLEMENTED(); +} + +void ArcFlossBridge::CreateSdpRecord(mojom::BluetoothSdpRecordPtr record_mojo, + CreateSdpRecordCallback callback) { + auto result = mojom::BluetoothCreateSdpRecordResult::New(); + result->status = mojom::BluetoothStatus::FAIL; + std::move(callback).Run(std::move(result)); + + NOTIMPLEMENTED(); +} + +void ArcFlossBridge::RemoveSdpRecord(uint32_t service_handle, + RemoveSdpRecordCallback callback) { + std::move(callback).Run(mojom::BluetoothStatus::FAIL); + + NOTIMPLEMENTED(); +} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h new file mode 100644 index 0000000..9cfabed --- /dev/null +++ b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h
@@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_FLOSS_BRIDGE_H_ +#define CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_FLOSS_BRIDGE_H_ + +#include "ash/components/arc/mojom/bluetooth.mojom.h" +#include "chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h" +#include "device/bluetooth/floss/bluetooth_adapter_floss.h" + +namespace arc { + +// Floss specialization for Arc Bluetooth bridge. Use this class whenever the +// common |device::BluetoothAdapter| or |device::BluetoothDevice| class apis are +// insufficient. +class ArcFlossBridge : public ArcBluetoothBridge { + public: + ArcFlossBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service); + ~ArcFlossBridge() override; + + ArcFlossBridge(const ArcFlossBridge&) = delete; + ArcFlossBridge& operator=(const ArcFlossBridge&) = delete; + + // Bluetooth Mojo host interface - Bluetooth SDP functions + void GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, + const device::BluetoothUUID& target_uuid) override; + void CreateSdpRecord(mojom::BluetoothSdpRecordPtr record_mojo, + CreateSdpRecordCallback callback) override; + void RemoveSdpRecord(uint32_t service_handle, + RemoveSdpRecordCallback callback) override; + + protected: + floss::BluetoothAdapterFloss* GetAdapter() const; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_ASH_ARC_BLUETOOTH_ARC_FLOSS_BRIDGE_H_
diff --git a/chrome/browser/ash/arc/bluetooth/arc_floss_bridge_unittest.cc b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge_unittest.cc new file mode 100644 index 0000000..6fc3d56 --- /dev/null +++ b/chrome/browser/ash/arc/bluetooth/arc_floss_bridge_unittest.cc
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/bluetooth/arc_floss_bridge.h" + +#include <memory> + +#include "ash/components/arc/session/arc_bridge_service.h" +#include "base/test/task_environment.h" +#include "chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +namespace arc { + +class ArcFlossBridgeTest : public testing::Test { + public: + void SetUp() override { + arc_bridge_service_ = std::make_unique<ArcBridgeService>(); + // TODO: Use Singleton instance tied to BrowserContext. + arc_bluetooth_bridge_ = + std::make_unique<ArcFlossBridge>(nullptr, arc_bridge_service_.get()); + } + + void TearDown() override { + arc_bluetooth_bridge_.reset(); + arc_bridge_service_.reset(); + } + + std::unique_ptr<ArcBridgeService> arc_bridge_service_; + std::unique_ptr<ArcBluetoothBridge> arc_bluetooth_bridge_; + base::test::SingleThreadTaskEnvironment task_environment_; +}; + +TEST_F(ArcFlossBridgeTest, Noop) {} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc index 586ad9c..cca1f403 100644 --- a/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc +++ b/chrome/browser/ash/arc/input_overlay/arc_input_overlay_manager_unittest.cc
@@ -458,8 +458,6 @@ // Test without enabling beta flag. int task_id = 21; - arc_app_test.app_instance()->SetTaskInfo(task_id, kRandomGamePackageName, - "activity"); arc_app_test.app_instance()->set_app_category_of_pkg( kRandomGamePackageName, arc::mojom::AppCategory::kGame); task_environment()->RunUntilIdle(); @@ -494,8 +492,6 @@ EXPECT_FALSE(injector); // Create an app with game category. task_id = 22; - arc_app_test.app_instance()->SetTaskInfo(task_id, kRandomGamePackageName, - "activity"); arc_app_test.app_instance()->set_app_category_of_pkg( kRandomGamePackageName, arc::mojom::AppCategory::kGame); task_environment()->RunUntilIdle();
diff --git a/chrome/browser/ash/arc/policy/arc_android_management_checker.cc b/chrome/browser/ash/arc/policy/arc_android_management_checker.cc index c6f8ec7..4fe30b7 100644 --- a/chrome/browser/ash/arc/policy/arc_android_management_checker.cc +++ b/chrome/browser/ash/arc/policy/arc_android_management_checker.cc
@@ -11,9 +11,9 @@ #include "base/task/single_thread_task_runner.h" #include "chrome/browser/ash/arc/policy/arc_policy_util.h" #include "chrome/browser/profiles/profile.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/signin/public/base/consent_level.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" namespace arc { @@ -47,8 +47,10 @@ // No need to check Android Management if the user is a Chrome OS managed // user, or belongs to a well-known non-enterprise domain. if (policy_util::IsAccountManaged(profile_) || - policy::BrowserPolicyConnector::IsNonEnterpriseUser( - profile_->GetProfileUserName())) { + (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + profile_->GetProfileUserName()) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise)) { std::move(callback).Run(CheckResult::ALLOWED); return; }
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc index 06deafa..2e2229f6 100644 --- a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc +++ b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
@@ -33,7 +33,6 @@ #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/policy/developer_tools_policy_handler.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" @@ -49,6 +48,7 @@ #include "components/policy/core/common/remote_commands/remote_commands_queue.h" #include "components/policy/policy_constants.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc index e8a2181..5bd9281 100644 --- a/chrome/browser/ash/arc/session/arc_service_launcher.cc +++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -92,6 +92,7 @@ #include "chrome/browser/ash/arc/tts/arc_tts_service.h" #include "chrome/browser/ash/arc/user_session/arc_user_session_service.h" #include "chrome/browser/ash/arc/video/gpu_arc_video_service_host.h" +#include "chrome/browser/ash/arc/vmm/arc_vmm_manager.h" #include "chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.h" #include "chrome/browser/ash/login/startup_utils.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -307,6 +308,7 @@ if (arc::IsArcVmEnabled()) { // ARCVM-only services. ArcMemoryPressureBridge::GetForBrowserContext(profile); + ArcVmmManager::GetForBrowserContext(profile); if (base::FeatureList::IsEnabled(kEnableArcVmDataMigration)) { arc_vm_data_migration_notifier_ =
diff --git a/chrome/browser/ash/arc/vmm/OWNERS b/chrome/browser/ash/arc/vmm/OWNERS new file mode 100644 index 0000000..e4f702a8 --- /dev/null +++ b/chrome/browser/ash/arc/vmm/OWNERS
@@ -0,0 +1 @@ +sstan@chromium.org
diff --git a/chrome/browser/ash/arc/vmm/arc_vmm_manager.cc b/chrome/browser/ash/arc/vmm/arc_vmm_manager.cc new file mode 100644 index 0000000..0ac55b6 --- /dev/null +++ b/chrome/browser/ash/arc/vmm/arc_vmm_manager.cc
@@ -0,0 +1,97 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/vmm/arc_vmm_manager.h" + +#include "ash/accelerators/accelerator_controller_impl.h" +#include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h" +#include "ash/components/arc/arc_features.h" +#include "ash/public/cpp/accelerators.h" +#include "ash/shell.h" +#include "base/feature_list.h" +#include "ui/base/accelerators/accelerator.h" + +namespace arc { + +namespace { +class ArcVmmManagerFactory + : public internal::ArcBrowserContextKeyedServiceFactoryBase< + ArcVmmManager, + ArcVmmManagerFactory> { + public: + static constexpr const char* kName = "ArcVmmManagerFactory"; + static ArcVmmManagerFactory* GetInstance() { + static base::NoDestructor<ArcVmmManagerFactory> instance; + return instance.get(); + } + + private: + friend class base::NoDestructor<ArcVmmManagerFactory>; + + ArcVmmManagerFactory() = default; + ~ArcVmmManagerFactory() override = default; +}; +} // namespace + +// static +ArcVmmManager* ArcVmmManager::GetForBrowserContext( + content::BrowserContext* context) { + return ArcVmmManagerFactory::GetForBrowserContext(context); +} + +ArcVmmManager::ArcVmmManager(content::BrowserContext* context, + ArcBridgeService* bridge) { + if (base::FeatureList::IsEnabled(kVmmSwapKeyboardShortcut)) { + accelerator_ = std::make_unique<AcceleratorTarget>(this); + } +} + +ArcVmmManager::~ArcVmmManager() = default; + +void ArcVmmManager::SetSwapState(bool enable) { + NOTIMPLEMENTED(); +} + +// ArcVmmManager::AcceleratorTarget -------------------------------------------- + +class ArcVmmManager::AcceleratorTarget : public ui::AcceleratorTarget { + public: + explicit AcceleratorTarget(ArcVmmManager* manager) + : manager_(manager), + vmm_swap_enabled_(ui::VKEY_O, ash::kDebugModifier), + vmm_swap_disabled_(ui::VKEY_P, ash::kDebugModifier) { + ash::Shell::Get()->accelerator_controller()->Register( + {vmm_swap_enabled_, vmm_swap_disabled_}, this); + } + AcceleratorTarget(const AcceleratorTarget&) = delete; + AcceleratorTarget& operator=(const AcceleratorTarget&) = delete; + ~AcceleratorTarget() override = default; + + private: + // ui::AcceleratorTarget: + bool AcceleratorPressed(const ui::Accelerator& accelerator) override { + if (accelerator == vmm_swap_enabled_) { + manager_->SetSwapState(true); + } else if (accelerator == vmm_swap_disabled_) { + manager_->SetSwapState(false); + } else { + NOTREACHED(); + return false; + } + return true; + } + + bool CanHandleAccelerators() const override { return true; } + + // The manager responsible for executing vmm commands. + ArcVmmManager* const manager_; + + // The accelerator to enable vmm swap for ARCVM. + const ui::Accelerator vmm_swap_enabled_; + + // The accelerator to disable vmm swap for ARCVM. + const ui::Accelerator vmm_swap_disabled_; +}; + +} // namespace arc
diff --git a/chrome/browser/ash/arc/vmm/arc_vmm_manager.h b/chrome/browser/ash/arc/vmm/arc_vmm_manager.h new file mode 100644 index 0000000..221a7b2f --- /dev/null +++ b/chrome/browser/ash/arc/vmm/arc_vmm_manager.h
@@ -0,0 +1,53 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_ +#define CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_ + +#include <string> + +#include "components/keyed_service/core/keyed_service.h" +#include "content/public/browser/browser_context.h" + +namespace arc { + +class ArcBridgeService; + +// ARCVM vmm features manager. +class ArcVmmManager : public KeyedService { + public: + // Returns singleton instance for the given BrowserContext, or nullptr if + // the browser |context| is not allowed to use ARC. + static ArcVmmManager* GetForBrowserContext(content::BrowserContext* context); + + ArcVmmManager(content::BrowserContext* context, ArcBridgeService* bridge); + + ArcVmmManager(const ArcVmmManager&) = delete; + ArcVmmManager& operator=(const ArcVmmManager&) = delete; + + ~ArcVmmManager() override; + + // SetSwapState change the ARCVM vmm swap state in crosvm. When swap enabled, + // the crosvm process will be STOP and guest memory will be moved to the + // staging memory. + void SetSwapState(bool enable); + + void set_user_id_hash(const std::string& user_id_hash) { + user_id_hash_ = user_id_hash; + } + + private: + // Accelerator target for experimental usage. Ctrl + Alt + Shift + O / P for + // enable or disable vmm swap. + class AcceleratorTarget; + + // Accelerator for experimental usage. Always behind the feature flag. + std::unique_ptr<AcceleratorTarget> accelerator_; + + std::string user_id_hash_; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_MANAGER_H_
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn index 1ff3d2c..bea04fba 100644 --- a/chrome/browser/ash/crosapi/BUILD.gn +++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -308,6 +308,7 @@ "//chromeos/startup:constants", "//chromeos/ui/wm:wm", "//chromeos/version", + "//components/app_restore", "//components/arc", "//components/crash/core/app", "//components/exo",
diff --git a/chrome/browser/ash/crosapi/browser_action.cc b/chrome/browser/ash/crosapi/browser_action.cc index 56e4f2e..ec724884 100644 --- a/chrome/browser/ash/crosapi/browser_action.cc +++ b/chrome/browser/ash/crosapi/browser_action.cc
@@ -259,24 +259,30 @@ class CreateBrowserWithRestoredDataAction final : public BrowserAction { public: - CreateBrowserWithRestoredDataAction(const std::vector<GURL>& urls, - const gfx::Rect& bounds, - ui::WindowShowState show_state, - int32_t active_tab_index, - base::StringPiece app_name, - int32_t restore_window_id) + CreateBrowserWithRestoredDataAction( + const std::vector<GURL>& urls, + const gfx::Rect& bounds, + const std::vector<tab_groups::TabGroupInfo>& tab_group_infos, + ui::WindowShowState show_state, + int32_t active_tab_index, + int32_t first_non_pinned_tab_index, + base::StringPiece app_name, + int32_t restore_window_id) : BrowserAction(true), urls_(urls), bounds_(bounds), + tab_group_infos_(tab_group_infos), show_state_(show_state), active_tab_index_(active_tab_index), + first_non_pinned_tab_index_(first_non_pinned_tab_index), app_name_(app_name), restore_window_id_(restore_window_id) {} void Perform(const VersionedBrowserService& service) override { crosapi::mojom::DeskTemplateStatePtr additional_state = - crosapi::mojom::DeskTemplateState::New(urls_, active_tab_index_, - app_name_, restore_window_id_); + crosapi::mojom::DeskTemplateState::New( + urls_, active_tab_index_, app_name_, restore_window_id_, + first_non_pinned_tab_index_, tab_group_infos_); crosapi::CrosapiManager::Get() ->crosapi_ash() ->desk_template_ash() @@ -288,8 +294,10 @@ private: const std::vector<GURL> urls_; const gfx::Rect bounds_; + const std::vector<tab_groups::TabGroupInfo> tab_group_infos_; const ui::WindowShowState show_state_; const int32_t active_tab_index_; + const int32_t first_non_pinned_tab_index_; const std::string app_name_; const int32_t restore_window_id_; }; @@ -368,12 +376,15 @@ std::unique_ptr<BrowserAction> BrowserAction::CreateBrowserWithRestoredData( const std::vector<GURL>& urls, const gfx::Rect& bounds, + const std::vector<tab_groups::TabGroupInfo>& tab_groups, ui::WindowShowState show_state, int32_t active_tab_index, + int32_t first_non_pinned_tab_index, base::StringPiece app_name, int32_t restore_window_id) { return std::make_unique<CreateBrowserWithRestoredDataAction>( - urls, bounds, show_state, active_tab_index, app_name, restore_window_id); + urls, bounds, tab_groups, show_state, active_tab_index, + first_non_pinned_tab_index, app_name, restore_window_id); } // No window will be opened in the following circumstances:
diff --git a/chrome/browser/ash/crosapi/browser_action.h b/chrome/browser/ash/crosapi/browser_action.h index 41428df..bd768f0 100644 --- a/chrome/browser/ash/crosapi/browser_action.h +++ b/chrome/browser/ash/crosapi/browser_action.h
@@ -9,6 +9,7 @@ #include "base/strings/string_piece_forward.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" +#include "components/tab_groups/tab_group_info.h" #include "ui/base/ui_base_types.h" namespace crosapi { @@ -59,8 +60,10 @@ static std::unique_ptr<BrowserAction> CreateBrowserWithRestoredData( const std::vector<GURL>& urls, const gfx::Rect& bounds, + const std::vector<tab_groups::TabGroupInfo>& tab_group_infos, ui::WindowShowState show_state, int32_t active_tab_index, + int32_t first_non_pinned_tab_index, base::StringPiece app_name, int32_t restore_window_id);
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index d1ba339..05664f8 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -692,12 +692,15 @@ void BrowserManager::CreateBrowserWithRestoredData( const std::vector<GURL>& urls, const gfx::Rect& bounds, + const std::vector<tab_groups::TabGroupInfo>& tab_group_infos, ui::WindowShowState show_state, int32_t active_tab_index, + int32_t first_non_pinned_tab_index, const std::string& app_name, int32_t restore_window_id) { PerformOrEnqueue(BrowserAction::CreateBrowserWithRestoredData( - urls, bounds, show_state, active_tab_index, app_name, restore_window_id)); + urls, bounds, tab_group_infos, show_state, active_tab_index, + first_non_pinned_tab_index, app_name, restore_window_id)); } void BrowserManager::InitializeAndStartIfNeeded() {
diff --git a/chrome/browser/ash/crosapi/browser_manager.h b/chrome/browser/ash/crosapi/browser_manager.h index b309979b..5bdf022 100644 --- a/chrome/browser/ash/crosapi/browser_manager.h +++ b/chrome/browser/ash/crosapi/browser_manager.h
@@ -31,6 +31,7 @@ #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/desk_template.mojom.h" +#include "components/component_updater/component_updater_service.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler_observer.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" @@ -38,6 +39,7 @@ #include "components/policy/core/common/policy_namespace.h" #include "components/policy/core/common/values_util.h" #include "components/session_manager/core/session_manager_observer.h" +#include "components/tab_groups/tab_group_info.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/ui_base_types.h" @@ -208,16 +210,22 @@ // |x_offset| is in DIP coordinates. void HandleTabScrubbing(float x_offset); - // Create a browser with the restored data containing |urls|, - // |bounds|, |show_state|, |active_tab_index| and |app_name|. Note an - // non-empty |app_name| indicates that the browser window is an app type - // browser window. - void CreateBrowserWithRestoredData(const std::vector<GURL>& urls, - const gfx::Rect& bounds, - const ui::WindowShowState show_state, - int32_t active_tab_index, - const std::string& app_name, - int32_t restore_window_id); + // Create a browser with the restored data containing `urls`, + // `bounds`,`tab_group_infos`, `show_state`, `active_tab_index`, + // `first_non_pinned_tab_index`, and `app_name`. Note an non-empty `app_name` + // indicates that the browser window is an app type browser window. Also + // note that` first_non_pinned_tab_indexes` with negative values are ignored + // type constratins for the `first_non_pinned_tab_index` and are enforced on + // the browser side and are dropped if they don't comply with said restraints. + void CreateBrowserWithRestoredData( + const std::vector<GURL>& urls, + const gfx::Rect& bounds, + const std::vector<tab_groups::TabGroupInfo>& tab_group_infos, + const ui::WindowShowState show_state, + int32_t active_tab_index, + int32_t first_non_pinned_tab_index, + const std::string& app_name, + int32_t restore_window_id); // Initialize resources and start Lacros. This class provides two approaches // to fulfill different requirements.
diff --git a/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc b/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc index e3217abd..4c37e81 100644 --- a/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc +++ b/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc
@@ -49,7 +49,7 @@ }); absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return base::UnguessableToken(); }
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 ca33c1b1..d935600 100644 --- a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc
@@ -6367,6 +6367,7 @@ ->context_factory() ->GetHostFrameSinkManager() ->StartFrameCountingForTest( // IN-TEST + base::TimeTicks::Now(), base::Seconds(params->bucket_size_in_seconds)); return RespondNow(NoArguments()); } @@ -6399,17 +6400,48 @@ return; } + // The data to fill in buckets where there is no data points in collected + // frame data, i.e. before the frame sink's creation and after the frame + // sink's destruction. + constexpr int kNotAvailable = -1; + + // Get the max size of frame sink data. The frame sink data that does not + // have enough data points (e.g. frame sinks destroyed before the end) will + // have kNotAvailable appended at the end. + size_t size = 0; + for (const auto& per_sink_data : data_ptr->per_sink_data) { + const size_t per_sink_data_size = + per_sink_data->start_bucket + per_sink_data->presented_frames.size(); + if (per_sink_data_size > size) { + size = per_sink_data_size; + } + } + std::vector<api::autotest_private::FrameCountingPerSinkData> result; for (const auto& per_sink_data : data_ptr->per_sink_data) { + // Skip frame sinks with no data points. + if (per_sink_data->presented_frames.empty()) { + continue; + } + api::autotest_private::FrameCountingPerSinkData result_per_sink_data; result_per_sink_data.sink_type = CompositorFrameSinkTypeToString(per_sink_data->type); result_per_sink_data.is_root = per_sink_data->is_root; + if (per_sink_data->start_bucket != 0) { + result_per_sink_data.presented_frames.resize(per_sink_data->start_bucket, + kNotAvailable); + } + std::copy(per_sink_data->presented_frames.begin(), per_sink_data->presented_frames.end(), std::back_inserter(result_per_sink_data.presented_frames)); + if (result_per_sink_data.presented_frames.size() < size) { + result_per_sink_data.presented_frames.resize(size, kNotAvailable); + } + result.emplace_back(std::move(result_per_sink_data)); }
diff --git a/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc b/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc index 9de0586..57fd489 100644 --- a/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc +++ b/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc
@@ -368,7 +368,7 @@ render_process_host_id_, request.url)) { DVLOG(1) << "Denied unauthorized request for " << request.url.possibly_invalid_spec(); - mojo::ReportBadMessage("Unauthorized externalfile request"); + ReportBadMessage("Unauthorized externalfile request"); return; } content::GetIOThreadTaskRunner({})->PostTask(
diff --git a/chrome/browser/ash/game_mode/game_mode_controller.cc b/chrome/browser/ash/game_mode/game_mode_controller.cc index f637b53a..aeed9a5 100644 --- a/chrome/browser/ash/game_mode/game_mode_controller.cc +++ b/chrome/browser/ash/game_mode/game_mode_controller.cc
@@ -8,6 +8,7 @@ #include "ash/components/arc/arc_util.h" #include "ash/components/arc/mojom/app.mojom.h" #include "ash/components/arc/session/connection_holder.h" +#include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "base/metrics/histogram_functions.h" #include "base/time/time.h" @@ -33,7 +34,7 @@ public: // Constructs an instance using the task ID of the window it is associated // with. - explicit ArcGameModeCriteria(int task_id) { + explicit ArcGameModeCriteria(aura::Window* window) { // For ARC container boards, Game Mode optimizations are not available // (b/248972198). if (!arc::IsArcVmEnabled()) @@ -44,14 +45,28 @@ DCHECK(arc::IsArcAllowedForProfile(profile)); connection_ = ArcAppListPrefs::Get(profile)->app_connection_holder(); - auto* app_instance = ARC_GET_INSTANCE_FOR_METHOD(connection_, GetTaskInfo); - if (!app_instance) { + auto* pkg_name = window->GetProperty(ash::kArcPackageNameKey); + + if (!pkg_name || pkg_name->empty()) { + LOG(ERROR) << "Failed to find package name for the requested task"; return; } - VLOG(2) << "Getting package name for ARC task: " << task_id; - app_instance->GetTaskInfo( - task_id, base::BindOnce(&ArcGameModeCriteria::OnReceiveTaskInfo, - weak_ptr_factory_.GetWeakPtr())); + + if (IsKnownGame(*pkg_name)) { + VLOG(2) << "ARC task package " << pkg_name << " is known game"; + Enable(); + return; + } + + auto* app_instance = + ARC_GET_INSTANCE_FOR_METHOD(connection_, GetAppCategory); + if (!app_instance) + return; + VLOG(2) << "Fetch app category of package: " << pkg_name; + + app_instance->GetAppCategory( + *pkg_name, base::BindOnce(&ArcGameModeCriteria::OnReceiveAppCategory, + weak_ptr_factory_.GetWeakPtr())); } // Checks if an ARC game package is in the known games list. These are apps @@ -72,28 +87,6 @@ return false; } - void OnReceiveTaskInfo(const std::string& pkg_name, - const std::string& activity) { - if (pkg_name.empty()) { - LOG(ERROR) << "Failed to find package name for the requested task"; - return; - } - - if (IsKnownGame(pkg_name)) { - VLOG(2) << "ARC task package " << pkg_name << " is known game"; - Enable(); - } else if (auto* app_instance = - ARC_GET_INSTANCE_FOR_METHOD(connection_, GetAppCategory); - app_instance) { - VLOG(2) << "Fetch app category of package: " << pkg_name; - app_instance->GetAppCategory( - pkg_name, base::BindOnce(&ArcGameModeCriteria::OnReceiveAppCategory, - weak_ptr_factory_.GetWeakPtr())); - } else { - LOG(ERROR) << "Failed to call GetAppCategory"; - } - } - void OnReceiveAppCategory(arc::mojom::AppCategory category) { VLOG(2) << "ARC app category is: " << category; if (category == arc::mojom::AppCategory::kGame) { @@ -228,10 +221,7 @@ game_mode_criteria_ = std::make_unique<GameModeEnabler>( GameMode::BOREALIS, /*signal_resourced=*/true); } else if (mode == GameMode::ARC) { - // We know GetWindowTaskId will not return absl::nullopt since ModeOfWindow - // already verified it. - game_mode_criteria_ = - std::make_unique<ArcGameModeCriteria>(*arc::GetWindowTaskId(window)); + game_mode_criteria_ = std::make_unique<ArcGameModeCriteria>(window); } else { LOG(DFATAL) << "Unknown GameMode: " << static_cast<int>(mode); }
diff --git a/chrome/browser/ash/game_mode/game_mode_controller_for_arc_unittest.cc b/chrome/browser/ash/game_mode/game_mode_controller_for_arc_unittest.cc index d75969ae..145c2c0 100644 --- a/chrome/browser/ash/game_mode/game_mode_controller_for_arc_unittest.cc +++ b/chrome/browser/ash/game_mode/game_mode_controller_for_arc_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/public/cpp/window_properties.h" #include "chrome/browser/ash/game_mode/testing/game_mode_controller_test_base.h" #include "ash/components/arc/arc_features.h" @@ -51,13 +52,16 @@ GameModeControllerTestBase::TearDown(); } - std::unique_ptr<views::Widget> CreateArcTaskWidget(int task_id) { + std::unique_ptr<views::Widget> CreateArcTaskWidget( + int task_id, const std::string& package_name = "asdf") { ash::TestWidgetBuilder builder; builder.SetShow(false); auto widget = builder.BuildOwnsNativeWidget(); exo::SetShellApplicationId( widget->GetNativeWindow(), base::StringPrintf("org.chromium.arc.%d", task_id)); + widget->GetNativeWindow()->SetProperty( + ash::kArcPackageNameKey, package_name); return widget; } @@ -68,12 +72,10 @@ }; TEST_F(GameModeControllerForArcTest, ChangingFullScreenTogglesGameMode) { - arc_app_test_.app_instance()->SetTaskInfo(42, "org.funstuff.client", - "activity"); arc_app_test_.app_instance()->set_app_category_of_pkg( "org.funstuff.client", arc::mojom::AppCategory::kGame); - auto game_widget = CreateArcTaskWidget(42); + auto game_widget = CreateArcTaskWidget(42, "org.funstuff.client"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response( @@ -92,12 +94,10 @@ } TEST_F(GameModeControllerForArcTest, SwitchToNonGameArcAppTurnsOffGameMode) { - arc_app_test_.app_instance()->SetTaskInfo(2424, "net.another.game", - "activity"); arc_app_test_.app_instance()->set_app_category_of_pkg( "net.another.game", arc::mojom::AppCategory::kGame); - auto game_widget = CreateArcTaskWidget(2424); + auto game_widget = CreateArcTaskWidget(2424, "net.another.game"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response( @@ -111,22 +111,19 @@ arc_app_test_.app_instance()->set_app_category_of_pkg( "net.recipes.search", arc::mojom::AppCategory::kProductivity); - arc_app_test_.app_instance()->SetTaskInfo(9999, "net.recipes.search", - "activity"); EXPECT_EQ(0, fake_resourced_client_->get_exit_game_mode_count()); - auto app_widget = CreateArcTaskWidget(9999); + auto app_widget = CreateArcTaskWidget(9999, "net.recipes.search"); app_widget->Show(); EXPECT_EQ(1, fake_resourced_client_->get_exit_game_mode_count()); } TEST_F(GameModeControllerForArcTest, SwitchToNonArcWindowAndBackTurnsOffGameMode) { - arc_app_test_.app_instance()->SetTaskInfo(42, "org.some.game", "activity"); - arc_app_test_.app_instance()->set_app_category_of_pkg( + arc_app_test_.app_instance()->set_app_category_of_pkg( "org.some.game", arc::mojom::AppCategory::kGame); - auto game_widget = CreateArcTaskWidget(42); + auto game_widget = CreateArcTaskWidget(42, "org.some.game"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response( @@ -151,14 +148,13 @@ } TEST_F(GameModeControllerForArcTest, SwitchToBorealisWindowAndBack) { - arc_app_test_.app_instance()->SetTaskInfo(14, "jp.foo.game", "activity"); arc_app_test_.app_instance()->set_app_category_of_pkg( - "jp.foo.game", arc::mojom::AppCategory::kGame); + "jp.foo.game", arc::mojom::AppCategory::kGame); auto non_game_widget = ash::TestWidgetBuilder().SetShow(true).BuildOwnsNativeWidget(); - auto game_widget = CreateArcTaskWidget(14); + auto game_widget = CreateArcTaskWidget(14, "jp.foo.game"); std::unique_ptr<views::Widget> borealis_widget = borealis::CreateFakeWidget("org.chromium.borealis.foo"); @@ -188,10 +184,8 @@ TEST_F(GameModeControllerForArcTest, IdentifyGameWithGetAppCategory) { arc_app_test_.app_instance()->set_app_category_of_pkg( "org.an_awesome.game", arc::mojom::AppCategory::kGame); - arc_app_test_.app_instance()->SetTaskInfo(9882, "org.an_awesome.game", - "activity"); - auto game_widget = CreateArcTaskWidget(9882); + auto game_widget = CreateArcTaskWidget(9882, "org.an_awesome.game"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response( ash::ResourcedClient::GameMode::OFF); @@ -202,10 +196,8 @@ TEST_F(GameModeControllerForArcTest, IdentifyGameWithKnownGameList) { arc_app_test_.app_instance()->set_app_category_of_pkg( "org.an_awesome.game", arc::mojom::AppCategory::kUndefined); - arc_app_test_.app_instance()->SetTaskInfo(9882, "com.mojang.minecraftedu", - "activity"); - auto game_widget = CreateArcTaskWidget(9882); + auto game_widget = CreateArcTaskWidget(9882, "com.mojang.minecraftedu"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response( ash::ResourcedClient::GameMode::OFF); @@ -216,10 +208,8 @@ TEST_F(GameModeControllerForArcTest, RecordLengthOfGameModeHistogram) { arc_app_test_.app_instance()->set_app_category_of_pkg( "org.an_awesome.game", arc::mojom::AppCategory::kGame); - arc_app_test_.app_instance()->SetTaskInfo(9882, "org.an_awesome.game", - "activity"); - auto game_widget = CreateArcTaskWidget(9882); + auto game_widget = CreateArcTaskWidget(9882, "org.an_awesome.game"); histogram_tester_->ExpectBucketCount( TimeInGameModeHistogramName(GameMode::ARC), 5000.0, 0); @@ -238,10 +228,8 @@ TEST_F(GameModeControllerForArcTest, RecordGameModeResultHistogram) { arc_app_test_.app_instance()->set_app_category_of_pkg( "org.an_awesome.gameedu", arc::mojom::AppCategory::kGame); - arc_app_test_.app_instance()->SetTaskInfo(9882, "org.an_awesome.gameedu", - "activity"); - auto game_widget = CreateArcTaskWidget(9882); + auto game_widget = CreateArcTaskWidget(9882, "org.an_awesome.gameedu"); game_widget->SetFullscreen(true); histogram_tester_->ExpectBucketCount( GameModeResultHistogramName(GameMode::ARC), GameModeResult::kAttempted, @@ -273,10 +261,8 @@ arc_app_test_.app_instance()->set_app_category_of_pkg( "net.another.game", arc::mojom::AppCategory::kGame); - arc_app_test_.app_instance()->SetTaskInfo(2424, "net.another.game", - "activity"); - auto game_widget = CreateArcTaskWidget(2424); + auto game_widget = CreateArcTaskWidget(2424, "net.another.game"); game_widget->Show(); fake_resourced_client_->set_set_game_mode_response(
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 746ef5f..c49171aa 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
@@ -9,11 +9,11 @@ #include "base/memory/scoped_refptr.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" +#include "chrome/browser/ash/app_mode/fake_kiosk_app_launcher.h" #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h" +#include "chrome/browser/ash/app_mode/kiosk_app_launcher.h" #include "chrome/browser/ash/app_mode/kiosk_app_types.h" -#include "chrome/browser/ash/app_mode/web_app/mock_web_kiosk_app_launcher.h" #include "chrome/browser/ash/login/test/kiosk_test_helpers.h" -#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/extensions/extension_service.h" @@ -25,6 +25,7 @@ #include "chrome/test/base/testing_profile.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/policy_service.h" #include "components/policy/policy_constants.h" #include "components/session_manager/core/session_manager.h" @@ -40,7 +41,6 @@ namespace { using ::testing::Eq; -using ::testing::Mock; const char kExtensionId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; const char kInvalidExtensionId[] = "invalid-extension-id"; @@ -101,7 +101,7 @@ disable_wait_timer_and_login_operations_for_testing_ = KioskLaunchController::DisableWaitTimerAndLoginOperationsForTesting(); - auto app_launcher = std::make_unique<MockWebKioskAppLauncher>(); + auto app_launcher = std::make_unique<FakeKioskAppLauncher>(); app_launcher_ = app_launcher.get(); view_ = std::make_unique<FakeAppLaunchSplashScreenHandler>(); @@ -132,7 +132,7 @@ AppLaunchSplashScreenView::Delegate& view_controls() { return *controller_; } - MockWebKioskAppLauncher& launcher() { return *app_launcher_; } + FakeKioskAppLauncher& launcher() { return *app_launcher_; } auto HasState(AppState app_state, NetworkUIState network_state) { return testing::AllOf( @@ -173,8 +173,8 @@ void RunUntilAppPrepared() { controller().Start(kiosk_app_id(), /*auto_launch=*/false); profile_controls().OnProfileLoaded(profile()); - launcher().CallOnAppInstalling(); - launcher().CallOnAppPrepared(); + launcher().observers().NotifyAppInstalling(); + launcher().observers().NotifyAppPrepared(); } void VerifyLaunchStateCrashKey(KioskLaunchState state) { @@ -192,7 +192,7 @@ std::unique_ptr<base::AutoReset<bool>> disable_wait_timer_and_login_operations_for_testing_; std::unique_ptr<FakeAppLaunchSplashScreenHandler> view_; - MockWebKioskAppLauncher* app_launcher_; // owned by `controller_`. + FakeKioskAppLauncher* app_launcher_; // owned by `controller_`. std::unique_ptr<KioskLaunchController> controller_; KioskAppId kiosk_app_id_; }; @@ -203,8 +203,8 @@ EXPECT_THAT(controller(), HasState(AppState::kCreatingProfile, NetworkUIState::kNotShowing)); - EXPECT_CALL(launcher(), Initialize()).Times(1); profile_controls().OnProfileLoaded(profile()); + EXPECT_TRUE(launcher().IsInitialized()); } TEST_F(KioskLaunchControllerTest, AppInstallingShouldUpdateSplashScreen) { @@ -212,7 +212,7 @@ VerifyLaunchStateCrashKey(KioskLaunchState::kLauncherStarted); profile_controls().OnProfileLoaded(profile()); - launcher().CallOnAppInstalling(); + launcher().observers().NotifyAppInstalling(); EXPECT_THAT( view(), @@ -221,11 +221,7 @@ } TEST_F(KioskLaunchControllerTest, AppPreparedShouldUpdateInternalState) { - controller().Start(kiosk_app_id(), /*auto_launch=*/false); - profile_controls().OnProfileLoaded(profile()); - launcher().CallOnAppInstalling(); - - launcher().CallOnAppPrepared(); + RunUntilAppPrepared(); EXPECT_THAT(controller(), HasState(AppState::kInstalled, NetworkUIState::kNotShowing)); @@ -236,35 +232,31 @@ } TEST_F(KioskLaunchControllerTest, SplashScreenTimerShouldLaunchPreparedApp) { - EXPECT_CALL(launcher(), LaunchApp()).Times(0); RunUntilAppPrepared(); + EXPECT_FALSE(launcher().HasAppLaunched()); - Mock::VerifyAndClearExpectations(&launcher()); - - EXPECT_CALL(launcher(), LaunchApp()).Times(1); FireSplashScreenTimer(); + EXPECT_TRUE(launcher().HasAppLaunched()); } TEST_F(KioskLaunchControllerTest, SplashScreenTimerShouldNotLaunchUnpreparedApp) { controller().Start(kiosk_app_id(), /*auto_launch=*/false); profile_controls().OnProfileLoaded(profile()); - launcher().CallOnAppInstalling(); + launcher().observers().NotifyAppInstalling(); - EXPECT_CALL(launcher(), LaunchApp()).Times(0); FireSplashScreenTimer(); + EXPECT_FALSE(launcher().HasAppLaunched()); - Mock::VerifyAndClearExpectations(&launcher()); - - EXPECT_CALL(launcher(), LaunchApp()).Times(1); - launcher().CallOnAppPrepared(); + launcher().observers().NotifyAppPrepared(); + EXPECT_TRUE(launcher().HasAppLaunched()); } TEST_F(KioskLaunchControllerTest, AppLaunchedShouldStartSession) { RunUntilAppPrepared(); FireSplashScreenTimer(); - launcher().CallOnAppLaunched(); + launcher().observers().NotifyAppLaunched(); EXPECT_THAT(controller(), HasState(AppState::kLaunched, NetworkUIState::kNotShowing)); @@ -287,9 +279,10 @@ view(), HasViewState( AppLaunchSplashScreenView::AppLaunchState::kPreparingNetwork)); + EXPECT_FALSE(launcher().HasContinueWithNetworkReadyBeenCalled()); - EXPECT_CALL(launcher(), ContinueWithNetworkReady()).Times(1); SetOnline(true); + EXPECT_TRUE(launcher().HasContinueWithNetworkReadyBeenCalled()); } TEST_F(KioskLaunchControllerTest, @@ -324,7 +317,6 @@ NetworkUIState::kNeedToShow)); VerifyLaunchStateCrashKey(KioskLaunchState::kLauncherStarted); - EXPECT_CALL(launcher(), Initialize()).Times(1); profile_controls().OnProfileLoaded(profile()); EXPECT_THAT(controller(), @@ -339,14 +331,11 @@ VerifyLaunchStateCrashKey(KioskLaunchState::kLauncherStarted); EXPECT_THAT(controller(), HasState(AppState::kCreatingProfile, NetworkUIState::kNotShowing)); - - EXPECT_CALL(launcher(), Initialize()).Times(1); profile_controls().OnProfileLoaded(profile()); - launcher().CallOnAppInstalling(); + launcher().observers().NotifyAppInstalling(); // User presses the hotkey, current installation is canceled. - EXPECT_CALL(launcher(), RestartLauncher()).Times(1); OnNetworkConfigRequested(); EXPECT_THAT(controller(), @@ -356,12 +345,12 @@ HasViewState( AppLaunchSplashScreenView::AppLaunchState::kInstallingApplication)); - EXPECT_CALL(launcher(), RestartLauncher()).Times(1); view_controls().OnNetworkConfigFinished(); EXPECT_THAT( view(), HasViewState( AppLaunchSplashScreenView::AppLaunchState::kPreparingProfile)); + EXPECT_TRUE(launcher().IsInitialized()); } TEST_F(KioskLaunchControllerTest, KioskProfileLoadFailedObserverShouldBeFired) { @@ -372,7 +361,6 @@ EXPECT_THAT(controller(), HasState(AppState::kCreatingProfile, NetworkUIState::kNotShowing)); - EXPECT_CALL(launcher(), Initialize()).Times(0); EXPECT_CALL(profile_load_failed_observer, OnKioskProfileLoadFailed()) .Times(1); profile_controls().OnProfileLoadFailed( @@ -398,15 +386,22 @@ TEST_F(KioskLaunchControllerTest, LaunchShouldCompleteAfterNetworkRequiredDuringAppLaunch) { + SetOnline(false); RunUntilAppPrepared(); FireSplashScreenTimer(); + EXPECT_EQ(launcher().launch_app_called(), 1); + // Network required during app launch network_delegate().InitializeNetwork(); EXPECT_THAT(controller(), HasState(AppState::kInitNetwork, NetworkUIState::kNotShowing)); + EXPECT_FALSE(launcher().HasContinueWithNetworkReadyBeenCalled()); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); - launcher().CallOnAppPrepared(); + SetOnline(true); + EXPECT_TRUE(launcher().HasContinueWithNetworkReadyBeenCalled()); + + launcher().observers().NotifyAppPrepared(); + EXPECT_EQ(launcher().launch_app_called(), 2); } class KioskLaunchControllerWithExtensionTest @@ -462,10 +457,10 @@ HasViewState( AppLaunchSplashScreenView::AppLaunchState::kWaitingAppWindow)); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); FireSplashScreenTimer(); + EXPECT_TRUE(launcher().HasAppLaunched()); - launcher().CallOnAppLaunched(); + launcher().observers().NotifyAppLaunched(); EXPECT_THAT(controller(), HasState(AppState::kLaunched, NetworkUIState::kNotShowing)); EXPECT_THAT( @@ -490,7 +485,6 @@ HasViewState( AppLaunchSplashScreenView::AppLaunchState::kInstallingExtension)); - EXPECT_CALL(launcher(), LaunchApp()).Times(0); SetExtensionReady(kExtensionId, kExtensionName); EXPECT_THAT(controller(), HasState(AppState::kInstalled, NetworkUIState::kNotShowing)); @@ -498,6 +492,7 @@ view(), HasViewState( AppLaunchSplashScreenView::AppLaunchState::kWaitingAppWindow)); + EXPECT_FALSE(launcher().HasAppLaunched()); histogram.ExpectBucketCount("Kiosk.Extensions.InstallTimedOut", false, 1); } @@ -515,7 +510,6 @@ HasViewState( AppLaunchSplashScreenView::AppLaunchState::kInstallingExtension)); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); SetExtensionReady(kExtensionId, kExtensionName); EXPECT_THAT(controller(), HasState(AppState::kInstalled, NetworkUIState::kNotShowing)); @@ -523,6 +517,7 @@ view(), HasViewState( AppLaunchSplashScreenView::AppLaunchState::kWaitingAppWindow)); + EXPECT_TRUE(launcher().HasAppLaunched()); } TEST_F(KioskLaunchControllerWithExtensionTest, @@ -540,9 +535,9 @@ FireSplashScreenTimer(); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); task_environment()->FastForwardBy(base::Minutes(2)); + EXPECT_TRUE(launcher().HasAppLaunched()); EXPECT_THAT(controller(), HasState(AppState::kInstalled, NetworkUIState::kNotShowing)); EXPECT_THAT( @@ -572,8 +567,8 @@ kExtensionId, kExtensionName, extensions::InstallStageTracker::FailureReason::INVALID_ID); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); FireSplashScreenTimer(); + EXPECT_TRUE(launcher().HasAppLaunched()); } TEST_F(KioskLaunchControllerWithExtensionTest, @@ -587,8 +582,8 @@ view(), HasErrorMessage(KioskAppLaunchError::Error::kExtensionsPolicyInvalid)); - EXPECT_CALL(launcher(), LaunchApp()).Times(1); FireSplashScreenTimer(); + EXPECT_TRUE(launcher().HasAppLaunched()); histogram.ExpectTotalCount("Kiosk.Extensions.InstallTimedOut", 0); } @@ -631,4 +626,34 @@ extensions::InstallStageTracker::FailureReason::INVALID_ID, 1); } +TEST_F(KioskLaunchControllerTest, TestFullFlow) { + SetOnline(true); + + EXPECT_FALSE(launcher().IsInitialized()); + EXPECT_FALSE(launcher().HasAppLaunched()); + EXPECT_FALSE(launcher().HasContinueWithNetworkReadyBeenCalled()); + + controller().Start(kiosk_app_id(), /*auto_launch=*/false); + profile_controls().OnProfileLoaded(profile()); + + EXPECT_EQ(launcher().initialize_called(), 1); + EXPECT_FALSE(launcher().HasAppLaunched()); + EXPECT_FALSE(launcher().HasContinueWithNetworkReadyBeenCalled()); + + launcher().observers().NotifyAppInstalling(); + + network_delegate().InitializeNetwork(); + + EXPECT_EQ(launcher().initialize_called(), 1); + EXPECT_EQ(launcher().continue_with_network_ready_called(), 1); + EXPECT_FALSE(launcher().HasAppLaunched()); + + launcher().observers().NotifyAppPrepared(); + + FireSplashScreenTimer(); + + EXPECT_EQ(launcher().initialize_called(), 1); + EXPECT_EQ(launcher().continue_with_network_ready_called(), 1); + EXPECT_EQ(launcher().launch_app_called(), 1); +} } // namespace ash
diff --git a/chrome/browser/ash/login/auth/chrome_login_performer.cc b/chrome/browser/ash/login/auth/chrome_login_performer.cc index 83a10ccc..2ed9434 100644 --- a/chrome/browser/ash/login/auth/chrome_login_performer.cc +++ b/chrome/browser/ash/login/auth/chrome_login_performer.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "components/account_id/account_id.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace ash { @@ -41,10 +42,11 @@ weak_factory_.GetWeakPtr(), &callback)); // Must not proceed without signature verification. if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { - if (delegate_) + if (delegate_) { delegate_->PolicyLoadFailed(); - else + } else { NOTREACHED(); + } return true; // Some callback was called. } else if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED) { // Value of AllowNewUser setting is still not verified. @@ -67,10 +69,11 @@ weak_factory_.GetWeakPtr(), callback)); // Must not proceed without signature verification. if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) { - if (delegate_) + if (delegate_) { delegate_->PolicyLoadFailed(); - else + } else { NOTREACHED(); + } } else if (status == CrosSettingsProvider::TEMPORARILY_UNTRUSTED) { // Value of AllowNewUser setting is still not verified. // Another attempt will be invoked after verification completion. @@ -99,7 +102,9 @@ policy::BrowserPolicyConnectorAsh* connector = g_browser_process->platform_part()->browser_policy_connector_ash(); if (connector->IsCloudManaged() && wildcard_match && - !connector->IsNonEnterpriseUser(account_id.GetUserEmail())) { + (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_id.GetUserEmail()) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus::kUnknown)) { wildcard_login_checker_ = std::make_unique<policy::WildcardLoginChecker>(); if (refresh_token.empty()) { NOTREACHED() << "Refresh token must be present.";
diff --git a/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc b/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc index 043aea3..3bec463 100644 --- a/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc +++ b/chrome/browser/ash/login/enrollment/enrollment_embedded_policy_server_browsertest.cc
@@ -9,7 +9,6 @@ #include "ash/public/cpp/login_screen_test_api.h" #include "base/check.h" #include "base/command_line.h" -#include "base/functional/bind.h" #include "base/test/gtest_util.h" #include "base/values.h" #include "build/build_config.h" @@ -38,7 +37,7 @@ #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.h" #include "chrome/browser/ash/policy/enrollment/enrollment_requisition_manager.h" -#include "chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h" +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h" #include "chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -1081,7 +1080,7 @@ WizardController::default_controller() ->GetAutoEnrollmentControllerForTesting() ->SetRlweClientFactoryForTesting( - base::BindRepeating(&policy::psm::FakeRlweClient::Create)); + policy::psm::testing::CreateClientFactory(/*is_member=*/true)); OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait(); @@ -1123,7 +1122,7 @@ WizardController::default_controller() ->GetAutoEnrollmentControllerForTesting() ->SetRlweClientFactoryForTesting( - base::BindRepeating(&policy::psm::FakeRlweClient::Create)); + policy::psm::testing::CreateClientFactory(/*is_member=*/true)); OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait(); @@ -1163,7 +1162,7 @@ WizardController::default_controller() ->GetAutoEnrollmentControllerForTesting() ->SetRlweClientFactoryForTesting( - base::BindRepeating(&policy::psm::FakeRlweClient::Create)); + policy::psm::testing::CreateClientFactory(/*is_member=*/true)); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepDeviceAttributes); enrollment_ui_.SubmitDeviceAttributes(test::values::kAssetId,
diff --git a/chrome/browser/ash/login/oobe_interactive_ui_test.cc b/chrome/browser/ash/login/oobe_interactive_ui_test.cc index fcf121c..c97f2cd 100644 --- a/chrome/browser/ash/login/oobe_interactive_ui_test.cc +++ b/chrome/browser/ash/login/oobe_interactive_ui_test.cc
@@ -45,7 +45,7 @@ #include "chrome/browser/ash/login/ui/login_display_host.h" #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ash/policy/enrollment/auto_enrollment_type_checker.h" -#include "chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h" +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" #include "chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.h" @@ -888,7 +888,7 @@ WizardController::default_controller() ->GetAutoEnrollmentControllerForTesting() ->SetRlweClientFactoryForTesting( - base::BindRepeating(&policy::psm::FakeRlweClient::Create)); + policy::psm::testing::CreateClientFactory()); PerformStepsBeforeEnrollmentCheck();
diff --git a/chrome/browser/ash/login/quick_unlock/pin_backend.h b/chrome/browser/ash/login/quick_unlock/pin_backend.h index d37ac66..684265e 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_backend.h +++ b/chrome/browser/ash/login/quick_unlock/pin_backend.h
@@ -10,6 +10,7 @@ #include "base/functional/callback.h" #include "chromeos/ash/components/login/auth/public/auth_callbacks.h" #include "chromeos/ash/components/login/auth/public/key.h" +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" #include "components/prefs/pref_service.h" class AccountId; @@ -24,7 +25,7 @@ // Provides high-level access to the user's PIN. The underlying storage can be // either cryptohome or prefs. -class PinBackend { +class PinBackend : public ash::auth::PinBackendDelegate { public: using BoolCallback = base::OnceCallback<void(bool)>; @@ -45,7 +46,7 @@ PinBackend(const PinBackend&) = delete; PinBackend& operator=(const PinBackend&) = delete; - ~PinBackend(); + ~PinBackend() override; // Check to see if the PinBackend supports login. This is true when the // cryptohome backend is available. @@ -61,7 +62,7 @@ void Set(const AccountId& account_id, const std::string& auth_token, const std::string& pin, - BoolCallback did_set); + BoolCallback did_set) override; // Set the state of PIN auto submit for the given user. Called when enabling // auto submit through the confirmation dialog in Settings. @@ -73,7 +74,7 @@ // Remove the given user's PIN. void Remove(const AccountId& account_id, const std::string& auth_token, - BoolCallback did_remove); + BoolCallback did_remove) override; // Is PIN authentication available for the given account? Even if PIN is set, // it may not be available for authentication due to some additional
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc index 20ca812..c3b1ee4 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc +++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc
@@ -151,55 +151,47 @@ } void SetPassword(const std::string& password) const { - ::user_data_auth::AddKeyRequest request; - - const cryptohome::KeyDefinition key_def = - cryptohome::KeyDefinition::CreateForPassword( - password, KeyLabel(kCryptohomeGaiaKeyLabel), - cryptohome::PRIV_MIGRATE); - cryptohome::KeyDefinitionToKey(key_def, request.mutable_key()); - *request.mutable_account_id() = - cryptohome::CreateAccountIdentifierFromAccountId(test_account_id_); - // Ensure that has_authorization_request() would return true. - request.mutable_authorization_request(); + ::user_data_auth::AddAuthFactorRequest request; + request.set_auth_session_id(user_context_->GetAuthSessionId()); + request.mutable_auth_factor()->set_type( + ::user_data_auth::AUTH_FACTOR_TYPE_PASSWORD); + request.mutable_auth_factor()->set_label(kCryptohomeGaiaKeyLabel); + request.mutable_auth_factor()->mutable_password_metadata(); + request.mutable_auth_input()->mutable_password_input()->set_secret( + password); base::RunLoop run_loop; - UserDataAuthClient::Get()->AddKey( - request, base::BindOnce( - [](base::OnceClosure closure, - absl::optional<::user_data_auth::AddKeyReply> reply) { - std::move(closure).Run(); - }, - run_loop.QuitClosure())); + UserDataAuthClient::Get()->AddAuthFactor( + request, + base::BindOnce( + [](base::OnceClosure closure, + absl::optional<::user_data_auth::AddAuthFactorReply> reply) { + std::move(closure).Run(); + }, + run_loop.QuitClosure())); run_loop.Run(); } // Setup a pin which has policy `auth_locked` true. That means the pin can't // be used for authentication because of the TPM protection. void SetAuthLockedPin(const std::string& pin) const { - ::user_data_auth::AddKeyRequest request; - - const cryptohome::KeyDefinition key_def = - cryptohome::KeyDefinition::CreateForPassword( - pin, KeyLabel(kCryptohomePinLabel), cryptohome::PRIV_MIGRATE); - cryptohome::KeyDefinitionToKey(key_def, request.mutable_key()); - request.mutable_key() - ->mutable_data() - ->mutable_policy() - ->set_low_entropy_credential(true); - *request.mutable_account_id() = - cryptohome::CreateAccountIdentifierFromAccountId(test_account_id_); - // Ensure that has_authorization_request() would return true. - request.mutable_authorization_request(); + ::user_data_auth::AddAuthFactorRequest request; + request.set_auth_session_id(user_context_->GetAuthSessionId()); + request.mutable_auth_factor()->set_type( + ::user_data_auth::AUTH_FACTOR_TYPE_PIN); + request.mutable_auth_factor()->set_label(kCryptohomePinLabel); + request.mutable_auth_factor()->mutable_pin_metadata(); + request.mutable_auth_input()->mutable_pin_input()->set_secret(pin); base::RunLoop run_loop; - UserDataAuthClient::Get()->AddKey( - request, base::BindOnce( - [](base::OnceClosure closure, - absl::optional<::user_data_auth::AddKeyReply> reply) { - std::move(closure).Run(); - }, - run_loop.QuitClosure())); - + UserDataAuthClient::Get()->AddAuthFactor( + request, + base::BindOnce( + [](base::OnceClosure closure, + absl::optional<::user_data_auth::AddAuthFactorReply> reply) { + std::move(closure).Run(); + }, + run_loop.QuitClosure())); run_loop.Run(); + FakeUserDataAuthClient::TestApi::Get()->SetPinLocked( cryptohome::CreateAccountIdentifierFromAccountId(test_account_id_), kCryptohomePinLabel, true);
diff --git a/chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h b/chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h index 4aedbc9..02e4dcb 100644 --- a/chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h +++ b/chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h
@@ -7,7 +7,7 @@ #include "base/memory/singleton.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h" -#include "chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h" +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" #include "components/account_id/account_id.h" class Profile;
diff --git a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc index 2d30f53..1c1217f 100644 --- a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc +++ b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc
@@ -7,15 +7,20 @@ #include "ash/components/arc/arc_prefs.h" #include "ash/components/arc/arc_util.h" #include "ash/components/arc/session/arc_vm_data_migration_status.h" +#include "base/logging.h" #include "base/notreached.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chromeos/ash/components/dbus/spaced/spaced_client.h" #include "components/prefs/pref_service.h" namespace ash { namespace { +constexpr char kPathToCheckFreeDiskSpace[] = "/home/chronos/user"; +constexpr int64_t kMinimumFreeDiskSpaceForMigration = 1LL << 30; // 1 GB. + constexpr char kUserActionSkip[] = "skip"; constexpr char kUserActionUpdate[] = "update"; @@ -32,15 +37,18 @@ ArcVmDataMigrationScreen::~ArcVmDataMigrationScreen() = default; void ArcVmDataMigrationScreen::ShowImpl() { + if (!view_) { + return; + } + // The migration screen is shown after a session restart with an ARC-enabled // login user, and thus the primary profile is available at this point. profile_ = ProfileManager::GetPrimaryUserProfile(); DCHECK(profile_); + + view_->Show(); + // TODO(b/258278176): Stop stale ARCVM and Upstart jobs while loading. SetUpInitialView(); - // TODO(b/258278176): Stop stale ARCVM and Upstart jobs before calling Show(). - if (view_) { - view_->Show(); - } } void ArcVmDataMigrationScreen::HideImpl() {} @@ -58,7 +66,7 @@ } void ArcVmDataMigrationScreen::SetUpInitialView() { - // TODO(b/258278176): Check free disk space and battery state. + // TODO(b/258278176): Check battery state. arc::ArcVmDataMigrationStatus data_migration_status = arc::GetArcVmDataMigrationStatus(profile_->GetPrefs()); switch (data_migration_status) { @@ -68,7 +76,11 @@ // started. arc::SetArcVmDataMigrationStatus( profile_->GetPrefs(), arc::ArcVmDataMigrationStatus::kNotified); - UpdateUIState(ArcVmDataMigrationScreenView::UIState::kWelcome); + DCHECK(ash::SpacedClient::Get()); + ash::SpacedClient::Get()->GetFreeDiskSpace( + kPathToCheckFreeDiskSpace, + base::BindOnce(&ArcVmDataMigrationScreen::OnGetFreeDiskSpace, + weak_ptr_factory_.GetWeakPtr())); break; case arc::ArcVmDataMigrationStatus::kStarted: // TODO(b/258278176): Show the resume screen. @@ -80,6 +92,27 @@ } } +void ArcVmDataMigrationScreen::OnGetFreeDiskSpace( + absl::optional<int64_t> reply) { + if (!reply.has_value() || reply.value() < 0) { + LOG(ERROR) << "Failed to get free disk space from spaced"; + HandleFatalError(); + return; + } + + if (!view_) { + return; + } + + const int64_t free_disk_space = reply.value(); + VLOG(1) << "Free disk space is " << free_disk_space; + if (free_disk_space < kMinimumFreeDiskSpaceForMigration) { + view_->SetRequiredFreeDiskSpace(kMinimumFreeDiskSpaceForMigration); + } + + UpdateUIState(ArcVmDataMigrationScreenView::UIState::kWelcome); +} + void ArcVmDataMigrationScreen::UpdateUIState( ArcVmDataMigrationScreenView::UIState state) { if (view_) { @@ -98,4 +131,9 @@ NOTIMPLEMENTED(); } +void ArcVmDataMigrationScreen::HandleFatalError() { + // TODO(b/258278176): Show a fatal error screen and report the reason. + chrome::AttemptRelaunch(); +} + } // namespace ash
diff --git a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h index 428f142..5e901634 100644 --- a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h +++ b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h
@@ -9,6 +9,7 @@ #include "chrome/browser/ash/login/screens/base_screen.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { @@ -28,11 +29,15 @@ void SetUpInitialView(); + void OnGetFreeDiskSpace(absl::optional<int64_t> reply); + void UpdateUIState(ArcVmDataMigrationScreenView::UIState state); void HandleSkip(); void HandleUpdate(); + void HandleFatalError(); + Profile* profile_; base::WeakPtr<ArcVmDataMigrationScreenView> view_;
diff --git a/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.cc b/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.cc index 53facc24..fd728942 100644 --- a/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.cc +++ b/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.cc
@@ -88,13 +88,13 @@ } void CryptohomeRecoverySetupScreen::OnRecoveryConfigured( - auth::RecoveryFactorEditor::ConfigureResult result) { + auth::mojom::ConfigureResult result) { switch (result) { - case auth::RecoveryFactorEditor::ConfigureResult::kSuccess: + case auth::mojom::ConfigureResult::kSuccess: ExitScreen(*context(), Result::DONE); break; - case auth::RecoveryFactorEditor::ConfigureResult::kInvalidTokenError: - case auth::RecoveryFactorEditor::ConfigureResult::kClientError: + case auth::mojom::ConfigureResult::kInvalidTokenError: + case auth::mojom::ConfigureResult::kFatalError: LOG(ERROR) << "Failed to setup recovery factor, result " << static_cast<int>(result); ExitScreen(*context(), Result::SKIPPED);
diff --git a/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.h b/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.h index 8e37d5d2..da13588 100644 --- a/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.h +++ b/chrome/browser/ash/login/screens/cryptohome_recovery_setup_screen.h
@@ -47,7 +47,7 @@ private: void ExitScreen(WizardContext& wizard_context, Result result); - void OnRecoveryConfigured(auth::RecoveryFactorEditor::ConfigureResult result); + void OnRecoveryConfigured(auth::mojom::ConfigureResult result); base::WeakPtr<CryptohomeRecoverySetupScreenView> view_ = nullptr; ScreenExitCallback exit_callback_; base::WeakPtrFactory<CryptohomeRecoverySetupScreen> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/login/screens/user_selection_screen.cc b/chrome/browser/ash/login/screens/user_selection_screen.cc index 526e6d37..75125178 100644 --- a/chrome/browser/ash/login/screens/user_selection_screen.cc +++ b/chrome/browser/ash/login/screens/user_selection_screen.cc
@@ -56,6 +56,7 @@ #include "chromeos/dbus/tpm_manager/tpm_manager_client.h" #include "components/account_id/account_id.h" #include "components/prefs/pref_service.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_type.h" @@ -224,8 +225,9 @@ // If the user may be enterprise-managed, don't display the banner, because // migration may be blocked by user policy (and user policy is not available // at this time yet). - if (!policy::BrowserPolicyConnector::IsNonEnterpriseUser( - account_id.GetUserEmail())) { + if (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_id.GetUserEmail()) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus::kUnknown) { UpdateUI(account_id, false); return; }
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc index ec68a7b..cf4c756f 100644 --- a/chrome/browser/ash/login/wizard_controller.cc +++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -1754,8 +1754,7 @@ // Restart to make the login page pick up the policy changes resulting from // enrollment recovery. (Not pretty, but this codepath is rarely exercised.) if (prescribed_enrollment_config_.mode == - policy::EnrollmentConfig::MODE_RECOVERY || - IsRollbackFlow(*wizard_context_)) { + policy::EnrollmentConfig::MODE_RECOVERY) { LOG(WARNING) << "Restart Chrome to pick up the policy changes"; EnrollmentScreen* screen = EnrollmentScreen::Get(screen_manager()); screen->OnBrowserRestart();
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc index 800e2cb..e82088f 100644 --- a/chrome/browser/ash/login/wizard_controller_browsertest.cc +++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -3156,22 +3156,6 @@ FakeRollbackNetworkConfig* network_config_; }; -IN_PROC_BROWSER_TEST_F(WizardControllerRollbackFlowTest, - RestartChromeAfterRollbackEnrollment) { - base::RunLoop run_loop; - auto subscription = - browser_shutdown::AddAppTerminatingCallback(run_loop.QuitClosure()); - - CheckCurrentScreen(WelcomeView::kScreenId); - EXPECT_CALL(*mock_enrollment_screen_, ShowImpl()).Times(1); - EXPECT_CALL(*mock_welcome_screen_, HideImpl()).Times(1); - WizardController::default_controller()->AdvanceToScreen( - EnrollmentScreenView::kScreenId); - CheckCurrentScreen(EnrollmentScreenView::kScreenId); - mock_enrollment_screen_->ExitScreen(EnrollmentScreen::Result::COMPLETED); - run_loop.Run(); -} - // TODO(crbug.com/1324410): Disabled due to flakiness. IN_PROC_BROWSER_TEST_F(WizardControllerRollbackFlowTest, DISABLED_SkipEnrollmentAfterRollback) {
diff --git a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc index 00b28df..3648537b 100644 --- a/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc +++ b/chrome/browser/ash/policy/active_directory/active_directory_migration_manager.cc
@@ -185,8 +185,10 @@ local_state_->SetTime(prefs::kLastChromadMigrationAttemptTime, base::Time::Now()); - // Unsigned remote powerwash requests are allowed in AD mode. - ash::SessionManagerClient::Get()->StartRemoteDeviceWipe(em::SignedData()); + // Unsigned remote powerwash requests and em::PolicyFetchRequest::NONE + // signature type are allowed in AD mode. + ash::SessionManagerClient::Get()->StartRemoteDeviceWipe( + em::SignedData(), em::PolicyFetchRequest::NONE); } void ActiveDirectoryMigrationManager::MaybeRunStatusCallback(bool started,
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc index 4faa884..7227e1c 100644 --- a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc +++ b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc
@@ -22,10 +22,10 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" @@ -59,7 +59,8 @@ ~UserCloudPolicyManagerTest() override = default; void TearDown() override { - BrowserPolicyConnector::SetNonEnterpriseDomainForTesting(nullptr); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting( + nullptr); MixinBasedInProcessBrowserTest::TearDown(); } @@ -174,9 +175,12 @@ // Recognize example.com as non-enterprise account. We don't use any // available public domain such as gmail.com in order to prevent possible // leak of verification keys/signatures. - BrowserPolicyConnector::SetNonEnterpriseDomainForTesting("example.com"); - EXPECT_TRUE(BrowserPolicyConnector::IsNonEnterpriseUser( - logged_in_user_mixin_.GetAccountId().GetUserEmail())); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting( + "example.com"); + EXPECT_EQ(signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + logged_in_user_mixin_.GetAccountId().GetUserEmail()), + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise); user_manager::KnownUser known_user(g_browser_process->local_state()); // If a user signs in with a known non-enterprise account there should be no // policy. @@ -195,9 +199,12 @@ using UserCloudPolicyManagerChildTest = UserCloudPolicyManagerTest; IN_PROC_BROWSER_TEST_P(UserCloudPolicyManagerChildTest, PolicyForChildUser) { - BrowserPolicyConnector::SetNonEnterpriseDomainForTesting("example.com"); - EXPECT_TRUE(BrowserPolicyConnector::IsNonEnterpriseUser( - logged_in_user_mixin_.GetAccountId().GetUserEmail())); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting( + "example.com"); + EXPECT_EQ(signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + logged_in_user_mixin_.GetAccountId().GetUserEmail()), + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise); user_manager::KnownUser known_user(g_browser_process->local_state()); // If a user signs in with a known non-enterprise account there should be no @@ -227,9 +234,12 @@ IN_PROC_BROWSER_TEST_P(UserCloudPolicyManagerChildTest, PolicyForChildUserMissing) { user_manager::KnownUser known_user(g_browser_process->local_state()); - BrowserPolicyConnector::SetNonEnterpriseDomainForTesting("example.com"); - EXPECT_TRUE(BrowserPolicyConnector::IsNonEnterpriseUser( - logged_in_user_mixin_.GetAccountId().GetUserEmail())); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting( + "example.com"); + EXPECT_EQ(signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + logged_in_user_mixin_.GetAccountId().GetUserEmail()), + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise); // If a user signs in with a known non-enterprise account there should be no // policy in case user type is child.
diff --git a/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc b/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc index fdb357e..22f8373 100644 --- a/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc +++ b/chrome/browser/ash/policy/core/user_policy_manager_builder_ash.cc
@@ -36,11 +36,11 @@ #include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h" #include "chromeos/ash/components/install_attributes/install_attributes.h" #include "chromeos/dbus/constants/dbus_paths.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/cloud_external_data_manager.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/configuration_policy_provider.h" #include "components/policy/policy_constants.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" @@ -118,7 +118,10 @@ // All other user types do not have user policy. const AccountId& account_id = user->GetAccountId(); if (user->GetType() != user_manager::USER_TYPE_CHILD && - BrowserPolicyConnector::IsNonEnterpriseUser(account_id.GetUserEmail())) { + signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_id.GetUserEmail()) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise) { DLOG(WARNING) << "No policy loaded for known non-enterprise user"; // Mark this profile as not requiring policy. known_user.SetProfileRequiresPolicy( @@ -286,7 +289,9 @@ ash::CrosSettings::Get()->IsUserAllowlisted( account_id.GetUserEmail(), &wildcard_match, user->GetType()) && wildcard_match && - !connector->IsNonEnterpriseUser(account_id.GetUserEmail())) { + signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_id.GetUserEmail()) == signin::AccountManagedStatusFinder:: + EmailEnterpriseStatus::kUnknown) { manager->EnableWildcardLoginCheck(account_id.GetUserEmail()); }
diff --git a/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.cc b/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.cc deleted file mode 100644 index 6b84395..0000000 --- a/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.cc +++ /dev/null
@@ -1,113 +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 "chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h" - -#include <string> -#include <vector> - -#include "base/check.h" -#include "chrome/browser/ash/policy/enrollment/psm/rlwe_client.h" -#include "third_party/private_membership/src/private_membership_rlwe.pb.h" -#include "third_party/shell-encryption/src/statusor.h" - -namespace psm_rlwe = private_membership::rlwe; - -namespace { -// Constants that represent the expected signal data from the server as a -// membership or not. The signal data is inside PirResponse.plaintext_entry_size -// field. -const int kHasMembership = 1; -const int kHasNoMembership = 2; -} // namespace - -namespace policy::psm { - -// static -std::unique_ptr<RlweClient> FakeRlweClient::Create( - const psm_rlwe::RlwePlaintextId& plaintext_id) { - return std::make_unique<FakeRlweClient>( - private_membership::rlwe::RlweUseCase::CROS_DEVICE_STATE, plaintext_id); -} - -FakeRlweClient::~FakeRlweClient() = default; - -::rlwe::StatusOr<psm_rlwe::PrivateMembershipRlweOprfRequest> -FakeRlweClient::CreateOprfRequest() { - psm_rlwe::PrivateMembershipRlweOprfRequest request; - request.set_use_case(use_case_); - - // Send the plaintext ID as the only encrypted ID. - const std::string encrypted_id = plaintext_id_.sensitive_id(); - *request.add_encrypted_ids() = encrypted_id; - - return request; -} - -::rlwe::StatusOr<psm_rlwe::PrivateMembershipRlweQueryRequest> -FakeRlweClient::CreateQueryRequest( - const psm_rlwe::PrivateMembershipRlweOprfResponse& oprf_response) { - psm_rlwe::PrivateMembershipRlweQueryRequest request; - request.set_use_case(use_case_); - - const std::string encrypted_id = - oprf_response.doubly_encrypted_ids(0).queried_encrypted_id(); - - // Check validity of returned queried ID. - if (encrypted_id != plaintext_id_.sensitive_id()) { - return absl::InvalidArgumentError( - "OPRF response contains a response to an erroneous encrypted ID."); - } - - // Send the same encrypted_id again to indicate the validality of the received - // |oprf_response|. - psm_rlwe::PrivateMembershipRlweQuery single_query; - single_query.set_queried_encrypted_id(encrypted_id); - *request.add_queries() = single_query; - - return request; -} - -::rlwe::StatusOr<bool> FakeRlweClient::ProcessQueryResponse( - const psm_rlwe::PrivateMembershipRlweQueryResponse& query_response) { - // Validate that we have an existing response. - if (!query_response.pir_responses_size()) { - return absl::InvalidArgumentError( - "Query response missing a response to a requested ID."); - } - - const auto& pir_response = query_response.pir_responses(0); - const std::string encrypted_id = pir_response.queried_encrypted_id(); - - // Check validity of returned queried ID. - if (encrypted_id != plaintext_id_.sensitive_id()) { - return absl::InvalidArgumentError( - "Query response contains a response to an erroneous encrypted ID."); - } - - // Server should fill out PirResponse message with plaintext_entry_size field - // to indicate the membership response. - const int server_membership_response = - pir_response.pir_response().plaintext_entry_size(); - - // Check validity of the server membership response. - if (server_membership_response != kHasMembership && - server_membership_response != kHasNoMembership) { - return absl::InvalidArgumentError( - "Query response contains unknown membership response to the queried " - "encrypted ID."); - } - - return server_membership_response == kHasMembership; -} - -std::string FakeRlweClient::GetPsmIdentifierDebugString() { - return plaintext_id_.sensitive_id(); -} - -FakeRlweClient::FakeRlweClient(psm_rlwe::RlweUseCase use_case, - const psm_rlwe::RlwePlaintextId& plaintext_id) - : use_case_(use_case), plaintext_id_(plaintext_id) {} - -} // namespace policy::psm
diff --git a/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h b/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h deleted file mode 100644 index 4e3cba9..0000000 --- a/chrome/browser/ash/policy/enrollment/psm/fake_rlwe_client.h +++ /dev/null
@@ -1,43 +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 CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_FAKE_RLWE_CLIENT_H_ -#define CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_FAKE_RLWE_CLIENT_H_ - -#include "chrome/browser/ash/policy/enrollment/psm/rlwe_client.h" - -#include <string> -#include <vector> - -#include "third_party/private_membership/src/private_membership_rlwe.pb.h" -#include "third_party/shell-encryption/src/statusor.h" - -namespace policy::psm { - -class FakeRlweClient : public RlweClient { - public: - // Creates a fake PSM RLWE client for testing purposes. - static std::unique_ptr<RlweClient> Create(const PlaintextId& plaintext_id); - - FakeRlweClient(UseCase use_case, const PlaintextId& plaintext_id); - FakeRlweClient(const FakeRlweClient&) = delete; - FakeRlweClient& operator=(const FakeRlweClient&) = delete; - ~FakeRlweClient() override; - - // Mocks all function calls of RlweClient. - ::rlwe::StatusOr<OprfRequest> CreateOprfRequest() override; - ::rlwe::StatusOr<QueryRequest> CreateQueryRequest( - const OprfResponse& oprf_response) override; - ::rlwe::StatusOr<bool> ProcessQueryResponse( - const QueryResponse& query_response) override; - std::string GetPsmIdentifierDebugString() override; - - private: - const UseCase use_case_; - const PlaintextId plaintext_id_; -}; - -} // namespace policy::psm - -#endif // CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_FAKE_RLWE_CLIENT_H_
diff --git a/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.cc b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.cc new file mode 100644 index 0000000..01aff8a --- /dev/null +++ b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.cc
@@ -0,0 +1,86 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h" + +#include <memory> +#include <string> + +#include "base/check.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/threading/thread_restrictions.h" +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_client_impl.h" +#include "components/policy/proto/device_management_backend.pb.h" +#include "third_party/private_membership/src/internal/testing/regression_test_data/regression_test_data.pb.h" +#include "third_party/private_membership/src/private_membership_rlwe_client.h" + +namespace em = enterprise_management; +using RlweTestData = + private_membership::rlwe::PrivateMembershipRlweClientRegressionTestData; + +namespace policy::psm::testing { + +namespace { + +std::unique_ptr<RlweClient> CreateRlweClient( + const RlweTestCase& test_case, + const private_membership::rlwe::RlwePlaintextId& /* unused*/) { + auto status_or_client = + private_membership::rlwe::PrivateMembershipRlweClient::CreateForTesting( + private_membership::rlwe::RlweUseCase::CROS_DEVICE_STATE, + {test_case.plaintext_id()}, test_case.ec_cipher_key(), + test_case.seed()); // IN-TEST + CHECK(status_or_client.ok()) << status_or_client.status().message(); + + return std::make_unique<RlweClientImpl>(std::move(status_or_client).value(), + test_case.plaintext_id()); +} + +RlweTestData ReadTestData() { + base::FilePath src_root_dir; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_root_dir)); + const base::FilePath path_to_test_data = + src_root_dir.AppendASCII("third_party") + .AppendASCII("private_membership") + .AppendASCII("src") + .AppendASCII("internal") + .AppendASCII("testing") + .AppendASCII("regression_test_data") + .AppendASCII("test_data.binarypb"); + + base::ScopedAllowBlockingForTesting allow_blocking; + CHECK(base::PathExists(path_to_test_data)) + << " path_to_test_data: " << path_to_test_data; + + std::string serialized_test_data; + CHECK(base::ReadFileToString(path_to_test_data, &serialized_test_data)); + + RlweTestData test_data; + CHECK(test_data.ParseFromString(serialized_test_data)); + + return test_data; +} + +} // namespace + +RlweTestCase LoadTestCase(bool is_member) { + const auto test_data = ReadTestData(); + + for (const auto& test_case : test_data.test_cases()) { + if (test_case.is_positive_membership_expected() == is_member) { + return test_case; + } + } + + CHECK(false) << "Could not find psm test data for is_member == " << is_member; + return {}; +} + +RlweClientFactory CreateClientFactory(bool is_member) { + return base::BindRepeating(&CreateRlweClient, LoadTestCase(is_member)); +} + +} // namespace policy::psm::testing
diff --git a/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h new file mode 100644 index 0000000..529a916 --- /dev/null +++ b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h
@@ -0,0 +1,44 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_RLWE_TEST_SUPPORT_H_ +#define CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_RLWE_TEST_SUPPORT_H_ + +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_client.h" + +#include <memory> + +#include "base/functional/callback.h" +#include "third_party/private_membership/src/internal/testing/regression_test_data/regression_test_data.pb.h" + +namespace private_membership::rlwe { +class RlwePlaintextId; +} // namespace private_membership::rlwe + +namespace policy::psm::testing { + +using RlweTestCase = private_membership::rlwe:: + PrivateMembershipRlweClientRegressionTestData::TestCase; + +using RlweClientFactory = base::RepeatingCallback<std::unique_ptr<RlweClient>( + const private_membership::rlwe::RlwePlaintextId&)>; + +// Load a test case from the test database provided by the +// third_party/private_membership library. These can be used to simulate PSM +// requests for members or non-members of the set. +// +// Note that this function performs a blocking file read. +RlweTestCase LoadTestCase(bool is_member); + +// Load a test case from the test database provided by the +// third_party/private_membership library. Based on that test case, +// create a callback as needed by the `AutoEnrollmentController` to create an +// `RlweClient`. The returned callback will ignore the plaintext id and +// instead create an `RlweClient` that will create requests as expected by the +// EmbeddedPolicyTestServer. +RlweClientFactory CreateClientFactory(bool is_member = true); + +} // namespace policy::psm::testing + +#endif // CHROME_BROWSER_ASH_POLICY_ENROLLMENT_PSM_RLWE_TEST_SUPPORT_H_
diff --git a/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support_unittest.cc b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support_unittest.cc new file mode 100644 index 0000000..b7f77ca --- /dev/null +++ b/chrome/browser/ash/policy/enrollment/psm/rlwe_test_support_unittest.cc
@@ -0,0 +1,46 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/policy/enrollment/psm/rlwe_test_support.h" + +#include "device_management_backend.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +class RlweTestSupportTest + : public testing::Test, + public testing::WithParamInterface</*is_member*/ bool> {}; + +// Test that the RlweClient created via CreateClientFactory matches the +// RlweTestCase loaded vid LoadTestCase. +TEST_P(RlweTestSupportTest, CaseMatchesFactory) { + const bool is_member = GetParam(); + const auto test_case = psm::testing::LoadTestCase(is_member); + auto rlwe_client = psm::testing::CreateClientFactory(is_member).Run( + private_membership::rlwe::RlwePlaintextId()); + + // Verify that the expected membership matches the test parameter. + EXPECT_EQ(test_case.is_positive_membership_expected(), is_member); + + // Create and compare OPRF request. + const auto status_or_orpf = rlwe_client->CreateOprfRequest(); + ASSERT_TRUE(status_or_orpf.ok()); + EXPECT_EQ(status_or_orpf.value().SerializeAsString(), + test_case.expected_oprf_request().SerializeAsString()); + + // Create and compare Query request. + // This also test that the OPRF response meets the RlweClient's expectations. + const auto status_or_query = + rlwe_client->CreateQueryRequest(test_case.oprf_response()); + ASSERT_TRUE(status_or_query.ok()); + EXPECT_EQ(status_or_query.value().SerializeAsString(), + test_case.expected_query_request().SerializeAsString()); +} + +INSTANTIATE_TEST_SUITE_P(RlweTestSupportTestSuite, + RlweTestSupportTest, + /* is_member*/ testing::Bool()); + +} // namespace policy
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc index e92dc5a..f2f458d7 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_remote_powerwash_job.cc
@@ -29,7 +29,8 @@ constexpr base::TimeDelta kFailsafeTimerTimeout = base::Seconds(10); void StartPowerwash(enterprise_management::SignedData signed_command) { - ash::SessionManagerClient::Get()->StartRemoteDeviceWipe(signed_command); + ash::SessionManagerClient::Get()->StartRemoteDeviceWipe( + signed_command, enterprise_management::PolicyFetchRequest::SHA1_RSA); } } // namespace
diff --git a/chrome/browser/ash/system/timezone_resolver_manager.cc b/chrome/browser/ash/system/timezone_resolver_manager.cc index 317a7870..9813c329 100644 --- a/chrome/browser/ash/system/timezone_resolver_manager.cc +++ b/chrome/browser/ash/system/timezone_resolver_manager.cc
@@ -143,29 +143,83 @@ } bool TimeZoneResolverManager::ShouldSendWiFiGeolocationData() { - int timezone_setting = GetTimezoneManagementSetting(); - return ( - (timezone_setting == - enterprise_management::SystemTimezoneProto::SEND_WIFI_ACCESS_POINTS) || - (timezone_setting == - enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO)); + // Managed user case, check cloud policies for automatic time zone. + if (IsTimeZoneResolutionPolicyControlled()) { + switch (GetEffectiveAutomaticTimezoneManagementSetting()) { + case enterprise_management::SystemTimezoneProto::SEND_WIFI_ACCESS_POINTS: + return true; + case enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO: + return true; + case enterprise_management::SystemTimezoneProto::USERS_DECIDE: + // Same as regular user flow, continue processing below. + break; + default: + return false; + } + } + + // Regular user case (also USERS_DECIDE case for managed). + // Automatic time zone setting is an user configurable option, applying + // the primary user's choice to the entire session. + // primary_user_prefs_ indicates if the user has signed in or not. + if (primary_user_prefs_) { + switch (GetEffectiveUserTimeZoneResolveMethod(primary_user_prefs_, + /*check_policy=*/false)) { + case TimeZoneResolveMethod::SEND_WIFI_ACCESS_POINTS: + return true; + case TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO: + return true; + default: + return false; + } + } + + // Precise location is disabled on log-in screen. + return false; } bool TimeZoneResolverManager::ShouldSendCellularGeolocationData() { - return (GetTimezoneManagementSetting() == - enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO); + // Managed user case, check cloud policies for automatic time zone. + if (IsTimeZoneResolutionPolicyControlled()) { + switch (GetEffectiveAutomaticTimezoneManagementSetting()) { + case enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO: + return true; + case enterprise_management::SystemTimezoneProto::USERS_DECIDE: + // Same as regular user flow, continue processing below. + break; + default: + return false; + } + } + + // Regular user case (also USERS_DECIDE case for managed). + // Automatic time zone setting is an user configurable option, applying + // the primary user's choice to the entire session. + // primary_user_prefs_ indicates if the has user signed in or not. + if (primary_user_prefs_) { + return GetEffectiveUserTimeZoneResolveMethod(primary_user_prefs_, + /*check_policy=*/false) == + TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO; + } + + // Precise location is disabled on log-in screen. + return false; } -int TimeZoneResolverManager::GetTimezoneManagementSetting() { - PrefService* local_state = g_browser_process->local_state(); - const bool is_managed = local_state->IsManagedPreference( +// static +int TimeZoneResolverManager::GetEffectiveAutomaticTimezoneManagementSetting() { + // Regular users choose automatic time zone method themselves. + if (!IsTimeZoneResolutionPolicyControlled()) { + return enterprise_management::SystemTimezoneProto::USERS_DECIDE; + } + + // Static time zone policy overrides automatic. + if (HasSystemTimezonePolicy()) { + return enterprise_management::SystemTimezoneProto::DISABLED; + } + + int policy_value = g_browser_process->local_state()->GetInteger( prefs::kSystemTimezoneAutomaticDetectionPolicy); - if (!is_managed) - return false; - - int policy_value = - local_state->GetInteger(prefs::kSystemTimezoneAutomaticDetectionPolicy); - DCHECK(policy_value <= enterprise_management::SystemTimezoneProto:: AutomaticTimezoneDetectionType_MAX); @@ -251,33 +305,22 @@ const PrefService* user_prefs, bool check_policy) { if (check_policy) { - if (HasSystemTimezonePolicy()) - return TimeZoneResolveMethod::DISABLED; - - PrefService* local_state = g_browser_process->local_state(); - const bool is_managed = local_state->IsManagedPreference( - prefs::kSystemTimezoneAutomaticDetectionPolicy); - if (is_managed) { - int policy_value = local_state->GetInteger( - prefs::kSystemTimezoneAutomaticDetectionPolicy); - - switch (policy_value) { - case enterprise_management::SystemTimezoneProto::USERS_DECIDE: - // Follow user preference. - break; - case enterprise_management::SystemTimezoneProto::DISABLED: - return TimeZoneResolveMethod::DISABLED; - case enterprise_management::SystemTimezoneProto::IP_ONLY: - return TimeZoneResolveMethod::IP_ONLY; - case enterprise_management::SystemTimezoneProto:: - SEND_WIFI_ACCESS_POINTS: - return TimeZoneResolveMethod::SEND_WIFI_ACCESS_POINTS; - case enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO: - return TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO; - default: - NOTREACHED(); - return TimeZoneResolveMethod::DISABLED; - } + int policy_value = GetEffectiveAutomaticTimezoneManagementSetting(); + switch (policy_value) { + case enterprise_management::SystemTimezoneProto::USERS_DECIDE: + // Follow user preference. + break; + case enterprise_management::SystemTimezoneProto::DISABLED: + return TimeZoneResolveMethod::DISABLED; + case enterprise_management::SystemTimezoneProto::IP_ONLY: + return TimeZoneResolveMethod::IP_ONLY; + case enterprise_management::SystemTimezoneProto::SEND_WIFI_ACCESS_POINTS: + return TimeZoneResolveMethod::SEND_WIFI_ACCESS_POINTS; + case enterprise_management::SystemTimezoneProto::SEND_ALL_LOCATION_INFO: + return TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO; + default: + NOTREACHED(); + return TimeZoneResolveMethod::DISABLED; } } if (user_prefs->GetBoolean(
diff --git a/chrome/browser/ash/system/timezone_resolver_manager.h b/chrome/browser/ash/system/timezone_resolver_manager.h index c9681a54..b3f50dc7 100644 --- a/chrome/browser/ash/system/timezone_resolver_manager.h +++ b/chrome/browser/ash/system/timezone_resolver_manager.h
@@ -87,7 +87,12 @@ static bool IfServiceShouldBeRunningForSigninScreen(); private: - int GetTimezoneManagementSetting(); + // Return the effective policy value for automatic time zone resolution. + // If static timezone policy is present returns + // enterprise_management::SystemTimezoneProto::DISABLED. + // For regular users returns + // enterprise_management::SystemTimezoneProto::USERS_DECIDE. + static int GetEffectiveAutomaticTimezoneManagementSetting(); // Local State initialization observer. void OnLocalStateInitialized(bool initialized);
diff --git a/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc b/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc new file mode 100644 index 0000000..11e60c8 --- /dev/null +++ b/chrome/browser/ash/system/timezone_resolver_manager_browsertest.cc
@@ -0,0 +1,321 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/system/timezone_resolver_manager.h" + +#include "ash/constants/ash_switches.h" +#include "chrome/browser/ash/login/login_manager_test.h" +#include "chrome/browser/ash/login/test/device_state_mixin.h" +#include "chrome/browser/ash/login/test/embedded_policy_test_server_mixin.h" +#include "chrome/browser/ash/login/test/login_manager_mixin.h" +#include "chrome/browser/ash/login/ui/user_adding_screen.h" +#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h" +#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" +#include "chrome/browser/ash/settings/stub_cros_settings_provider.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part_ash.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/pref_names.h" +#include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/settings/cros_settings_names.h" +#include "components/account_id/account_id.h" +#include "components/policy/proto/chrome_device_policy.pb.h" +#include "components/prefs/pref_service.h" +#include "content/public/test/browser_test.h" + +namespace ash { + +namespace em = enterprise_management; + +namespace { + +static constexpr std::array< + em::SystemTimezoneProto::AutomaticTimezoneDetectionType, + 5> + kTimeZoneAutomaticDetectionCloudPolicies = { + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_USERS_DECIDE, + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_DISABLED, + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_IP_ONLY, + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_SEND_WIFI_ACCESS_POINTS, + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_SEND_ALL_LOCATION_INFO}; + +constexpr std::array<system::TimeZoneResolverManager::TimeZoneResolveMethod, 4> + kUserTimeZoneAutomaticDetectionUserChoices = { + system::TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED, + system::TimeZoneResolverManager::TimeZoneResolveMethod::IP_ONLY, + system::TimeZoneResolverManager::TimeZoneResolveMethod:: + SEND_WIFI_ACCESS_POINTS, + system::TimeZoneResolverManager::TimeZoneResolveMethod:: + SEND_ALL_LOCATION_INFO, +}; + +} // namespace + +class TimeZoneResolverManagerTest : public LoginManagerTest { + public: + TimeZoneResolverManagerTest() { + login_manager_.AppendManagedUsers(1); + login_manager_.AppendRegularUsers(2); + + managed_user_id_ = login_manager_.users()[0].account_id; + regular_primary_user_id_ = login_manager_.users()[1].account_id; + regular_secondary_user_id_ = login_manager_.users()[2].account_id; + } + + ~TimeZoneResolverManagerTest() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + // This is needed so that tests don't need to mock our policy + // infrastructure. When settings this, profile initialization will not fail, + // because of policies. + command_line->AppendSwitch(switches::kAllowFailedPolicyFetchForTest); + LoginManagerTest::SetUpCommandLine(command_line); + } + + // Set the cloud policy for automatic time zone detection and wait until it's + // propagated to the local state. + void SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType detection_type) { + // Override the cloud policy for automatic time zone detection to the given + // value. + device_policy_builder_.SetDefaultSigningKey(); + device_policy_builder_.payload() + .mutable_system_timezone() + ->set_timezone_detection_type(detection_type); + device_policy_builder_.Build(); + policy_test_server_mixin_.UpdateDevicePolicy( + device_policy_builder_.payload()); + + // Simulating a policy fetch. + ash::FakeSessionManagerClient::Get()->set_device_policy( + device_policy_builder_.GetBlob()); + ash::FakeSessionManagerClient::Get()->OnPropertyChangeComplete(true); + + // Wait for the policy value to get propagated. + policy::LocalStateValueWaiter( + prefs::kSystemTimezoneAutomaticDetectionPolicy, + base::Value(detection_type)) + .Wait(); + } + + // Static policy overrides automatic detection policy + void SetDeviceTimeZoneStaticPolicy(const std::string& value) { + cros_settings_.device_settings()->SetString(kSystemTimezonePolicy, value); + } + + void SetUserTimeZoneResolveMethod( + PrefService* pref_service, + system::TimeZoneResolverManager::TimeZoneResolveMethod method) { + // The way the automatic time zone is implemented today is that we have 2 + // user preferences. kResolveTimezoneByGeolocationMigratedToMethod - marked + // to true, when user first interacts with the automatic time zone setting. + // kResolveTimezoneByGeolocationMethod - storing the user choice, whether + // they want to use coarse (IP-based) or precise (Wi-Fi and Cellular-based) + // location. + if (!pref_service->GetBoolean( + ::prefs::kResolveTimezoneByGeolocationMigratedToMethod)) { + pref_service->SetBoolean( + ::prefs::kResolveTimezoneByGeolocationMigratedToMethod, true); + } + + pref_service->SetInteger(::prefs::kResolveTimezoneByGeolocationMethod, + static_cast<int>(method)); + } + + protected: + AccountId managed_user_id_; + AccountId regular_primary_user_id_; + AccountId regular_secondary_user_id_; + + DeviceStateMixin device_state_{ + &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; + ash::EmbeddedPolicyTestServerMixin policy_test_server_mixin_{&mixin_host_}; + LoginManagerMixin login_manager_{&mixin_host_}; + + ScopedTestingCrosSettings cros_settings_; + policy::DevicePolicyBuilder device_policy_builder_; +}; + +IN_PROC_BROWSER_TEST_F(TimeZoneResolverManagerTest, RegularUser) { + ash::system::TimeZoneResolverManager* tz_resolver_manager = + g_browser_process->platform_part()->GetTimezoneResolverManager(); + + // Log in a user. + LoginUser(regular_primary_user_id_); + base::RunLoop().RunUntilIdle(); + PrefService* pref_service = + g_browser_process->profile_manager()->GetActiveUserProfile()->GetPrefs(); + + // Check that all user options for automatic timezone is working correctly: + SetUserTimeZoneResolveMethod( + pref_service, + system::TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + SetUserTimeZoneResolveMethod( + pref_service, + system::TimeZoneResolverManager::TimeZoneResolveMethod::IP_ONLY); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + SetUserTimeZoneResolveMethod( + pref_service, system::TimeZoneResolverManager::TimeZoneResolveMethod:: + SEND_WIFI_ACCESS_POINTS); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + SetUserTimeZoneResolveMethod( + pref_service, system::TimeZoneResolverManager::TimeZoneResolveMethod:: + SEND_ALL_LOCATION_INFO); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_TRUE(tz_resolver_manager->ShouldSendCellularGeolocationData()); +} + +IN_PROC_BROWSER_TEST_F(TimeZoneResolverManagerTest, RegularMultiUser) { + ash::system::TimeZoneResolverManager* tz_resolver_manager = + g_browser_process->platform_part()->GetTimezoneResolverManager(); + + // Log in primary user. + LoginUser(regular_primary_user_id_); + base::RunLoop().RunUntilIdle(); + PrefService* primary_pref_service = + g_browser_process->profile_manager()->GetActiveUserProfile()->GetPrefs(); + + // Add secondary user and log in. + ash::UserAddingScreen::Get()->Start(); + AddUser(regular_secondary_user_id_); + base::RunLoop().RunUntilIdle(); + + // Check that primary user's choice for time zone detection method is + // overriding secondary user's choice. Checking all configurations: + PrefService* secondary_pref_service = + g_browser_process->profile_manager()->GetActiveUserProfile()->GetPrefs(); + SetUserTimeZoneResolveMethod( + primary_pref_service, + system::TimeZoneResolverManager::TimeZoneResolveMethod::DISABLED); + for (auto tz_choice : kUserTimeZoneAutomaticDetectionUserChoices) { + SetUserTimeZoneResolveMethod(secondary_pref_service, tz_choice); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } + + SetUserTimeZoneResolveMethod( + primary_pref_service, + system::TimeZoneResolverManager::TimeZoneResolveMethod::IP_ONLY); + for (auto tz_choice : kUserTimeZoneAutomaticDetectionUserChoices) { + SetUserTimeZoneResolveMethod(secondary_pref_service, tz_choice); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } + + SetUserTimeZoneResolveMethod( + primary_pref_service, system::TimeZoneResolverManager:: + TimeZoneResolveMethod::SEND_WIFI_ACCESS_POINTS); + for (auto tz_choice : kUserTimeZoneAutomaticDetectionUserChoices) { + SetUserTimeZoneResolveMethod(secondary_pref_service, tz_choice); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } + + SetUserTimeZoneResolveMethod( + primary_pref_service, system::TimeZoneResolverManager:: + TimeZoneResolveMethod::SEND_ALL_LOCATION_INFO); + for (auto tz_choice : kUserTimeZoneAutomaticDetectionUserChoices) { + SetUserTimeZoneResolveMethod(secondary_pref_service, tz_choice); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_TRUE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } +} + +IN_PROC_BROWSER_TEST_F(TimeZoneResolverManagerTest, ManagedUser) { + ash::system::TimeZoneResolverManager* tz_resolver_manager = + g_browser_process->platform_part()->GetTimezoneResolverManager(); + + // Check that on login screen TimeZoneResolverManager is not sending any data + // to Google servers. + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_USERS_DECIDE); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + // Log in a managed user. + LoginUser(managed_user_id_); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + // Disable automatic time zone detection by policy. + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_DISABLED); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + // Set automatic time zone to IP_ONLY. + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_IP_ONLY); + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + // Set automatic time zone to WIFI. + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_SEND_WIFI_ACCESS_POINTS); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + + // Set automatic time zone to ALL_INFO (i.e. Wi-Fi and cellular). + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_SEND_ALL_LOCATION_INFO); + EXPECT_TRUE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_TRUE(tz_resolver_manager->ShouldSendCellularGeolocationData()); +} + +IN_PROC_BROWSER_TEST_F(TimeZoneResolverManagerTest, + ManagedUserStaticTimeZonePolicy) { + // Set static time zone by policy and log in a managed user. + // Static time zone policy overrides automatic time zone policies, + // so no matter what other policies are provided, automatic time zone + // resolution will be prohobited. + SetDeviceTimeZoneStaticPolicy("Europe/Berlin"); + LoginUser(managed_user_id_); + base::RunLoop().RunUntilIdle(); + + // Iterate over all possible automatic time zone policies and check that + // TimeZoneResolverManager is not sending out any sensor data. + ash::system::TimeZoneResolverManager* tz_resolver_manager = + g_browser_process->platform_part()->GetTimezoneResolverManager(); + for (auto tz_policy : kTimeZoneAutomaticDetectionCloudPolicies) { + SetDeviceTimeZoneAutomaticDetectionPolicy(tz_policy); + + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } + + // Iterate over all possible user options in time zone settings and check that + // TimeZoneResolverManager is not sending any sensor data. + SetDeviceTimeZoneAutomaticDetectionPolicy( + em::SystemTimezoneProto::AutomaticTimezoneDetectionType:: + SystemTimezoneProto_AutomaticTimezoneDetectionType_USERS_DECIDE); + PrefService* pref_service = + g_browser_process->profile_manager()->GetActiveUserProfile()->GetPrefs(); + for (auto tz_user_choice : kUserTimeZoneAutomaticDetectionUserChoices) { + SetUserTimeZoneResolveMethod(pref_service, tz_user_choice); + + EXPECT_FALSE(tz_resolver_manager->ShouldSendWiFiGeolocationData()); + EXPECT_FALSE(tz_resolver_manager->ShouldSendCellularGeolocationData()); + } +} + +} // namespace ash
diff --git a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc index 41b406f..d488e887 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc +++ b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
@@ -66,7 +66,7 @@ DCHECK(token.has_value()); absl::optional<base::UnguessableToken> unguessable_token = - base::UnguessableToken::Deserialize2(token->high(), token->low()); + base::UnguessableToken::Deserialize(token->high(), token->low()); return unguessable_token.value(); }
diff --git a/chrome/browser/ash/telemetry_extension/probe_service_converters.cc b/chrome/browser/ash/telemetry_extension/probe_service_converters.cc index aee217a..b610fbde 100644 --- a/chrome/browser/ash/telemetry_extension/probe_service_converters.cc +++ b/chrome/browser/ash/telemetry_extension/probe_service_converters.cc
@@ -426,8 +426,8 @@ crosapi::mojom::ProbeSystemInfoPtr UncheckedConvertPtr( cros_healthd::mojom::OsInfoPtr input) { return crosapi::mojom::ProbeSystemInfo::New(crosapi::mojom::ProbeOsInfo::New( - std::move(input->oem_name), - ConvertProbePtr(std::move(input->os_version)))); + std::move(input->oem_name), ConvertProbePtr(std::move(input->os_version)), + std::move(input->marketing_name))); } crosapi::mojom::ProbeOsVersionPtr UncheckedConvertPtr(
diff --git a/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc b/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc index 39412692..8980a3d 100644 --- a/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc +++ b/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc
@@ -1236,19 +1236,22 @@ constexpr char kBuildNumber[] = "13544"; constexpr char kPatchNumber[] = "59.0"; constexpr char kReleaseChannel[] = "stable-channel"; + constexpr char kMarketingName[] = "Test Marketing Name"; auto os_version = cros_healthd::mojom::OsVersion::New( kReleaseMilestone, kBuildNumber, kPatchNumber, kReleaseChannel); auto input = cros_healthd::mojom::OsInfo::New(); input->oem_name = kOemName; input->os_version = std::move(os_version); + input->marketing_name = kMarketingName; EXPECT_EQ( ConvertProbePtr(std::move(input)), crosapi::mojom::ProbeSystemInfo::New(crosapi::mojom::ProbeOsInfo::New( kOemName, crosapi::mojom::ProbeOsVersion::New(kReleaseMilestone, kBuildNumber, - kPatchNumber, kReleaseChannel)))); + kPatchNumber, kReleaseChannel), + kMarketingName))); } TEST(ProbeServiceConverters, OsVersionPtr) {
diff --git a/chrome/browser/ash/video_conference/video_conference_app_service_client.cc b/chrome/browser/ash/video_conference/video_conference_app_service_client.cc index 89cf5aa..d26f008 100644 --- a/chrome/browser/ash/video_conference/video_conference_app_service_client.cc +++ b/chrome/browser/ash/video_conference/video_conference_app_service_client.cc
@@ -7,6 +7,7 @@ #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "base/containers/contains.h" +#include "base/functional/callback_helpers.h" #include "base/strings/utf_string_conversions.h" #include "base/unguessable_token.h" #include "chrome/browser/apps/app_service/app_service_proxy_ash.h" @@ -153,13 +154,32 @@ } AppState& state = GetOrAddAppState(app_id); + const std::string app_name = GetAppName(app_id); if (update.CameraChanged()) { state.is_capturing_camera = is_capturing_camera; + + if (is_capturing_camera && camera_system_disabled_) { + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->NotifyDeviceUsedWhileDisabled( + crosapi::mojom::VideoConferenceMediaDevice::kCamera, + base::UTF8ToUTF16(app_name), base::DoNothingAs<void(bool)>()); + } } if (update.MicrophoneChanged()) { state.is_capturing_microphone = is_capturing_microphone; + + if (is_capturing_microphone && microphone_system_disabled_) { + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->NotifyDeviceUsedWhileDisabled( + crosapi::mojom::VideoConferenceMediaDevice::kMicrophone, + base::UTF8ToUTF16(app_name), base::DoNothingAs<void(bool)>()); + } } HandleMediaUsageUpdate();
diff --git a/chrome/browser/ash/video_conference/video_conference_app_service_client_browsertest.cc b/chrome/browser/ash/video_conference/video_conference_app_service_client_browsertest.cc index e69b3ecb..16c239cf 100644 --- a/chrome/browser/ash/video_conference/video_conference_app_service_client_browsertest.cc +++ b/chrome/browser/ash/video_conference/video_conference_app_service_client_browsertest.cc
@@ -5,11 +5,15 @@ #include "chrome/browser/ash/video_conference/video_conference_app_service_client.h" #include <cstdlib> +#include <utility> +#include <vector> #include "ash/constants/ash_features.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" +#include "ash/system/video_conference/fake_video_conference_tray_controller.h" #include "ash/system/video_conference/video_conference_media_state.h" +#include "ash/system/video_conference/video_conference_tray_controller.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -263,22 +267,26 @@ EXPECT_FALSE(permission.has_camera_permission); EXPECT_FALSE(permission.has_microphone_permission); - UpdateAppPermision(kAppId1, false, true); + UpdateAppPermision(kAppId1, /*has_camera_permission=*/false, + /*has_microphone_permission=*/true); permission = GetAppPermission(kAppId1); EXPECT_FALSE(permission.has_camera_permission); EXPECT_TRUE(permission.has_microphone_permission); - UpdateAppPermision(kAppId1, true, true); + UpdateAppPermision(kAppId1, /*has_camera_permission=*/true, + /*has_microphone_permission=*/true); permission = GetAppPermission(kAppId1); EXPECT_TRUE(permission.has_camera_permission); EXPECT_TRUE(permission.has_microphone_permission); - UpdateAppPermision(kAppId1, true, false); + UpdateAppPermision(kAppId1, /*has_camera_permission=*/true, + /*has_microphone_permission=*/false); permission = GetAppPermission(kAppId1); EXPECT_TRUE(permission.has_camera_permission); EXPECT_FALSE(permission.has_microphone_permission); - UpdateAppPermision(kAppId1, false, false); + UpdateAppPermision(kAppId1, /*has_camera_permission=*/false, + /*has_microphone_permission=*/false); permission = GetAppPermission(kAppId1); EXPECT_FALSE(permission.has_camera_permission); EXPECT_FALSE(permission.has_microphone_permission); @@ -371,13 +379,15 @@ InstallApp(kAppId2); // no-camera, no-mic should not start a tracking of the app. - SetAppCapabilityAccess(kAppId1, false, false); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/false); EXPECT_TRUE(GetMediaApps().empty()); std::vector<crosapi::mojom::VideoConferenceMediaAppInfoPtr> media_app_info; // has-camera, no-mic should start the tracking of the app. - SetAppCapabilityAccess(kAppId1, true, false); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/false); media_app_info = GetMediaApps(); crosapi::mojom::VideoConferenceMediaAppInfoPtr expected_media_app_info = crosapi::mojom::VideoConferenceMediaAppInfo::New( @@ -391,14 +401,16 @@ EXPECT_TRUE(media_app_info[0].Equals(expected_media_app_info)); // has-camera, has-mic should change the value of GetMediaApps. - SetAppCapabilityAccess(kAppId1, true, true); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); media_app_info = GetMediaApps(); ASSERT_EQ(media_app_info.size(), 1u); expected_media_app_info->is_capturing_microphone = true; EXPECT_TRUE(media_app_info[0].Equals(expected_media_app_info)); // no-camera, has-mic should change the value of GetMediaApps. - SetAppCapabilityAccess(kAppId1, false, true); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/true); media_app_info = GetMediaApps(); ASSERT_EQ(media_app_info.size(), 1u); expected_media_app_info->is_capturing_camera = false; @@ -406,7 +418,8 @@ // no-camera, no-mic should change the value of GetMediaApps; but not removing // the tracking app. - SetAppCapabilityAccess(kAppId1, false, false); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/false); media_app_info = GetMediaApps(); ASSERT_EQ(media_app_info.size(), 1u); expected_media_app_info->is_capturing_microphone = false; @@ -420,7 +433,8 @@ instance1.Start(); // has-camera, has-mic should start tracking of the kAppId1. - SetAppCapabilityAccess(kAppId1, true, true); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); std::vector<crosapi::mojom::VideoConferenceMediaAppInfoPtr> media_app_info; @@ -462,7 +476,8 @@ EXPECT_TRUE(GetMediaApps().empty()); // has-camera, has-mic should start a tracking of the app. - SetAppCapabilityAccess(kAppId1, true, true); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); std::vector<crosapi::mojom::VideoConferenceMediaAppInfoPtr> media_app_info; @@ -500,8 +515,10 @@ // Install two apps with permissions. InstallApp(kAppId1); InstallApp(kAppId2); - UpdateAppPermision(kAppId1, true, false); - UpdateAppPermision(kAppId2, false, true); + UpdateAppPermision(kAppId1, /*has_camera_permission=*/true, + /*has_microphone_permission=*/false); + UpdateAppPermision(kAppId2, /*has_camera_permission=*/false, + /*has_microphone_permission=*/true); // Start two running instance. FakeAppInstance instance1(instance_registry_, kAppId1); @@ -518,7 +535,8 @@ EXPECT_FALSE(state.is_capturing_screen); // Accessing camera should start a tracking of the kAppId1. - SetAppCapabilityAccess(kAppId1, true, false); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/false); state = GetMediaStateInVideoConferenceManagerAsh(); EXPECT_TRUE(state.has_media_app); @@ -526,7 +544,8 @@ EXPECT_TRUE(state.is_capturing_camera); // Accessing microphone should start a tracking of the kAppId2. - SetAppCapabilityAccess(kAppId2, false, true); + SetAppCapabilityAccess(kAppId2, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/true); state = GetMediaStateInVideoConferenceManagerAsh(); EXPECT_TRUE(state.has_media_app); @@ -534,7 +553,8 @@ EXPECT_TRUE(state.is_capturing_microphone); // This should stop the accessing, but not the permission. - SetAppCapabilityAccess(kAppId1, false, false); + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/false); state = GetMediaStateInVideoConferenceManagerAsh(); EXPECT_TRUE(state.has_camera_permission); @@ -550,7 +570,8 @@ EXPECT_FALSE(state.has_camera_permission); EXPECT_FALSE(state.is_capturing_camera); - SetAppCapabilityAccess(kAppId2, false, false); + SetAppCapabilityAccess(kAppId2, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/false); state = GetMediaStateInVideoConferenceManagerAsh(); EXPECT_TRUE(state.has_microphone_permission); @@ -592,10 +613,96 @@ // has-camera, has-mic should not start tracking of the app only because // that we are not tracking the AppType listed above. - SetAppCapabilityAccess(app_id, true, true); + SetAppCapabilityAccess(app_id, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); EXPECT_TRUE(GetMediaApps().empty()); } } +IN_PROC_BROWSER_TEST_F(VideoConferenceAppServiceClientTest, + HandleDeviceUsedWhileDisabled) { + // Notify disabling state of camera and microphone from + // video_conference_manager_ash. + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->SetSystemMediaDeviceStatus( + crosapi::mojom::VideoConferenceMediaDevice::kCamera, + /*disabled=*/true); + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->SetSystemMediaDeviceStatus( + crosapi::mojom::VideoConferenceMediaDevice::kMicrophone, + /*disabled=*/true); + + FakeVideoConferenceTrayController* fake_try_controller = + static_cast<FakeVideoConferenceTrayController*>( + VideoConferenceTrayController::Get()); + + InstallApp(kAppId1); + + // Accessing camera will trigger NotifyDeviceUsedWhileDisabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/false); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 1u); + EXPECT_THAT(fake_try_controller->device_used_while_disabled_records().back(), + testing::Pair(crosapi::mojom::VideoConferenceMediaDevice::kCamera, + base::UTF8ToUTF16(std::string(kAppName1)))); + + // Accessing microphone will trigger NotifyDeviceUsedWhileDisabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 2u); + EXPECT_THAT( + fake_try_controller->device_used_while_disabled_records().back(), + testing::Pair(crosapi::mojom::VideoConferenceMediaDevice::kMicrophone, + base::UTF8ToUTF16(std::string(kAppName1)))); + + // Stopping microphone access should not trigger + // NotifyDeviceUsedWhileDisabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/false); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 2u); + + // Stopping camera access should not trigger NotifyDeviceUsedWhileDisabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/false, + /*is_capturing_microphone=*/false); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 2u); + + // Notify enabling state of camera and microphone from + // video_conference_manager_ash. + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->SetSystemMediaDeviceStatus( + crosapi::mojom::VideoConferenceMediaDevice::kCamera, + /*disabled=*/false); + crosapi::CrosapiManager::Get() + ->crosapi_ash() + ->video_conference_manager_ash() + ->SetSystemMediaDeviceStatus( + crosapi::mojom::VideoConferenceMediaDevice::kMicrophone, + /*disabled=*/false); + + // Accessing camera should not trigger NotifyDeviceUsedWhileDisabled because + // camera is not disabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/false); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 2u); + + // Accessing microphone should not trigger NotifyDeviceUsedWhileDisabled + // because microphone is not disabled. + SetAppCapabilityAccess(kAppId1, /*is_capturing_camera=*/true, + /*is_capturing_microphone=*/true); + ASSERT_EQ(fake_try_controller->device_used_while_disabled_records().size(), + 2u); +} + } // namespace ash
diff --git a/chrome/browser/ash/video_conference/video_conference_manager_ash.cc b/chrome/browser/ash/video_conference/video_conference_manager_ash.cc index dd3bb216a..5d8ca1e9 100644 --- a/chrome/browser/ash/video_conference/video_conference_manager_ash.cc +++ b/chrome/browser/ash/video_conference/video_conference_manager_ash.cc
@@ -80,7 +80,7 @@ } } -void VideoConferenceManagerAsh::SetSystemDeviceStatus( +void VideoConferenceManagerAsh::SetSystemMediaDeviceStatus( crosapi::mojom::VideoConferenceMediaDevice device, bool disabled) { for (auto& [_, client_wrapper] : client_id_to_wrapper_) {
diff --git a/chrome/browser/ash/video_conference/video_conference_manager_ash.h b/chrome/browser/ash/video_conference/video_conference_manager_ash.h index 9e9068d..15f35a0 100644 --- a/chrome/browser/ash/video_conference/video_conference_manager_ash.h +++ b/chrome/browser/ash/video_conference/video_conference_manager_ash.h
@@ -50,8 +50,9 @@ void ReturnToApp(const base::UnguessableToken& id); // Sets whether |device| is disabled at the system or hardware level. - void SetSystemDeviceStatus(crosapi::mojom::VideoConferenceMediaDevice device, - bool disabled); + void SetSystemMediaDeviceStatus( + crosapi::mojom::VideoConferenceMediaDevice device, + bool disabled); // Registers an ash-browser client. Non-mojo clients need to manually call // |UnregisterClient|, e.g. inside their destructor.
diff --git a/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc b/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc index 37d57e3..a4edac6 100644 --- a/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc +++ b/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc
@@ -773,7 +773,7 @@ parsed_response->albums->push_back( ash::personalization_app::mojom::GooglePhotosAlbum::New( *album_id, *title, base::saturated_cast<int>(num_photos), - GURL(*cover_photo_url), timestamp)); + GURL(*cover_photo_url), timestamp, /*is_shared=*/false)); } return parsed_response; } @@ -846,7 +846,7 @@ parsed_response->albums->push_back( ash::personalization_app::mojom::GooglePhotosAlbum::New( *album_id, *title, /*num_image=*/0, GURL(*cover_photo_url), - timestamp)); + timestamp, /*is_shared=*/true)); } return parsed_response; }
diff --git a/chrome/browser/ash/web_applications/help_app/help_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/help_app/help_app_integration_browsertest.cc index 446aaa07..da9acf8 100644 --- a/chrome/browser/ash/web_applications/help_app/help_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/help_app/help_app_integration_browsertest.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h" #include "chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.h" #include "chrome/browser/notifications/notification_display_service_tester.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/ash/system_tray_client_impl.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -51,6 +50,7 @@ #include "components/language/core/browser/pref_names.h" #include "components/services/app_service/public/cpp/app_launch_util.h" #include "components/services/app_service/public/cpp/features.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/user_manager/user_names.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc index 349fda0..667479a 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc
@@ -41,8 +41,9 @@ // May already be bound if user refreshes page. theme_observer_remote_.reset(); theme_observer_remote_.Bind(std::move(observer)); - if (!color_mode_observer_.IsObserving()) + if (!color_mode_observer_.IsObserving()) { color_mode_observer_.Observe(ash::DarkLightModeControllerImpl::Get()); + } // Call it once to get the current color mode. OnColorModeChanged( ash::DarkLightModeControllerImpl::Get()->IsDarkModeEnabled()); @@ -58,10 +59,24 @@ // Call once to get the initial status. NotifyColorModeAutoScheduleChanged(); if (ash::features::IsJellyEnabled()) { - // TODO(b/261505637): Observe changes to the color prefs. - AccountId account_id = GetAccountId(profile_); - OnStaticColorChanged(color_palette_controller_->GetStaticColor(account_id)); - OnColorSchemeChanged(color_palette_controller_->GetColorScheme(account_id)); + OnStaticColorChanged(); + OnColorSchemeChanged(); + if (!pref_change_registrar_.IsObserved( + ash::prefs::kDynamicColorColorScheme)) { + pref_change_registrar_.Add( + ash::prefs::kDynamicColorColorScheme, + base::BindRepeating( + &PersonalizationAppThemeProviderImpl::OnColorSchemeChanged, + base::Unretained(this))); + } + if (!pref_change_registrar_.IsObserved( + ash::prefs::kDynamicColorSeedColor)) { + pref_change_registrar_.Add( + ash::prefs::kDynamicColorSeedColor, + base::BindRepeating( + &PersonalizationAppThemeProviderImpl::OnStaticColorChanged, + base::Unretained(this))); + } } } @@ -79,8 +94,9 @@ bool enabled) { PrefService* pref_service = profile_->GetPrefs(); DCHECK(pref_service); - if (enabled) + if (enabled) { LogPersonalizationTheme(ColorMode::kAuto); + } const ScheduleType schedule_type = enabled ? ScheduleType::kSunsetToSunrise : ScheduleType::kNone; pref_service->SetInteger(ash::prefs::kDarkModeScheduleType, @@ -104,16 +120,16 @@ theme_observer_remote_->OnColorModeChanged(dark_mode_enabled); } -void PersonalizationAppThemeProviderImpl::OnColorSchemeChanged( - ColorScheme color_scheme) { +void PersonalizationAppThemeProviderImpl::OnColorSchemeChanged() { DCHECK(theme_observer_remote_.is_bound()); - theme_observer_remote_->OnColorSchemeChanged(color_scheme); + theme_observer_remote_->OnColorSchemeChanged( + color_palette_controller_->GetColorScheme(GetAccountId(profile_))); } -void PersonalizationAppThemeProviderImpl::OnStaticColorChanged( - absl::optional<SkColor> color) { +void PersonalizationAppThemeProviderImpl::OnStaticColorChanged() { DCHECK(theme_observer_remote_.is_bound()); - theme_observer_remote_->OnStaticColorChanged(color); + theme_observer_remote_->OnStaticColorChanged( + color_palette_controller_->GetStaticColor(GetAccountId(profile_))); } bool PersonalizationAppThemeProviderImpl::IsColorModeAutoScheduleEnabled() { @@ -150,7 +166,6 @@ } color_palette_controller_->SetColorScheme( color_scheme, GetAccountId(profile_), base::DoNothing()); - OnColorSchemeChanged(color_scheme); } void PersonalizationAppThemeProviderImpl::GetStaticColor( @@ -173,10 +188,6 @@ AccountId account_id = GetAccountId(profile_); color_palette_controller_->SetStaticColor(static_color, account_id, base::DoNothing()); - // TODO(b/261505637): Remove and use pref listeners once the prefs are - // available. - OnStaticColorChanged(static_color); - OnColorSchemeChanged(ColorScheme::kStatic); } void PersonalizationAppThemeProviderImpl::GenerateSampleColorSchemes(
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h index ebec652..358abc50 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h
@@ -76,9 +76,9 @@ // Notify webUI the current state of color mode auto scheduler. void NotifyColorModeAutoScheduleChanged(); - void OnColorSchemeChanged(ColorScheme color_scheme); + void OnColorSchemeChanged(); - void OnStaticColorChanged(absl::optional<SkColor> color); + void OnStaticColorChanged(); // Pointer to profile of user that opened personalization SWA. Not owned. raw_ptr<Profile> const profile_ = nullptr;
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl_unittest.cc index f508a6f..077c3f5 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "ash/constants/ash_pref_names.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/style/color_palette_controller.h" @@ -35,15 +36,17 @@ constexpr char kFakeTestEmail[] = "fakeemail@personalization"; constexpr char kTestGaiaId[] = "1234567890"; +AccountId kAccountId = + AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId); -void AddAndLoginUser(const AccountId& account_id) { +void AddAndLoginUser() { ash::FakeChromeUserManager* user_manager = static_cast<ash::FakeChromeUserManager*>( user_manager::UserManager::Get()); - user_manager->AddUser(account_id); - user_manager->LoginUser(account_id); - user_manager->SwitchActiveUser(account_id); + user_manager->AddUser(kAccountId); + user_manager->LoginUser(kAccountId); + user_manager->SwitchActiveUser(kAccountId); } class TestThemeObserver @@ -267,10 +270,14 @@ void SetUp() override { PersonalizationAppThemeProviderImplTest::SetUp(); - AccountId account_id = - AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId); - AddAndLoginUser(account_id); - GetSessionControllerClient()->AddUserSession(account_id, kFakeTestEmail); + AddAndLoginUser(); + GetSessionControllerClient()->AddUserSession(kAccountId, kFakeTestEmail); + } + + protected: + PrefService* GetUserPrefService() { + return Shell::Get()->session_controller()->GetUserPrefServiceForUser( + kAccountId); } private: @@ -281,23 +288,68 @@ SetThemeObserver(); theme_provider_remote()->FlushForTesting(); SkColor color = SK_ColorMAGENTA; - EXPECT_NE(color, GetStaticColor()); - EXPECT_NE(ash::ColorScheme::kStatic, GetColorScheme()); + EXPECT_NE(color, + GetUserPrefService()->GetUint64(prefs::kDynamicColorSeedColor)); theme_provider()->SetStaticColor(color); + EXPECT_EQ(color, + GetUserPrefService()->GetUint64(prefs::kDynamicColorSeedColor)); +} + +TEST_F(PersonalizationAppThemeProviderImplJellyTest, + ObserveStaticColorChanges) { + SetThemeObserver(); + theme_provider_remote()->FlushForTesting(); + SkColor color = SK_ColorMAGENTA; + EXPECT_NE(color, + GetUserPrefService()->GetUint64(prefs::kDynamicColorSeedColor)); + + // The static color is set via the UserPrefService in + // ColorPaletteController, and the pref listener is set via the + // ProfilePrefService in the ThemeProvider. In real life, these point to the + // same object, but not in this test. We have to set the pref in both places + // for the pref listener to work. Only the profile prefs will trigger the + // listener, and only the UserPrefService holds the information about which + // pref was updated. + theme_provider()->SetStaticColor(color); + profile()->GetPrefs()->SetUint64(prefs::kDynamicColorSeedColor, color); + EXPECT_EQ(color, GetStaticColor()); - EXPECT_EQ(ash::ColorScheme::kStatic, GetColorScheme()); } TEST_F(PersonalizationAppThemeProviderImplJellyTest, SetColorScheme) { SetThemeObserver(); theme_provider_remote()->FlushForTesting(); auto color_scheme = ash::ColorScheme::kExpressive; - EXPECT_NE(color_scheme, GetColorScheme()); + EXPECT_NE((int)color_scheme, + GetUserPrefService()->GetInteger(prefs::kDynamicColorColorScheme)); theme_provider()->SetColorScheme(color_scheme); + EXPECT_EQ((int)color_scheme, + GetUserPrefService()->GetInteger(prefs::kDynamicColorColorScheme)); +} + +TEST_F(PersonalizationAppThemeProviderImplJellyTest, + ObserveColorSchemeChanges) { + SetThemeObserver(); + theme_provider_remote()->FlushForTesting(); + auto color_scheme = ash::ColorScheme::kExpressive; + EXPECT_NE((int)color_scheme, + GetUserPrefService()->GetInteger(prefs::kDynamicColorColorScheme)); + + // The color scheme is set via the UserPrefService in + // ColorPaletteController, and the pref listener is set via the + // ProfilePrefService in the ThemeProvider. In real life, these point to the + // same object, but not in this test. We have to set the pref in both places + // for the pref listener to work. Only the profile prefs will trigger the + // listener, and only the UserPrefService holds the information about which + // pref was updated. + theme_provider()->SetColorScheme(color_scheme); + profile()->GetPrefs()->SetInteger(prefs::kDynamicColorColorScheme, + (int)color_scheme); + EXPECT_EQ(color_scheme, GetColorScheme()); }
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc index ff8a338..8bdd67b 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
@@ -780,7 +780,8 @@ EXPECT_TRUE( base::Time::FromUTCString("2021-12-31T07:07:07.000Z", ×tamp)); valid_albums_vector.push_back(GooglePhotosAlbum::New( - "albumId", "title", 1, GURL("https://www.google.com/"), timestamp)); + "albumId", "title", 1, GURL("https://www.google.com/"), timestamp, + /*is_shared=*/false)); auto result = FetchGooglePhotosAlbumsResponse::New( mojo::Clone(valid_albums_vector), kResumeToken); EXPECT_EQ(google_photos_albums_fetcher->ParseResponse(&response), result);
diff --git a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc index 1833dba9..ffe6e318 100644 --- a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc +++ b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc
@@ -130,31 +130,19 @@ LegalMessageLine::Parse(value->GetDict(), &legal_message_lines, /*escape_apostrophes=*/true); } - if (is_uploading) { - // Upload save infobar delegate: - credit_card_to_save_ = credit_card; - std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> delegate( - new AutofillSaveCardInfoBarDelegateMobile( - is_uploading, options, credit_card, legal_message_lines, - /*upload_save_card_callback=*/ - base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: - UploadSaveCardPromptCallback, - base::Unretained(this)), - /*local_save_card_callback=*/{}, AccountInfo())); - return delegate; - } - // Local save infobar delegate: credit_card_to_save_ = credit_card; - std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> delegate( - new AutofillSaveCardInfoBarDelegateMobile( - is_uploading, options, credit_card, legal_message_lines, - /*upload_save_card_callback=*/{}, - /*local_save_card_callback=*/ - base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: - LocalSaveCardPromptCallback, - base::Unretained(this)), - AccountInfo())); - return delegate; + return is_uploading + ? AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( + options, credit_card, + base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: + UploadSaveCardPromptCallback, + base::Unretained(this)), + legal_message_lines, AccountInfo()) + : AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( + options, credit_card, + base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: + LocalSaveCardPromptCallback, + base::Unretained(this))); } // Test that local credit card save infobar metrics are logged correctly.
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java index 5c82c55d..bc9c988 100644 --- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java +++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.back_press; +import android.util.SparseIntArray; + import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -15,9 +17,6 @@ import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.Type; -import java.util.HashMap; -import java.util.Map; - /** * A central manager class to handle the back gesture. Every component/feature which is going to * intercept the back press event must implement the {@link BackPressHandler} and be registered @@ -31,29 +30,30 @@ */ public class BackPressManager implements Destroyable { @VisibleForTesting - static final Map<Integer, Integer> sMetricsMap = new HashMap() { - { - put(Type.TEXT_BUBBLE, 0); - put(Type.VR_DELEGATE, 1); - put(Type.AR_DELEGATE, 2); - put(Type.SCENE_OVERLAY, 3); - put(Type.START_SURFACE, 4); - put(Type.SELECTION_POPUP, 5); - put(Type.MANUAL_FILLING, 6); - put(Type.FULLSCREEN, 7); - put(Type.BOTTOM_SHEET, 8); - put(Type.TAB_MODAL_HANDLER, 9); - put(Type.TAB_SWITCHER, 10); - put(Type.CLOSE_WATCHER, 11); - put(Type.TAB_HISTORY, 12); - put(Type.TAB_RETURN_TO_CHROME_START_SURFACE, 13); - put(Type.SHOW_READING_LIST, 14); - put(Type.MINIMIZE_APP_AND_CLOSE_TAB, 15); - put(Type.FIND_TOOLBAR, 16); - put(Type.LOCATION_BAR, 17); - // Add new one here. - } - }; + static final SparseIntArray sMetricsMap; + static { + SparseIntArray map = new SparseIntArray(17); + map.put(Type.TEXT_BUBBLE, 0); + map.put(Type.VR_DELEGATE, 1); + map.put(Type.AR_DELEGATE, 2); + map.put(Type.SCENE_OVERLAY, 3); + map.put(Type.START_SURFACE, 4); + map.put(Type.SELECTION_POPUP, 5); + map.put(Type.MANUAL_FILLING, 6); + map.put(Type.FULLSCREEN, 7); + map.put(Type.BOTTOM_SHEET, 8); + map.put(Type.TAB_MODAL_HANDLER, 9); + map.put(Type.TAB_SWITCHER, 10); + map.put(Type.CLOSE_WATCHER, 11); + map.put(Type.TAB_HISTORY, 12); + map.put(Type.TAB_RETURN_TO_CHROME_START_SURFACE, 13); + map.put(Type.SHOW_READING_LIST, 14); + map.put(Type.MINIMIZE_APP_AND_CLOSE_TAB, 15); + map.put(Type.FIND_TOOLBAR, 16); + map.put(Type.LOCATION_BAR, 17); + // Add new one here and update array size. + sMetricsMap = map; + } private final OnBackPressedCallback mCallback = new OnBackPressedCallback(false) { @Override
diff --git a/chrome/browser/banners/android/OWNERS b/chrome/browser/banners/android/OWNERS new file mode 100644 index 0000000..3f3a939 --- /dev/null +++ b/chrome/browser/banners/android/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/browser/banners/app_banner_manager_browsertest.cc b/chrome/browser/banners/app_banner_manager_browsertest.cc index e61e278..d55f14a 100644 --- a/chrome/browser/banners/app_banner_manager_browsertest.cc +++ b/chrome/browser/banners/app_banner_manager_browsertest.cc
@@ -741,8 +741,8 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kIgnoreCertificateErrors); - EnableFeatureAndSetParams(::features::kBackForwardCache, - "TimeToLiveInBackForwardCacheInSeconds", "3600"); + EnableFeatureAndSetParams(::features::kBackForwardCacheTimeToLiveControl, + "time_to_live_seconds", "3600"); // Navigating quickly between cached pages can fail flakily with: // CanStorePageNow: <URL> : No: blocklisted features: outstanding network // request (others)
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc index c718624e..c62d8bc 100644 --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc
@@ -227,4 +227,14 @@ "FedCmWithoutThirdPartyCookies", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables the Incoming Call Notifications scenario. When created by an +// installed origin, an incoming call notification should have increased +// priority, colored buttons, a ringtone, and a default "close" button. +// Otherwise, if the origin is not installed, it should behave like the default +// notifications, but with the added "Close" button. See +// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Notifications/notifications_actions_customization.md +BASE_FEATURE(kIncomingCallNotifications, + "IncomingCallNotifications", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace features
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index e43bbc1..c148a765 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -80,6 +80,8 @@ BASE_DECLARE_FEATURE(kFedCmWithoutThirdPartyCookies); +BASE_DECLARE_FEATURE(kIncomingCallNotifications); + } // namespace features #endif // CHROME_BROWSER_BROWSER_FEATURES_H_
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 216ff33..c559c9de 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -1218,9 +1218,9 @@ #endif // Create the global SodaInstaller instance. -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) soda_installer_impl_ = std::make_unique<speech::SodaInstallerImpl>(); -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS_ASH) soda_installer_impl_ = std::make_unique<speech::SodaInstallerImplChromeOS>();
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 0130685..c7fab534 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -381,7 +381,7 @@ // but some users of component updater only install per-user. std::unique_ptr<component_updater::ComponentUpdateService> component_updater_; -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) // Used to create a singleton instance of SodaInstallerImpl, which can be // retrieved using speech::SodaInstaller::GetInstance(). // SodaInstallerImpl depends on ComponentUpdateService, so define it here
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index ff6a34d..83e3492 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -2157,8 +2157,6 @@ #if !BUILDFLAG(IS_ANDROID) TEST_F(ChromeBrowsingDataRemoverDelegateTest, ZeroSuggestInMemoryCacheClear) { - using CacheEntry = ZeroSuggestCacheService::CacheEntry; - // Enable in-memory ZPS caching. base::test::ScopedFeatureList features; features.InitAndEnableFeature(omnibox::kZeroSuggestInMemoryCaching); @@ -2168,10 +2166,8 @@ ZeroSuggestCacheService* zero_suggest_cache_service = ZeroSuggestCacheServiceFactory::GetForProfile(GetProfile()); - zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, - CacheEntry(response)); - zero_suggest_cache_service->StoreZeroSuggestResponse("", - CacheEntry(response)); + zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, response); + zero_suggest_cache_service->StoreZeroSuggestResponse("", response); // Verify that the cache is initially non-empty. EXPECT_FALSE(zero_suggest_cache_service->IsCacheEmpty()); @@ -3806,7 +3802,7 @@ std::vector<std::string> tokens{kPersistentOriginTrialToken}; content::OriginTrialsControllerDelegate* delegate = profile->GetOriginTrialsControllerDelegate(); - delegate->PersistTrialsFromTokens(origin, tokens, + delegate->PersistTrialsFromTokens(origin, /*partition_origin=*/origin, tokens, kPersistentOriginTrialValidTime); // Delete all data types that trigger website setting deletions. @@ -3816,12 +3812,14 @@ EXPECT_FALSE( delegate - ->GetPersistedTrialsForOrigin(origin, kPersistentOriginTrialValidTime) + ->GetPersistedTrialsForOrigin(origin, /*partition_origin=*/origin, + kPersistentOriginTrialValidTime) .empty()); BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), mask, false); - EXPECT_TRUE( - delegate - ->GetPersistedTrialsForOrigin(origin, kPersistentOriginTrialValidTime) - .empty()); + EXPECT_TRUE(delegate + ->GetPersistedTrialsForOrigin(origin, + /*partition_origin=*/origin, + kPersistentOriginTrialValidTime) + .empty()); }
diff --git a/chrome/browser/chrome_back_forward_cache_browsertest.cc b/chrome/browser/chrome_back_forward_cache_browsertest.cc index c7836fd..21c98dc0 100644 --- a/chrome/browser/chrome_back_forward_cache_browsertest.cc +++ b/chrome/browser/chrome_back_forward_cache_browsertest.cc
@@ -83,8 +83,8 @@ command_line->AppendSwitch( switches::kEnableExperimentalWebPlatformFeatures); - EnableFeatureAndSetParams(features::kBackForwardCache, - "TimeToLiveInBackForwardCacheInSeconds", "3600"); + EnableFeatureAndSetParams(features::kBackForwardCacheTimeToLiveControl, + "time_to_live_seconds", "3600"); // Navigating quickly between cached pages can fail flakily with: // CanStorePageNow: <URL> : No: blocklisted features: outstanding network // request (others)
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 4ebc6bbf..6b22c38d 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -684,6 +684,7 @@ #endif } +#if BUILDFLAG(IS_WIN) void BindMediaFoundationRendererNotifierHandler( content::RenderFrameHost* frame_host, mojo::PendingReceiver<media::mojom::MediaFoundationRendererNotifier> @@ -693,6 +694,7 @@ std::move(receiver)); } } +#endif // BUILDFLAG(IS_WIN) #endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) @@ -844,8 +846,10 @@ base::BindRepeating(&BindSpeechRecognitionClientBrowserInterfaceHandler)); map->Add<media::mojom::SpeechRecognitionRecognizerClient>( base::BindRepeating(&BindSpeechRecognitionRecognizerClientHandler)); +#if BUILDFLAG(IS_WIN) map->Add<media::mojom::MediaFoundationRendererNotifier>( base::BindRepeating(&BindMediaFoundationRendererNotifierHandler)); +#endif #endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ @@ -951,7 +955,7 @@ ash::personalization_app::PersonalizationAppUI, ash::settings::OSSettingsUI, #endif - NewTabPageUI, OmniboxPopupUI>(map); + NewTabPageUI, OmniboxPopupUI, BookmarksSidePanelUI>(map); RegisterWebUIControllerInterfaceBinder< new_tab_page::mojom::PageHandlerFactory, NewTabPageUI>(map); @@ -1122,6 +1126,9 @@ RegisterWebUIControllerInterfaceBinder<ash::auth::mojom::RecoveryFactorEditor, ash::settings::OSSettingsUI>(map); + RegisterWebUIControllerInterfaceBinder<ash::auth::mojom::PinFactorEditor, + ash::settings::OSSettingsUI>(map); + RegisterWebUIControllerInterfaceBinder< ash::cellular_setup::mojom::ESimManager, ash::settings::OSSettingsUI, ash::NetworkUI, ash::OobeUI>(map);
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index f888bef..a09033c 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -494,13 +494,11 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) return base::FeatureList::IsEnabled( ash::features::kOnDeviceSpeechRecognition); -#else -#if BUILDFLAG(ENABLE_COMPONENT_UPDATER) +#elif !BUILDFLAG(IS_CHROMEOS_LACROS) && BUILDFLAG(ENABLE_COMPONENT_UPDATER) return !command_line.HasSwitch(switches::kDisableComponentUpdate); #else return false; -#endif // BUILDFLAG(ENABLE_COMPONENT_UPDATER) -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS_ASH) } #endif // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 08151a8..95fc727 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -250,6 +250,7 @@ #include "components/safe_browsing/content/browser/browser_url_loader_throttle.h" #include "components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition.h" #include "components/safe_browsing/content/browser/safe_browsing_navigation_throttle.h" +#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" #include "components/safe_browsing/core/browser/realtime/policy_engine.h" #include "components/safe_browsing/core/browser/realtime/url_lookup_service.h" #include "components/safe_browsing/core/browser/url_checker_delegate.h" @@ -481,6 +482,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/search/new_tab_page_navigation_throttle.h" #include "chrome/browser/ui/web_applications/tabbed_web_app_navigation_throttle.h" +#include "chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_loader_factory.h" #include "chrome/browser/web_applications/policy/web_app_policy_manager.h" #include "chrome/browser/web_applications/web_app_helpers.h" @@ -2355,7 +2357,7 @@ InstantService* instant_service = InstantServiceFactory::GetForProfile(profile); if (instant_service) - instant_service->AddInstantProcess(site_instance->GetProcess()); + instant_service->AddInstantProcess(site_instance->GetProcess()->GetID()); } #endif @@ -4291,13 +4293,6 @@ return l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME); } -base::FilePath ChromeContentBrowserClient::GetFontLookupTableCacheDir() { - base::FilePath user_data_dir; - base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); - DCHECK(!user_data_dir.empty()); - return user_data_dir.Append(FILE_PATH_LITERAL("FontLookupTableCache")); -} - base::FilePath ChromeContentBrowserClient::GetShaderDiskCacheDirectory() { base::FilePath user_data_dir; base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); @@ -4991,6 +4986,10 @@ MaybeAddThrottle( web_app::TabbedWebAppNavigationThrottle::MaybeCreateThrottleFor(handle), &throttles); + + MaybeAddThrottle( + web_app::WebUIWebAppNavigationThrottle::MaybeCreateThrottleFor(handle), + &throttles); #endif // g_browser_process->safe_browsing_service() may be null in unittests. @@ -5370,6 +5369,11 @@ GetUrlLookupService(browser_context, is_enterprise_lookup_enabled, is_consumer_lookup_enabled); + safe_browsing::HashRealTimeService* hash_realtime_service = + safe_browsing_service_ + ? safe_browsing_service_->GetHashRealTimeService(profile) + : nullptr; + result.push_back(safe_browsing::BrowserURLLoaderThrottle::Create( base::BindOnce( &ChromeContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate, @@ -5379,7 +5383,8 @@ /*should_check_on_sb_disabled=*/is_enterprise_lookup_enabled, safe_browsing::GetURLAllowlistByPolicy(profile->GetPrefs())), wc_getter, frame_tree_node_id, - url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr)); + url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr, + hash_realtime_service ? hash_realtime_service->GetWeakPtr() : nullptr)); } #endif
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 662251e..071a3dd 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -397,7 +397,6 @@ void BrowserURLHandlerCreated(content::BrowserURLHandler* handler) override; base::FilePath GetDefaultDownloadDirectory() override; std::string GetDefaultDownloadName() override; - base::FilePath GetFontLookupTableCacheDir() override; base::FilePath GetShaderDiskCacheDirectory() override; base::FilePath GetGrShaderDiskCacheDirectory() override; base::FilePath GetNetLogDefaultDirectory() override;
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc index 877b209..ccf84687 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_api_guard_function_browsertest.cc
@@ -6,6 +6,7 @@ #include <string> #include "base/strings/string_util.h" +#include "base/test/scoped_feature_list.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.h" #include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h" @@ -15,6 +16,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_mock_cert_verifier.h" +#include "extensions/common/extension_features.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" #include "net/dns/mock_host_resolver.h" @@ -44,6 +46,14 @@ std::string service_worker = R"( const tests = [ // Telemetry APIs. + async function getAudioInfo() { + await chrome.test.assertPromiseRejects( + chrome.os.telemetry.getAudioInfo(), + 'Error: Unauthorized access to ' + + 'chrome.os.telemetry.getAudioInfo.' + ' %s' + ); + chrome.test.succeed(); + }, async function getBatteryInfo() { await chrome.test.assertPromiseRejects( chrome.os.telemetry.getBatteryInfo(), @@ -68,6 +78,14 @@ ); chrome.test.succeed(); }, + async function getMarketingInfo() { + await chrome.test.assertPromiseRejects( + chrome.os.telemetry.getMarketingInfo(), + 'Error: Unauthorized access to chrome.os.telemetry.' + + 'getMarketingInfo. %s' + ); + chrome.test.succeed(); + }, async function getMemoryInfo() { await chrome.test.assertPromiseRejects( chrome.os.telemetry.getMemoryInfo(), @@ -423,7 +441,18 @@ } // namespace -using TelemetryExtensionApiGuardBrowserTest = BaseTelemetryExtensionBrowserTest; +class TelemetryExtensionApiGuardBrowserTest + : public BaseTelemetryExtensionBrowserTest { + public: + TelemetryExtensionApiGuardBrowserTest() { + // Include unreleased APIs. + feature_list_.InitAndEnableFeature( + extensions_features::kTelemetryExtensionPendingApprovalApi); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; IN_PROC_BROWSER_TEST_F(TelemetryExtensionApiGuardBrowserTest, CanAccessApiReturnsError) {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc index d2a6de9..c4e7b72 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
@@ -45,6 +45,29 @@ } #endif // BUILDFLAG(IS_CHROMEOS_LACROS) +// OsTelemetryGetAudioInfoFunction --------------------------------------------- + +void OsTelemetryGetAudioInfoFunction::RunIfAllowed() { + auto cb = base::BindOnce(&OsTelemetryGetAudioInfoFunction::OnResult, this); + + GetRemoteService()->ProbeTelemetryInfo( + {crosapi::mojom::ProbeCategoryEnum::kAudio}, std::move(cb)); +} + +void OsTelemetryGetAudioInfoFunction::OnResult( + crosapi::mojom::ProbeTelemetryInfoPtr ptr) { + if (!ptr || !ptr->audio_result || !ptr->audio_result->is_audio_info()) { + Respond(Error("API internal error")); + return; + } + auto& audio_info = ptr->audio_result->get_audio_info(); + + auto result = + converters::ConvertPtr<telemetry::AudioInfo>(std::move(audio_info)); + + Respond(ArgumentList(telemetry::GetAudioInfo::Results::Create(result))); +} + // OsTelemetryGetBatteryInfoFunction ------------------------------------------- void OsTelemetryGetBatteryInfoFunction::RunIfAllowed() { @@ -184,6 +207,36 @@ telemetry::GetInternetConnectivityInfo::Results::Create(result))); } +// OsTelemetryGetMarketingInfoFunction ----------------------------------------- + +void OsTelemetryGetMarketingInfoFunction::RunIfAllowed() { + auto cb = + base::BindOnce(&OsTelemetryGetMarketingInfoFunction::OnResult, this); + + GetRemoteService()->ProbeTelemetryInfo( + {crosapi::mojom::ProbeCategoryEnum::kSystem}, std::move(cb)); +} + +void OsTelemetryGetMarketingInfoFunction::OnResult( + crosapi::mojom::ProbeTelemetryInfoPtr ptr) { + if (!ptr || !ptr->system_result || !ptr->system_result->is_system_info()) { + Respond(Error("API internal error")); + return; + } + + auto& system_info = ptr->system_result->get_system_info(); + + if (!system_info->os_info) { + Respond(Error("API internal error")); + return; + } + + telemetry::MarketingInfo result; + result.marketing_name = system_info->os_info->marketing_name; + + Respond(ArgumentList(telemetry::GetMarketingInfo::Results::Create(result))); +} + // OsTelemetryGetMemoryInfoFunction -------------------------------------------- void OsTelemetryGetMemoryInfoFunction::RunIfAllowed() {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h index f1a891d..3e6111bc 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h
@@ -37,6 +37,18 @@ std::unique_ptr<RemoteProbeServiceStrategy> remote_probe_service_strategy_; }; +class OsTelemetryGetAudioInfoFunction : public TelemetryApiFunctionBase { + DECLARE_EXTENSION_FUNCTION("os.telemetry.getAudioInfo", + OS_TELEMETRY_GETAUDIOINFO) + void OnResult(crosapi::mojom::ProbeTelemetryInfoPtr ptr); + + private: + ~OsTelemetryGetAudioInfoFunction() override = default; + + // BaseTelemetryExtensionApiGuardFunction: + void RunIfAllowed() override; +}; + class OsTelemetryGetBatteryInfoFunction : public TelemetryApiFunctionBase { DECLARE_EXTENSION_FUNCTION("os.telemetry.getBatteryInfo", OS_TELEMETRY_GETBATTERYINFO) @@ -89,6 +101,19 @@ void OnResult(crosapi::mojom::ProbeTelemetryInfoPtr ptr); }; +class OsTelemetryGetMarketingInfoFunction : public TelemetryApiFunctionBase { + DECLARE_EXTENSION_FUNCTION("os.telemetry.getMarketingInfo", + OS_TELEMETRY_GETMARKETINGINFO) + + private: + ~OsTelemetryGetMarketingInfoFunction() override = default; + + // BaseTelemetryExtensionApiGuardFunction: + void RunIfAllowed() override; + + void OnResult(crosapi::mojom::ProbeTelemetryInfoPtr ptr); +}; + class OsTelemetryGetMemoryInfoFunction : public TelemetryApiFunctionBase { DECLARE_EXTENSION_FUNCTION("os.telemetry.getMemoryInfo", OS_TELEMETRY_GETMEMORYINFO)
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc index 97eed44..06358b9 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_browsertest.cc
@@ -5,7 +5,9 @@ #include <memory> #include <string> #include <utility> +#include <vector> +#include "base/test/scoped_feature_list.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h" #include "chrome/browser/chromeos/extensions/telemetry/api/fake_probe_service.h" @@ -14,6 +16,7 @@ #include "chromeos/services/network_config/public/mojom/network_types.mojom.h" #include "chromeos/services/network_health/public/mojom/network_health_types.mojom.h" #include "content/public/test/browser_test.h" +#include "extensions/common/extension_features.h" #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -202,6 +205,125 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, + GetAudioInfo_Error) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // If Probe interface is not available on this version of ash-chrome, this + // test suite will no-op. + if (!IsServiceAvailable()) { + return; + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + + // Configure FakeProbeService. + { + auto fake_service_impl = std::make_unique<FakeProbeService>(); + fake_service_impl->SetExpectedLastRequestedCategories( + {crosapi::mojom::ProbeCategoryEnum::kAudio}); + + SetServiceForTesting(std::move(fake_service_impl)); + } + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function getAudioInfo() { + await chrome.test.assertPromiseRejects( + chrome.os.telemetry.getAudioInfo(), + 'Error: API internal error' + ); + chrome.test.succeed(); + } + ]); + )"); +} + +IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, + GetAudioInfo_Success) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // If Probe interface is not available on this version of ash-chrome, this + // test suite will no-op. + if (!IsServiceAvailable()) { + return; + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + + // Configure FakeProbeService. + { + auto telemetry_info = crosapi::mojom::ProbeTelemetryInfo::New(); + + { + std::vector<crosapi::mojom::ProbeAudioOutputNodeInfoPtr> output_infos; + auto output_node_info = crosapi::mojom::ProbeAudioOutputNodeInfo::New(); + output_node_info->id = crosapi::mojom::UInt64Value::New(43); + output_node_info->name = "Internal Speaker"; + output_node_info->device_name = "HDA Intel PCH: CA0132 Analog:0,0"; + output_node_info->active = crosapi::mojom::BoolValue::New(false); + output_node_info->node_volume = crosapi::mojom::UInt8Value::New(212); + output_infos.push_back(std::move(output_node_info)); + + std::vector<crosapi::mojom::ProbeAudioInputNodeInfoPtr> input_infos; + auto input_node_info = crosapi::mojom::ProbeAudioInputNodeInfo::New(); + input_node_info->id = crosapi::mojom::UInt64Value::New(42); + input_node_info->name = "External Mic"; + input_node_info->device_name = "HDA Intel PCH: CA0132 Analog:1,0"; + input_node_info->active = crosapi::mojom::BoolValue::New(true); + input_node_info->node_gain = crosapi::mojom::UInt8Value::New(1); + input_infos.push_back(std::move(input_node_info)); + + auto audio_info = crosapi::mojom::ProbeAudioInfo::New(); + audio_info->output_mute = crosapi::mojom::BoolValue::New(true); + audio_info->input_mute = crosapi::mojom::BoolValue::New(false); + audio_info->underruns = crosapi::mojom::UInt32Value::New(56); + audio_info->severe_underruns = crosapi::mojom::UInt32Value::New(3); + audio_info->output_nodes = std::move(output_infos); + audio_info->input_nodes = std::move(input_infos); + + telemetry_info->audio_result = + crosapi::mojom::ProbeAudioResult::NewAudioInfo(std::move(audio_info)); + } + + auto fake_service_impl = std::make_unique<FakeProbeService>(); + fake_service_impl->SetProbeTelemetryInfoResponse(std::move(telemetry_info)); + fake_service_impl->SetExpectedLastRequestedCategories( + {crosapi::mojom::ProbeCategoryEnum::kAudio}); + + SetServiceForTesting(std::move(fake_service_impl)); + } + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function getAudioInfo() { + const result = await chrome.os.telemetry.getAudioInfo(); + chrome.test.assertEq( + // The dictionary members are ordered lexicographically by the Unicode + // codepoints that comprise their identifiers. + { + inputMute: false, + inputNodes: [{ + active: true, + deviceName: 'HDA Intel PCH: CA0132 Analog:1,0', + id: 42, + name: 'External Mic', + nodeGain: 1, + }], + outputMute: true, + outputNodes: [{ + active: false, + deviceName: 'HDA Intel PCH: CA0132 Analog:0,0', + id: 43, + name: 'Internal Speaker', + nodeVolume: 212 + }], + severeUnderruns: 3, + underruns: 56, + }, result); + + chrome.test.succeed(); + } + ]); + )"); +} + +IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, GetBatteryInfo_ApiInternalError) { #if BUILDFLAG(IS_CHROMEOS_LACROS) // If Probe interface is not available on this version of ash-chrome, this @@ -585,6 +707,85 @@ } IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, + GetMarketingInfo_Error) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // If Probe interface is not available on this version of ash-chrome, this + // test suite will no-op. + if (!IsServiceAvailable()) { + return; + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + + // Configure FakeProbeService. + { + auto fake_service_impl = std::make_unique<FakeProbeService>(); + fake_service_impl->SetExpectedLastRequestedCategories( + {crosapi::mojom::ProbeCategoryEnum::kSystem}); + + SetServiceForTesting(std::move(fake_service_impl)); + } + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function getMarketingInfo() { + await chrome.test.assertPromiseRejects( + chrome.os.telemetry.getMarketingInfo(), + 'Error: API internal error' + ); + chrome.test.succeed(); + } + ]); + )"); +} + +IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, + GetMarketingInfo_Success) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // If Probe interface is not available on this version of ash-chrome, this + // test suite will no-op. + if (!IsServiceAvailable()) { + return; + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + + // Configure FakeProbeService. + { + auto telemetry_info = crosapi::mojom::ProbeTelemetryInfo::New(); + { + auto os_info = crosapi::mojom::ProbeOsInfo::New(); + os_info->marketing_name = "Test Marketing Name"; + + auto system_info = crosapi::mojom::ProbeSystemInfo::New(); + system_info->os_info = std::move(os_info); + + telemetry_info->system_result = + crosapi::mojom::ProbeSystemResult::NewSystemInfo( + std::move(system_info)); + } + + auto fake_service_impl = std::make_unique<FakeProbeService>(); + fake_service_impl->SetProbeTelemetryInfoResponse(std::move(telemetry_info)); + fake_service_impl->SetExpectedLastRequestedCategories( + {crosapi::mojom::ProbeCategoryEnum::kSystem}); + + SetServiceForTesting(std::move(fake_service_impl)); + } + + CreateExtensionAndRunServiceWorker(R"( + chrome.test.runTests([ + async function getMarketingInfo() { + const result = await chrome.os.telemetry.getMarketingInfo(); + chrome.test.assertEq( + { + marketingName: "Test Marketing Name", + }, result); + chrome.test.succeed(); + } + ]); + )"); +} + +IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest, GetMemoryInfo_Error) { #if BUILDFLAG(IS_CHROMEOS_LACROS) // If Probe interface is not available on this version of ash-chrome, this
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.cc index 56d62ed..6002e3fc 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.cc
@@ -28,6 +28,71 @@ } // namespace namespace unchecked { +chromeos::api::os_telemetry::AudioInputNodeInfo UncheckedConvertPtr( + crosapi::mojom::ProbeAudioInputNodeInfoPtr input) { + telemetry_api::AudioInputNodeInfo result; + + if (input->id) { + result.id = input->id->value; + } + result.name = input->name; + result.device_name = input->device_name; + if (input->active) { + result.active = input->active->value; + } + if (input->node_gain) { + result.node_gain = input->node_gain->value; + } + + return result; +} + +chromeos::api::os_telemetry::AudioOutputNodeInfo UncheckedConvertPtr( + crosapi::mojom::ProbeAudioOutputNodeInfoPtr input) { + telemetry_api::AudioOutputNodeInfo result; + + if (input->id) { + result.id = input->id->value; + } + result.name = input->name; + result.device_name = input->device_name; + if (input->active) { + result.active = input->active->value; + } + if (input->node_volume) { + result.node_volume = input->node_volume->value; + } + + return result; +} + +telemetry_api::AudioInfo UncheckedConvertPtr( + telemetry_service::ProbeAudioInfoPtr input) { + telemetry_api::AudioInfo result; + + if (input->output_mute) { + result.output_mute = input->output_mute->value; + } + if (input->input_mute) { + result.input_mute = input->input_mute->value; + } + if (input->underruns) { + result.underruns = input->underruns->value; + } + if (input->severe_underruns) { + result.severe_underruns = input->severe_underruns->value; + } + if (input->output_nodes) { + result.output_nodes = ConvertPtrVector<telemetry_api::AudioOutputNodeInfo>( + std::move(input->output_nodes.value())); + } + if (input->input_nodes) { + result.input_nodes = ConvertPtrVector<telemetry_api::AudioInputNodeInfo>( + std::move(input->input_nodes.value())); + } + + return result; +} telemetry_api::CpuCStateInfo UncheckedConvertPtr( telemetry_service::ProbeCpuCStateInfoPtr input) {
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h index 3360f66..bcce467 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h
@@ -27,6 +27,15 @@ // nullptr, they should be called only via ConvertPtr wrapper that checks // whether input pointer is nullptr. +chromeos::api::os_telemetry::AudioInputNodeInfo UncheckedConvertPtr( + crosapi::mojom::ProbeAudioInputNodeInfoPtr input); + +chromeos::api::os_telemetry::AudioOutputNodeInfo UncheckedConvertPtr( + crosapi::mojom::ProbeAudioOutputNodeInfoPtr input); + +chromeos::api::os_telemetry::AudioInfo UncheckedConvertPtr( + crosapi::mojom::ProbeAudioInfoPtr input); + chromeos::api::os_telemetry::CpuCStateInfo UncheckedConvertPtr( crosapi::mojom::ProbeCpuCStateInfoPtr input);
diff --git a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters_unittest.cc b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters_unittest.cc index 8a510bd..c19f9cf9 100644 --- a/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters_unittest.cc +++ b/chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters_unittest.cc
@@ -30,6 +30,168 @@ namespace converters { +TEST(TelemetryApiConverters, AudioInputNodeInfo) { + constexpr uint64_t kId = 42; + constexpr char kName[] = "Internal Mic"; + constexpr char kDeviceName[] = "HDA Intel PCH: CA0132 Analog:0,0"; + constexpr bool kActive = true; + constexpr uint8_t kNodeGain = 1; + + auto input = telemetry_service::ProbeAudioInputNodeInfo::New(); + input->id = crosapi::mojom::UInt64Value::New(kId); + input->name = kName; + input->device_name = kDeviceName; + input->active = crosapi::mojom::BoolValue::New(kActive); + input->node_gain = crosapi::mojom::UInt8Value::New(kNodeGain); + + auto result = ConvertPtr<telemetry_api::AudioInputNodeInfo>(std::move(input)); + + ASSERT_TRUE(result.id); + EXPECT_EQ(kId, static_cast<uint64_t>(*result.id)); + + ASSERT_TRUE(result.name); + EXPECT_EQ(kName, *result.name); + + ASSERT_TRUE(result.device_name); + EXPECT_EQ(kDeviceName, *result.device_name); + + ASSERT_TRUE(result.active); + EXPECT_EQ(kActive, *result.active); + + ASSERT_TRUE(result.node_gain); + EXPECT_EQ(kNodeGain, static_cast<uint8_t>(*result.node_gain)); +} + +TEST(TelemetryApiConverters, AudioOutputNodeInfo) { + constexpr uint64_t kId = 42; + constexpr char kName[] = "Internal Speaker"; + constexpr char kDeviceName[] = "HDA Intel PCH: CA0132 Analog:0,0"; + constexpr bool kActive = true; + constexpr uint8_t kNodeVolume = 242; + + auto input = telemetry_service::ProbeAudioOutputNodeInfo::New(); + input->id = crosapi::mojom::UInt64Value::New(kId); + input->name = kName; + input->device_name = kDeviceName; + input->active = crosapi::mojom::BoolValue::New(kActive); + input->node_volume = crosapi::mojom::UInt8Value::New(kNodeVolume); + + auto result = + ConvertPtr<telemetry_api::AudioOutputNodeInfo>(std::move(input)); + + ASSERT_TRUE(result.id); + EXPECT_EQ(kId, static_cast<uint64_t>(*result.id)); + + ASSERT_TRUE(result.name); + EXPECT_EQ(kName, *result.name); + + ASSERT_TRUE(result.device_name); + EXPECT_EQ(kDeviceName, *result.device_name); + + ASSERT_TRUE(result.active); + EXPECT_EQ(kActive, *result.active); + + ASSERT_TRUE(result.node_volume); + EXPECT_EQ(kNodeVolume, static_cast<uint8_t>(*result.node_volume)); +} + +TEST(TelemetryApiConverters, AudioInfo) { + constexpr bool kOutputMute = true; + constexpr bool kInputMute = false; + constexpr uint32_t kUnderruns = 56; + constexpr uint32_t kSevereUnderruns = 3; + + constexpr uint64_t kIdInput = 42; + constexpr char kNameInput[] = "Internal Speaker"; + constexpr char kDeviceNameInput[] = "HDA Intel PCH: CA0132 Analog:0,0"; + constexpr bool kActiveInput = true; + constexpr uint8_t kNodeGainInput = 1; + + constexpr uint64_t kIdOutput = 43; + constexpr char kNameOutput[] = "Extenal Speaker"; + constexpr char kDeviceNameOutput[] = "HDA Intel PCH: CA0132 Analog:1,0"; + constexpr bool kActiveOutput = false; + constexpr uint8_t kNodeVolumeOutput = 212; + + std::vector<telemetry_service::ProbeAudioInputNodeInfoPtr> input_node_info; + auto input_node = telemetry_service::ProbeAudioInputNodeInfo::New(); + input_node->id = crosapi::mojom::UInt64Value::New(kIdInput); + input_node->name = kNameInput; + input_node->device_name = kDeviceNameInput; + input_node->active = crosapi::mojom::BoolValue::New(kActiveInput); + input_node->node_gain = crosapi::mojom::UInt8Value::New(kNodeGainInput); + input_node_info.push_back(std::move(input_node)); + + std::vector<telemetry_service::ProbeAudioOutputNodeInfoPtr> output_node_info; + auto output_node = telemetry_service::ProbeAudioOutputNodeInfo::New(); + output_node->id = crosapi::mojom::UInt64Value::New(kIdOutput); + output_node->name = kNameOutput; + output_node->device_name = kDeviceNameOutput; + output_node->active = crosapi::mojom::BoolValue::New(kActiveOutput); + output_node->node_volume = crosapi::mojom::UInt8Value::New(kNodeVolumeOutput); + output_node_info.push_back(std::move(output_node)); + + auto input = telemetry_service::ProbeAudioInfo::New(); + input->output_mute = crosapi::mojom::BoolValue::New(kOutputMute); + input->input_mute = crosapi::mojom::BoolValue::New(kInputMute); + input->underruns = crosapi::mojom::UInt32Value::New(kUnderruns); + input->severe_underruns = crosapi::mojom::UInt32Value::New(kSevereUnderruns); + input->output_nodes = std::move(output_node_info); + input->input_nodes = std::move(input_node_info); + + auto result = ConvertPtr<telemetry_api::AudioInfo>(std::move(input)); + + ASSERT_TRUE(result.output_mute); + EXPECT_EQ(kOutputMute, *result.output_mute); + + ASSERT_TRUE(result.input_mute); + EXPECT_EQ(kInputMute, *result.input_mute); + + ASSERT_TRUE(result.underruns); + EXPECT_EQ(kUnderruns, static_cast<uint32_t>(*result.underruns)); + + ASSERT_TRUE(result.severe_underruns); + EXPECT_EQ(kSevereUnderruns, static_cast<uint32_t>(*result.severe_underruns)); + + auto result_output_nodes = std::move(result.output_nodes); + ASSERT_EQ(result_output_nodes.size(), 1UL); + + ASSERT_TRUE(result_output_nodes[0].id); + EXPECT_EQ(kIdOutput, static_cast<uint64_t>(*result_output_nodes[0].id)); + + ASSERT_TRUE(result_output_nodes[0].name); + EXPECT_EQ(kNameOutput, *result_output_nodes[0].name); + + ASSERT_TRUE(result_output_nodes[0].device_name); + EXPECT_EQ(kDeviceNameOutput, *result_output_nodes[0].device_name); + + ASSERT_TRUE(result_output_nodes[0].active); + EXPECT_EQ(kActiveOutput, *result_output_nodes[0].active); + + ASSERT_TRUE(result_output_nodes[0].node_volume); + EXPECT_EQ(kNodeVolumeOutput, + static_cast<uint8_t>(*result_output_nodes[0].node_volume)); + + auto result_input_nodes = std::move(result.input_nodes); + ASSERT_EQ(result_input_nodes.size(), 1UL); + + ASSERT_TRUE(result_input_nodes[0].id); + EXPECT_EQ(kIdInput, static_cast<uint64_t>(*result_input_nodes[0].id)); + + ASSERT_TRUE(result_input_nodes[0].name); + EXPECT_EQ(kNameInput, *result_input_nodes[0].name); + + ASSERT_TRUE(result_input_nodes[0].device_name); + EXPECT_EQ(kDeviceNameInput, *result_input_nodes[0].device_name); + + ASSERT_TRUE(result_input_nodes[0].active); + EXPECT_EQ(kActiveInput, *result_input_nodes[0].active); + + ASSERT_TRUE(result_input_nodes[0].node_gain); + EXPECT_EQ(kNodeGainInput, + static_cast<uint8_t>(*result_input_nodes[0].node_gain)); +} + TEST(TelemetryApiConverters, CpuArchitectureEnum) { EXPECT_EQ(telemetry_api::CpuArchitectureEnum::CPU_ARCHITECTURE_ENUM_UNKNOWN, Convert(telemetry_service::ProbeCpuArchitectureEnum::kUnknown));
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.cc b/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.cc index aed4e1da..6982d0f4 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.h" +#include "base/functional/bind.h" +#include "base/functional/callback_forward.h" #include "base/process/process_handle.h" +#include "base/task/bind_post_task.h" #include "chrome/browser/chromeos/policy/dlp/dlp_file_access_copy_or_move_delegate_factory.h" #include "chromeos/dbus/dlp/dlp_client.h" #include "content/public/browser/browser_task_traits.h" @@ -16,6 +19,7 @@ dlp::RequestFileAccessRequest PrepareBaseRequestFileAccessRequest( const std::vector<base::FilePath>& files) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); dlp::RequestFileAccessRequest request; for (const auto& file : files) request.add_files_paths(file.value()); @@ -24,29 +28,65 @@ return request; } +void RequestFileAccessForSystem( + const std::vector<base::FilePath>& files, + base::OnceCallback<void(file_access::ScopedFileAccess)> callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (file_access::ScopedFileAccessDelegate::HasInstance()) { + file_access::ScopedFileAccessDelegate::Get()->RequestFilesAccessForSystem( + files, base::BindPostTask(content::GetIOThreadTaskRunner({}), + std::move(callback))); + } else { + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + file_access::ScopedFileAccess::Allowed())); + } +} + } // namespace // static void DlpScopedFileAccessDelegate::Initialize(chromeos::DlpClient* client) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!HasInstance()) { new DlpScopedFileAccessDelegate(client); } + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce([]() { + if (!request_files_access_for_system_io_callback_) { + request_files_access_for_system_io_callback_ = + new file_access::ScopedFileAccessDelegate:: + RequestFilesAccessForSystemIOCallback(base::BindPostTask( + content::GetUIThreadTaskRunner({}), + base::BindRepeating(&RequestFileAccessForSystem))); + } + })); } DlpScopedFileAccessDelegate::DlpScopedFileAccessDelegate( chromeos::DlpClient* client) : client_(client), weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DlpFileAccessCopyOrMoveDelegateFactory::Initialize(); } DlpScopedFileAccessDelegate::~DlpScopedFileAccessDelegate() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DlpFileAccessCopyOrMoveDelegateFactory::DeleteInstance(); + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce([]() { + if (request_files_access_for_system_io_callback_) { + delete request_files_access_for_system_io_callback_; + request_files_access_for_system_io_callback_ = nullptr; + } + })); } void DlpScopedFileAccessDelegate::RequestFilesAccess( const std::vector<base::FilePath>& files, const GURL& destination_url, base::OnceCallback<void(file_access::ScopedFileAccess)> callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!client_->IsAlive()) { std::move(callback).Run(file_access::ScopedFileAccess::Allowed()); return; @@ -62,6 +102,7 @@ void DlpScopedFileAccessDelegate::RequestFilesAccessForSystem( const std::vector<base::FilePath>& files, base::OnceCallback<void(file_access::ScopedFileAccess)> callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!client_->IsAlive()) { std::move(callback).Run(file_access::ScopedFileAccess::Allowed()); return; @@ -77,21 +118,18 @@ void DlpScopedFileAccessDelegate::PostRequestFileAccessToDaemon( const ::dlp::RequestFileAccessRequest request, base::OnceCallback<void(file_access::ScopedFileAccess)> callback) { - // base::Unretained is safe as |client_| (global dbus singleton) outlives the - // usage of |callback|. - auto dbus_cb = base::BindOnce( - &chromeos::DlpClient::RequestFileAccess, base::Unretained(client_), + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + client_->RequestFileAccess( request, base::BindOnce(&DlpScopedFileAccessDelegate::OnResponse, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); - - content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(dbus_cb)); } void DlpScopedFileAccessDelegate::OnResponse( base::OnceCallback<void(file_access::ScopedFileAccess)> callback, const dlp::RequestFileAccessResponse response, base::ScopedFD fd) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (response.has_error_message()) { std::move(callback).Run(file_access::ScopedFileAccess::Allowed()); return;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate_unittest.cc index f11b9c2..65b09a3 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate_unittest.cc
@@ -7,12 +7,14 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" +#include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" -#include "base/task/thread_pool/thread_pool_instance.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "chromeos/dbus/dlp/fake_dlp_client.h" #include "components/file_access/file_access_copy_or_move_delegate_factory.h" +#include "components/file_access/scoped_file_access.h" #include "components/file_access/scoped_file_access_delegate.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -92,11 +94,13 @@ class DlpScopedFileAccessDelegateTaskTest : public testing::Test { public: - content::BrowserTaskEnvironment browser_task_environment_; + content::BrowserTaskEnvironment browser_task_environment_{ + content::BrowserTaskEnvironment::REAL_IO_THREAD}; + base::RunLoop run_loop_; chromeos::FakeDlpClient fake_dlp_client_; - scoped_refptr<base::SingleThreadTaskRunner> UIThread_ = + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_ = content::GetUIThreadTaskRunner({}); - scoped_refptr<base::SingleThreadTaskRunner> IOThread_ = + scoped_refptr<base::SingleThreadTaskRunner> io_thread_ = content::GetIOThreadTaskRunner({}); void SetUp() override { @@ -107,14 +111,14 @@ void TestPreInit() { EXPECT_FALSE( file_access::FileAccessCopyOrMoveDelegateFactory::HasInstance()); - UIThread_->PostTask( + ui_thread_->PostTask( FROM_HERE, base::BindOnce(&DlpScopedFileAccessDelegateTaskTest::Init, base::Unretained(this))); } void Init() { DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_); - IOThread_->PostTask( + io_thread_->PostTask( FROM_HERE, base::BindOnce(&DlpScopedFileAccessDelegateTaskTest::TestPostInit, base::Unretained(this))); @@ -123,14 +127,14 @@ void TestPostInit() { EXPECT_TRUE( file_access::FileAccessCopyOrMoveDelegateFactory::HasInstance()); - UIThread_->PostTask( + ui_thread_->PostTask( FROM_HERE, base::BindOnce(&DlpScopedFileAccessDelegateTaskTest::Delete, base::Unretained(this))); } void Delete() { file_access::ScopedFileAccessDelegate::DeleteInstance(); - IOThread_->PostTask( + io_thread_->PostTask( FROM_HERE, base::BindOnce(&DlpScopedFileAccessDelegateTaskTest::TestPostDelete, base::Unretained(this))); @@ -139,15 +143,126 @@ void TestPostDelete() { EXPECT_FALSE( file_access::FileAccessCopyOrMoveDelegateFactory::HasInstance()); + run_loop_.Quit(); } }; TEST_F(DlpScopedFileAccessDelegateTaskTest, TestSync) { - IOThread_->PostTask( + io_thread_->PostTask( FROM_HERE, base::BindOnce(&DlpScopedFileAccessDelegateTaskTest::TestPreInit, base::Unretained(this))); - browser_task_environment_.RunUntilIdle(); + run_loop_.Run(); +} + +TEST_F(DlpScopedFileAccessDelegateTaskTest, + TestGetFilesAccessForSystemIONoInstance) { + base::FilePath file_path; + base::CreateTemporaryFile(&file_path); + io_thread_->PostTask( + FROM_HERE, base::BindLambdaForTesting([this, &file_path]() { + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + {file_path}, base::BindLambdaForTesting( + [this](file_access::ScopedFileAccess file_access) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + EXPECT_TRUE(file_access.is_allowed()); + run_loop_.Quit(); + })); + })); + run_loop_.Run(); +} + +// This test should simulate calling RequestFilesAccessForSystemIO with existing +// callback for the IO thread but destructed DlpScopedFileAccessDelegate on the +// UI thread. +TEST_F(DlpScopedFileAccessDelegateTaskTest, + TestGetFilesAccessForSystemIODestroyedInstance) { + base::FilePath file_path; + base::CreateTemporaryFile(&file_path); + DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_); + // Dlp would disallow but missing ScopedFileAccessDelegate should fall back to + // allow. + fake_dlp_client_.SetFileAccessAllowed(false); + + // Post a task on IO thread to sync with to be sure the IO task setting + // `request_files_access_for_system_io_callback_` has run. + base::RunLoop init; + io_thread_->PostTask( + FROM_HERE, base::BindOnce(&base::RunLoop::Quit, base::Unretained(&init))); + init.Run(); + + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIOCallback* + original_callback; + + // Callback that calls the original + // request_files_access_for_system_io_callback_ after destructing + // DlpScopedFileAccessDelegate. + auto decorated_callback = base::BindLambdaForTesting( + [this, &original_callback]( + const std::vector<base::FilePath>& path, + base::OnceCallback<void(file_access::ScopedFileAccess)> callback) { + ui_thread_->PostTask( + FROM_HERE, + base::BindOnce( + &file_access::ScopedFileAccessDelegate::DeleteInstance)); + original_callback->Run(path, std::move(callback)); + }); + + original_callback = file_access::ScopedFileAccessDelegate:: + SetRequestFilesAccessForSystemIOCallbackForTesting(decorated_callback); + + // The request for file access should be granted as that is the default + // behaviour for no running dlp (no rules). + io_thread_->PostTask( + FROM_HERE, base::BindLambdaForTesting([this, &file_path]() { + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + {file_path}, base::BindLambdaForTesting( + [this](file_access::ScopedFileAccess file_access) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + EXPECT_TRUE(file_access.is_allowed()); + run_loop_.Quit(); + })); + })); + run_loop_.Run(); + delete original_callback; +} + +TEST_F(DlpScopedFileAccessDelegateTaskTest, + TestGetFilesAccessForSystemIOAllow) { + DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_); + base::FilePath file_path; + base::CreateTemporaryFile(&file_path); + fake_dlp_client_.SetFileAccessAllowed(true); + io_thread_->PostTask( + FROM_HERE, base::BindLambdaForTesting([this, &file_path]() { + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + {file_path}, base::BindLambdaForTesting( + [this](file_access::ScopedFileAccess file_access) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + EXPECT_TRUE(file_access.is_allowed()); + run_loop_.Quit(); + })); + })); + run_loop_.Run(); +} + +TEST_F(DlpScopedFileAccessDelegateTaskTest, + TestGetFilesAccessForSystemIODisallow) { + DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_); + base::FilePath file_path; + base::CreateTemporaryFile(&file_path); + fake_dlp_client_.SetFileAccessAllowed(false); + io_thread_->PostTask( + FROM_HERE, base::BindLambdaForTesting([this, &file_path]() { + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + {file_path}, base::BindLambdaForTesting( + [this](file_access::ScopedFileAccess file_access) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + EXPECT_FALSE(file_access.is_allowed()); + run_loop_.Quit(); + })); + })); + run_loop_.Run(); } } // namespace policy
diff --git a/chrome/browser/component_updater/recovery_improved_component_installer.cc b/chrome/browser/component_updater/recovery_improved_component_installer.cc index d5da1ea..1d1ebce 100644 --- a/chrome/browser/component_updater/recovery_improved_component_installer.cc +++ b/chrome/browser/component_updater/recovery_improved_component_installer.cc
@@ -29,12 +29,18 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "base/types/expected.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/component_updater/component_updater_utils.h" #include "components/services/unzip/content/unzip_service.h" #include "components/update_client/patcher.h" #include "components/update_client/unzip/unzip_impl.h" +#if BUILDFLAG(IS_POSIX) +#include <errno.h> +#endif + namespace component_updater { constexpr base::TaskTraits @@ -98,30 +104,48 @@ void RecoveryComponentActionHandler::RunCommand( const base::CommandLine& cmdline) { VLOG(1) << "run command: " << cmdline.GetCommandLineString(); - base::LaunchOptions options; + base::expected<base::Process, int> process_or_error = + [&cmdline]() -> base::expected<base::Process, int> { + base::LaunchOptions options; #if BUILDFLAG(IS_WIN) - options.start_hidden = true; + options.start_hidden = true; #endif - base::Process process = base::LaunchProcess(cmdline, options); + base::Process process = base::LaunchProcess(cmdline, options); + if (!process.IsValid()) { +#if BUILDFLAG(IS_WIN) + return base::unexpected(::GetLastError()); +#elif BUILDFLAG(IS_POSIX) + return base::unexpected(errno); +#else + return base::unexpected(0); +#endif + } + return base::ok(std::move(process)); + }(); base::ThreadPool::PostTask( FROM_HERE, kThreadPoolTaskTraitsRunCommand, base::BindOnce(&RecoveryComponentActionHandler::WaitForCommand, this, - std::move(process))); + std::move(process_or_error))); } -void RecoveryComponentActionHandler::WaitForCommand(base::Process process) { +void RecoveryComponentActionHandler::WaitForCommand( + base::expected<base::Process, int> process_or_error) { int exit_code = 0; - const base::TimeDelta kMaxWaitTime = base::Seconds(600); + int extra_code1 = 0; bool succeeded = false; - if (!process.IsValid()) { + constexpr base::TimeDelta kMaxWaitTime = base::Seconds(600); + if (process_or_error.has_value()) { + succeeded = + process_or_error->WaitForExitWithTimeout(kMaxWaitTime, &exit_code); + } else { exit_code = static_cast<int>(update_client::InstallError::LAUNCH_PROCESS_FAILED); - } else { - succeeded = process.WaitForExitWithTimeout(kMaxWaitTime, &exit_code); + extra_code1 = process_or_error.error(); } base::DeletePathRecursively(unpack_path_); main_task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), succeeded, exit_code, 0)); + FROM_HERE, + base::BindOnce(std::move(callback_), succeeded, exit_code, extra_code1)); } // The SHA256 of the SubjectPublicKeyInfo used to sign the component CRX.
diff --git a/chrome/browser/component_updater/recovery_improved_component_installer.h b/chrome/browser/component_updater/recovery_improved_component_installer.h index 7b6301c8..f9b805a1 100644 --- a/chrome/browser/component_updater/recovery_improved_component_installer.h +++ b/chrome/browser/component_updater/recovery_improved_component_installer.h
@@ -16,6 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" +#include "base/types/expected.h" #include "base/values.h" #include "components/component_updater/component_installer.h" #include "components/crx_file/crx_verifier.h" @@ -110,7 +111,11 @@ void Unpack(); void UnpackComplete(const update_client::ComponentUnpacker::Result& result); void RunCommand(const base::CommandLine& cmdline); - void WaitForCommand(base::Process process); + + // `process` contains the process object, if the process was successfully + // created or an error value otherwise (if the error is available on that + // platform). + void WaitForCommand(base::expected<base::Process, int> process_or_error); SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc index 44ede47..3c075e6 100644 --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc
@@ -6,9 +6,12 @@ #include "base/feature_list.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/metrics/histogram_functions.h" #include "base/path_service.h" +#include "base/task/thread_pool.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -149,6 +152,15 @@ // Clean up any desktop sharing hubs that were installed on Android. component_updater::DeleteDesktopSharingHub(path); #endif // BUILDFLAG(IS_ANDROID) + +#if BUILDFLAG(IS_WIN) + // TODO(crbug/1407233): Remove this call once it has rolled out for a few + // milestones + base::ThreadPool::PostTask( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, + base::GetDeleteFileCallback( + path.Append(FILE_PATH_LITERAL("SwReporter")))); +#endif // BUILDFLAG(IS_WIN) } RegisterSSLErrorAssistantComponent(cus); @@ -169,16 +181,9 @@ RegisterOriginTrialsComponent(cus); RegisterMediaEngagementPreloadComponent(cus, base::OnceClosure()); -#if BUILDFLAG(IS_WIN) - // SwReporter is only needed for official builds. However, to enable testing - // on chromium build bots, it is always registered here and - // RegisterSwReporterComponent() has support for running only in official - // builds or tests. - RegisterSwReporterComponent(cus, g_browser_process->local_state()); -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) RegisterThirdPartyModuleListComponent(cus); -#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) -#endif // BUILDFLAG(IS_WIN) +#endif // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) MaybeRegisterPKIMetadataComponent(cus);
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc index ff7c129..bc15b40 100644 --- a/chrome/browser/content_settings/content_settings_browsertest.cc +++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -873,11 +873,12 @@ void SetUpCommandLine(base::CommandLine* command_line) override { scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kBackForwardCache, - {// Set a very long TTL before expiration (longer than the test - // timeout) so tests that are expecting deletion don't pass when - // they shouldn't. - {"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"ignore_outstanding_network_request_for_testing", "true"}}}}, + {{"ignore_outstanding_network_request_for_testing", "true"}}}, + // Set a very long TTL before expiration (longer than the test + // timeout) so tests that are expecting deletion don't pass when + // they shouldn't. + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); ContentSettingsTest::SetUpCommandLine(command_line);
diff --git a/chrome/browser/content_settings/content_settings_supervised_provider.cc b/chrome/browser/content_settings/content_settings_supervised_provider.cc index 6cd52e2b..b29f31a 100644 --- a/chrome/browser/content_settings/content_settings_supervised_provider.cc +++ b/chrome/browser/content_settings/content_settings_supervised_provider.cc
@@ -10,8 +10,8 @@ #include "base/functional/bind.h" #include "base/values.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" namespace {
diff --git a/chrome/browser/content_settings/content_settings_supervised_provider_unittest.cc b/chrome/browser/content_settings/content_settings_supervised_provider_unittest.cc index 5597cb710..03b20c1 100644 --- a/chrome/browser/content_settings/content_settings_supervised_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_supervised_provider_unittest.cc
@@ -8,12 +8,12 @@ #include <string> #include "chrome/browser/content_settings/content_settings_mock_observer.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "components/content_settings/core/browser/content_settings_rule.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/prefs/testing_pref_store.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_;
diff --git a/chrome/browser/custom_handlers/chrome_protocol_handler_registry_delegate.cc b/chrome/browser/custom_handlers/chrome_protocol_handler_registry_delegate.cc index 836c60f..547c21d 100644 --- a/chrome/browser/custom_handlers/chrome_protocol_handler_registry_delegate.cc +++ b/chrome/browser/custom_handlers/chrome_protocol_handler_registry_delegate.cc
@@ -75,7 +75,7 @@ // difference (http://crbug.com/88255). return false; #else - return shell_integration::GetDefaultWebClientSetPermission() != + return shell_integration::GetDefaultSchemeClientSetPermission() != shell_integration::SET_DEFAULT_NOT_ALLOWED; #endif }
diff --git a/chrome/browser/devtools/protocol/form_devtools_issues_browsertest.cc b/chrome/browser/devtools/protocol/form_devtools_issues_browsertest.cc index 38666c91..84621f0 100644 --- a/chrome/browser/devtools/protocol/form_devtools_issues_browsertest.cc +++ b/chrome/browser/devtools/protocol/form_devtools_issues_browsertest.cc
@@ -99,4 +99,15 @@ .has_value()); } +IN_PROC_BROWSER_TEST_F(AutofillFormDevtoolsProtocolTest, + FormHasInputWithoutIdAndName) { + NavigateToFormPageAndEnableAudits(); + base::Value::Dict notification = + WaitForGenericIssueAdded("FormEmptyIdAndNameAttributesForInputError"); + EXPECT_TRUE(notification + .FindIntByDottedPath( + "issue.details.genericIssueDetails.violatingNodeId") + .has_value()); +} + } // namespace autofill
diff --git a/chrome/browser/dips/dips_service.cc b/chrome/browser/dips/dips_service.cc index 07659270..60ad7f55 100644 --- a/chrome/browser/dips/dips_service.cc +++ b/chrome/browser/dips/dips_service.cc
@@ -197,13 +197,38 @@ } bool DIPSService::ShouldBlockThirdPartyCookies() const { - if (!cookie_settings_) { + if (IsShuttingDown()) { return cached_should_block_3pcs_.value(); } return cookie_settings_->ShouldBlockThirdPartyCookies(); } +bool DIPSService::HasCookieException(const std::string& site) const { + DCHECK(!IsShuttingDown()); + GURL url("https://" + site); + + // Checks whether there is an exception allowing all third-parties embedded + // under |site| to use cookies. + if (cookie_settings_->IsFullCookieAccessAllowed( + GURL(), net::SiteForCookies::FromUrl(url), url::Origin::Create(url), + net::CookieSettingOverrides(), + content_settings::CookieSettingsBase::QueryReason::kCookies)) { + return true; + } + + // Checks whether there is an exception allowing |site| to use cookies when + // embedded by any other site. + if (cookie_settings_->IsFullCookieAccessAllowed( + url, net::SiteForCookies(), absl::nullopt, + net::CookieSettingOverrides(), + content_settings::CookieSettingsBase::QueryReason::kCookies)) { + return true; + } + + return false; +} + DIPSCookieMode DIPSService::GetCookieMode() const { return GetDIPSCookieMode(browser_context_->IsOffTheRecord(), ShouldBlockThirdPartyCookies()); @@ -344,16 +369,30 @@ } if (ShouldBlockThirdPartyCookies() && dips::kDeletionEnabled.Get()) { - // TODO: Check for site-specific third-party cookie exceptions here and - // exclude sites with them from 'sites_to_clear' then call - // 'DIPSStorage::RemoveRows' to remove the DIPS entries for the excluded - // sites. - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce( - &DIPSService::RunDeletionTaskOnUIThread, weak_factory_.GetWeakPtr(), - std::move(sites_to_clear), - base::BindOnce(&UmaHistogramDeletionLatency, deletion_start))); + if (IsShuttingDown()) { + return; + } + + std::vector<std::string> excepted_sites; + std::vector<std::string> non_excepted_sites; + + for (const auto& site : sites_to_clear) { + if (HasCookieException(site)) { + excepted_sites.push_back(site); + } else { + non_excepted_sites.push_back(site); + } + } + + if (excepted_sites.empty()) { + PostDeletionTaskToUIThread(deletion_start, std::move(non_excepted_sites)); + } else { + storage_.AsyncCall(&DIPSStorage::RemoveRows) + .WithArgs(std::move(excepted_sites)) + .Then(base::BindOnce(&DIPSService::PostDeletionTaskToUIThread, + weak_factory_.GetWeakPtr(), deletion_start, + std::move(non_excepted_sites))); + } } else { storage_.AsyncCall(&DIPSStorage::RemoveRows) .WithArgs(std::move(sites_to_clear)) @@ -361,10 +400,8 @@ } } -void DIPSService::RunDeletionTaskOnUIThread(std::vector<std::string> sites, - base::OnceClosure callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - +void DIPSService::PostDeletionTaskToUIThread(base::Time deletion_start, + std::vector<std::string> sites) { std::unique_ptr<content::BrowsingDataFilterBuilder> filter = content::BrowsingDataFilterBuilder::Create( content::BrowsingDataFilterBuilder::Mode::kDelete); @@ -372,6 +409,18 @@ filter->AddRegisterableDomain(site); } + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&DIPSService::RunDeletionTaskOnUIThread, + weak_factory_.GetWeakPtr(), std::move(filter), + base::BindOnce(&UmaHistogramDeletionLatency, + deletion_start))); +} + +void DIPSService::RunDeletionTaskOnUIThread( + std::unique_ptr<content::BrowsingDataFilterBuilder> filter, + base::OnceClosure callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + StateClearer::DeleteState(browser_context_->GetBrowsingDataRemover(), std::move(filter), std::move(callback)); }
diff --git a/chrome/browser/dips/dips_service.h b/chrome/browser/dips/dips_service.h index e4382ec..99b3903 100644 --- a/chrome/browser/dips/dips_service.h +++ b/chrome/browser/dips/dips_service.h
@@ -14,6 +14,7 @@ #include "chrome/browser/dips/dips_storage.h" #include "chrome/browser/dips/dips_utils.h" #include "components/keyed_service/core/keyed_service.h" +#include "content/public/browser/browsing_data_filter_builder.h" class Profile; @@ -72,6 +73,7 @@ std::unique_ptr<signin::PersistentRepeatingTimer> CreateTimer( Profile* profile); void Shutdown() override; + bool IsShuttingDown() const { return !cookie_settings_; } void GotState(std::vector<DIPSRedirectInfoPtr> redirects, DIPSRedirectChainInfoPtr chain, @@ -89,9 +91,14 @@ void OnTimerFired(); void DeleteDIPSEligibleState(base::Time deletion_start, std::vector<std::string> sites_to_clear); - void RunDeletionTaskOnUIThread(std::vector<std::string> sites_to_clear, - base::OnceClosure callback); + void PostDeletionTaskToUIThread(base::Time deletion_start, + std::vector<std::string> sites_to_clear); + void RunDeletionTaskOnUIThread( + std::unique_ptr<content::BrowsingDataFilterBuilder> filter, + base::OnceClosure callback); + bool ShouldBlockThirdPartyCookies() const; + bool HasCookieException(const std::string& site) const; raw_ptr<content::BrowserContext> browser_context_; scoped_refptr<content_settings::CookieSettings> cookie_settings_;
diff --git a/chrome/browser/dips/dips_service_unittest.cc b/chrome/browser/dips/dips_service_unittest.cc index 1e446adb..12cbcfa 100644 --- a/chrome/browser/dips/dips_service_unittest.cc +++ b/chrome/browser/dips/dips_service_unittest.cc
@@ -10,12 +10,18 @@ #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h" +#include "chrome/browser/content_settings/cookie_settings_factory.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/dips/dips_features.h" #include "chrome/browser/dips/dips_service_factory.h" #include "chrome/browser/dips/dips_state.h" #include "chrome/browser/dips/dips_utils.h" #include "chrome/browser/profiles/profile_test_util.h" #include "chrome/test/base/testing_profile.h" +#include "components/content_settings/core/browser/cookie_settings.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/pref_names.h" +#include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/mock_browsing_data_remover_delegate.h" #include "testing/gtest/include/gtest/gtest.h" @@ -82,19 +88,28 @@ class DIPSServiceStateRemovalTest : public testing::Test { public: DIPSServiceStateRemovalTest() - : base_profile_(std::make_unique<TestingProfile>()), - incognito_profile_( - TestingProfile::Builder().BuildIncognito(base_profile_.get())) {} + : profile_(std::make_unique<TestingProfile>()), + cookie_settings_( + CookieSettingsFactory::GetForProfile(GetProfile()).get()), + service_(DIPSService::Get(profile_.get())) {} base::TimeDelta grace_period; base::TimeDelta interaction_ttl; base::TimeDelta tiny_delta = base::Milliseconds(1); - // These methods rely on the incognito profile since third-party cookies are - // blocked by default in incognito and having them blocked is a condition for - // DIPS to perform deletion. + void SetBlockThirdPartyCookies(bool value) { + GetProfile()->GetPrefs()->SetInteger( + prefs::kCookieControlsMode, + static_cast<int>( + value ? content_settings::CookieControlsMode::kBlockThirdParty + : content_settings::CookieControlsMode::kOff)); + } + DIPSService* GetService() { return service_; } - Profile* GetProfile() { return incognito_profile_; } + Profile* GetProfile() { return profile_.get(); } + content_settings::CookieSettings* GetCookieSettings() { + return cookie_settings_; + } protected: content::BrowserTaskEnvironment task_environment_; @@ -106,17 +121,17 @@ interaction_ttl = dips::kInteractionTtl.Get(); ASSERT_LT(tiny_delta, grace_period); - incognito_profile_->GetBrowsingDataRemover()->SetEmbedderDelegate( - &delegate_); + GetProfile()->GetBrowsingDataRemover()->SetEmbedderDelegate(&delegate_); + SetBlockThirdPartyCookies(true); + ASSERT_TRUE(GetCookieSettings()->ShouldBlockThirdPartyCookies()); - service_ = DIPSService::Get(incognito_profile_); DCHECK(service_); service_->SetStorageClockForTesting(&clock_); - service_->storage()->FlushPostedTasksForTesting(); + WaitOnStorage(); } void TearDown() override { - base_profile_.reset(); + profile_.reset(); base::RunLoop().RunUntilIdle(); } @@ -155,8 +170,8 @@ private: base::SimpleTestClock clock_; - std::unique_ptr<TestingProfile> base_profile_; - raw_ptr<TestingProfile> incognito_profile_ = nullptr; + std::unique_ptr<TestingProfile> profile_; + raw_ptr<content_settings::CookieSettings> cookie_settings_ = nullptr; raw_ptr<DIPSService> service_ = nullptr; }; @@ -248,6 +263,101 @@ EXPECT_FALSE(GetDIPSState(url).has_value()); } +TEST_F(DIPSServiceStateRemovalTest, + BrowsingDataDeletion_Respects3PCExceptions) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + dips::kFeature, {{"delete", "true"}, {"triggering_action", "bounce"}}); + + GURL excepted_3p_url("https://excepted-as-3p.com"); + GURL excepted_1p_url("https://excepted-as-1p.com"); + GURL non_excepted_url("https://not-excepted.com"); + + HostContentSettingsMap* map = + HostContentSettingsMapFactory::GetForProfile(GetProfile()); + + // Add exception to third-party cookie blocking rule for + // 'excepted_3p_url' in third-part context. + map->SetContentSettingCustomScope( + ContentSettingsPattern::FromString("[*.]" + excepted_3p_url.host()), + ContentSettingsPattern::Wildcard(), ContentSettingsType::COOKIES, + ContentSetting::CONTENT_SETTING_ALLOW); + + // Add exception to third-party cookie blocking rule for third-parties + // embedded by 'excepted_1p_url'. + map->SetContentSettingCustomScope( + ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::FromString("[*.]" + excepted_1p_url.host()), + ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_ALLOW); + + // Verify settings. + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetCookieSettings()->GetCookieSetting( + excepted_3p_url, GURL(), net::CookieSettingOverrides(), nullptr, + content_settings::CookieSettingsBase::QueryReason::kCookies)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetCookieSettings()->GetCookieSetting( + GURL(), excepted_3p_url, net::CookieSettingOverrides(), nullptr, + content_settings::CookieSettingsBase::QueryReason::kCookies)); + + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetCookieSettings()->GetCookieSetting( + excepted_1p_url, GURL(), net::CookieSettingOverrides(), nullptr, + content_settings::CookieSettingsBase::QueryReason::kCookies)); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetCookieSettings()->GetCookieSetting( + GURL(), excepted_1p_url, net::CookieSettingOverrides(), nullptr, + content_settings::CookieSettingsBase::QueryReason::kCookies)); + + // Record bounces for sites. + base::Time bounce = base::Time::FromDoubleT(2); + GetService() + ->storage() + ->AsyncCall(&DIPSStorage::RecordBounce) + .WithArgs(excepted_3p_url, bounce, false); + GetService() + ->storage() + ->AsyncCall(&DIPSStorage::RecordBounce) + .WithArgs(excepted_1p_url, bounce, false); + GetService() + ->storage() + ->AsyncCall(&DIPSStorage::RecordBounce) + .WithArgs(non_excepted_url, bounce, false); + WaitOnStorage(); + EXPECT_TRUE(GetDIPSState(excepted_3p_url).has_value()); + EXPECT_TRUE(GetDIPSState(excepted_1p_url).has_value()); + EXPECT_TRUE(GetDIPSState(non_excepted_url).has_value()); + + auto filter_builder = content::BrowsingDataFilterBuilder::Create( + content::BrowsingDataFilterBuilder::Mode::kDelete); + filter_builder->AddRegisterableDomain(GetSiteForDIPS(non_excepted_url)); + delegate_.ExpectCall( + base::Time::Min(), base::Time::Max(), + chrome_browsing_data_remover::FILTERABLE_DATA_TYPES | + content::BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS, + content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | + content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB, + filter_builder.get()); + + // Time-travel to after the grace period has ended for the bounce. + AdvanceTimeTo(bounce + grace_period + tiny_delta); + FireDIPSTimer(); + task_environment_.RunUntilIdle(); + + // Verify that a removal task was posted to the BrowsingDataRemover(Delegate) + // for 'non_excepted_url'. + delegate_.VerifyAndClearExpectations(); + // Because this test fixture uses a MockBrowsingDataRemoverDelegate the DIPS + // entry should not actually be removed. However, in practice it would be. + EXPECT_TRUE(GetDIPSState(non_excepted_url).has_value()); + // The DIPS entries for 'excepted_3p_url' and 'excepted_1p_url' should be + // removed, since only DIPS state is cleared for sites with a cookie exception + // and the BrowsingDataRemover(Delegate) isn't relied on for that kind of + // deletion. + EXPECT_FALSE(GetDIPSState(excepted_3p_url).has_value()); + EXPECT_FALSE(GetDIPSState(excepted_1p_url).has_value()); +} + // A test class that verifies DIPSService state deletion metrics collection // behavior. class DIPSServiceHistogramTest : public DIPSServiceStateRemovalTest {
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc index 244127b..e1a7f22 100644 --- a/chrome/browser/engagement/site_engagement_service_unittest.cc +++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -537,14 +537,8 @@ EXPECT_DOUBLE_EQ(0.0, service_->GetScore(url2)); } -// Disabled due to flakiness on Builder Linux Tests. crbug.com/1137759 -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#define MAYBE_CheckHistograms DISABLED_CheckHistograms -#else -#define MAYBE_CheckHistograms CheckHistograms -#endif - -TEST_F(SiteEngagementServiceTest, MAYBE_CheckHistograms) { +// TODO(https://crbug.com/1137759): Flaky test. +TEST_F(SiteEngagementServiceTest, DISABLED_CheckHistograms) { base::HistogramTester histograms; base::Time current_day = GetReferenceTime();
diff --git a/chrome/browser/enterprise/connectors/common.cc b/chrome/browser/enterprise/connectors/common.cc index 2d6874b6..46a850e 100644 --- a/chrome/browser/enterprise/connectors/common.cc +++ b/chrome/browser/enterprise/connectors/common.cc
@@ -162,15 +162,6 @@ ReportingSettings& ReportingSettings::operator=(ReportingSettings&&) = default; ReportingSettings::~ReportingSettings() = default; -FileSystemSettings::FileSystemSettings() = default; -FileSystemSettings::FileSystemSettings(const FileSystemSettings&) = default; -FileSystemSettings::FileSystemSettings(FileSystemSettings&&) = default; -FileSystemSettings& FileSystemSettings::operator=(const FileSystemSettings&) = - default; -FileSystemSettings& FileSystemSettings::operator=(FileSystemSettings&&) = - default; -FileSystemSettings::~FileSystemSettings() = default; - const char* ConnectorPref(AnalysisConnector connector) { switch (connector) { case AnalysisConnector::BULK_DATA_ENTRY:
diff --git a/chrome/browser/enterprise/connectors/common.h b/chrome/browser/enterprise/connectors/common.h index 6f4f185c9..3997cc3 100644 --- a/chrome/browser/enterprise/connectors/common.h +++ b/chrome/browser/enterprise/connectors/common.h
@@ -98,29 +98,6 @@ bool per_profile = false; }; -// Struct holding the necessary data to tweak the behavior of the file system -// Connector. -struct FileSystemSettings { - FileSystemSettings(); - FileSystemSettings(const FileSystemSettings&); - FileSystemSettings(FileSystemSettings&&); - FileSystemSettings& operator=(const FileSystemSettings&); - FileSystemSettings& operator=(FileSystemSettings&&); - ~FileSystemSettings(); - - std::string service_provider; - GURL home; - GURL authorization_endpoint; - GURL token_endpoint; - std::string enterprise_id; - std::string email_domain; - std::string client_id; - std::string client_secret; - std::vector<std::string> scopes; - size_t max_direct_size; - std::set<std::string> mime_types; -}; - // Returns the pref path corresponding to a connector. const char* ConnectorPref(AnalysisConnector connector); const char* ConnectorPref(ReportingConnector connector);
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command.cc index 705aaf59..05d03e44 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command.cc
@@ -8,9 +8,11 @@ #include <utility> #include "base/base64.h" +#include "base/base_paths.h" #include "base/check.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/scoped_refptr.h" @@ -35,15 +37,20 @@ namespace { +base::FilePath GetBinaryFilePath() { + base::FilePath exe_path; + if (base::PathService::Get(base::DIR_EXE, &exe_path)) { + return exe_path.Append(constants::kBinaryFileName); + } + return exe_path; +} + // Builds the command line needed to launch the service. The `params` specify // the needed KeyRotationCommandParams. 'pipe_name` is the name of the pipe to // connect to. base::CommandLine GetCommandLine(const KeyRotationCommand::Params& params, const std::string& pipe_name) { - base::FilePath exe_path; - bool success = base::PathService::Get(base::DIR_EXE, &exe_path); - DCHECK(success); - exe_path = exe_path.Append(constants::kBinaryFileName); + base::FilePath exe_path = GetBinaryFilePath(); base::CommandLine command_line(exe_path); std::string token_base64; @@ -103,6 +110,15 @@ base::BindOnce( [](base::CommandLine command_line, LaunchCallback launch_callback, mojo::OutgoingInvitation invitation) { + if (!base::PathExists(GetBinaryFilePath())) { + SYSLOG(ERROR) + << "Device trust key rotation failed. Could not find " + "management service executable."; + LogKeyRotationCommandError( + KeyRotationCommandError::kMissingManagementService); + return KeyRotationCommand::Status::FAILED_INVALID_INSTALLATION; + } + mojo::PlatformChannel channel; base::LaunchOptions options; options.allow_new_privs = true; @@ -112,6 +128,8 @@ if (!process.IsValid()) { SYSLOG(ERROR) << "Device trust key rotation failed. Could not " "launch the ChromeManagementService process."; + LogKeyRotationCommandError( + KeyRotationCommandError::kProcessInvalid); return KeyRotationCommand::Status::FAILED; } @@ -125,18 +143,28 @@ if (!process.WaitForExitWithTimeout(timeouts::kProcessWaitTimeout, &exit_code)) { SYSLOG(ERROR) << "Device trust key rotation timed out."; + LogKeyRotationCommandError(KeyRotationCommandError::kTimeout); return KeyRotationCommand::Status::TIMED_OUT; } - LogManagementServiceExitCode(exit_code); - if (exit_code == kSuccess) { - return KeyRotationCommand::Status::SUCCEEDED; - } else if (exit_code != kFailure) { - SYSLOG(ERROR) - << "Device trust key rotation failed with exit code: " - << exit_code; + LogKeyRotationExitCode(exit_code); + + switch (exit_code) { + case kSuccess: + return KeyRotationCommand::Status::SUCCEEDED; + case kFailedInsufficientPermissions: + return KeyRotationCommand::Status::FAILED_INVALID_PERMISSIONS; + case kFailedKeyConflict: + return KeyRotationCommand::Status::FAILED_KEY_CONFLICT; + case kFailure: + return KeyRotationCommand::Status::FAILED; + case kUnknownFailure: + default: + SYSLOG(ERROR) + << "Device trust key rotation failed with exit code: " + << exit_code; + return KeyRotationCommand::Status::FAILED; } - return KeyRotationCommand::Status::FAILED; }, command_line, launch_callback_, std::move(invitation)), std::move(callback));
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command_unittest.cc index 1b53ea59..da60a98e 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command_unittest.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/linux_key_rotation_command_unittest.cc
@@ -8,13 +8,17 @@ #include <utility> #include "base/base64.h" +#include "base/base_paths.h" #include "base/command_line.h" +#include "base/files/file_util.h" #include "base/memory/scoped_refptr.h" -#include "base/run_loop.h" +#include "base/path_service.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/multiprocess_test.h" +#include "base/test/scoped_path_override.h" #include "base/test/task_environment.h" +#include "base/test/test_future.h" #include "base/threading/platform_thread.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.h" #include "chrome/browser/enterprise/connectors/device_trust/key_management/core/shared_command_constants.h" @@ -32,11 +36,8 @@ namespace { -constexpr char kManagementServicePositiveExitCodeHistogramName[] = - "Enterprise.DeviceTrust.ManagementService.ExitCode.Positive"; - -constexpr char kManagementServiceNegativeExitCodeHistogramName[] = - "Enterprise.DeviceTrust.ManagementService.ExitCode.Negative"; +constexpr char kExitCodeHistogram[] = + "Enterprise.DeviceTrust.KeyRotationCommand.ExitCode"; constexpr char kNonce[] = "nonce"; @@ -49,10 +50,17 @@ "7C1.2.3&request=browser_public_key_upload"; static constexpr const char* kSwitches[] = { - switches::kRotateDTKey, switches::kDmServerUrl, switches::kPipeName, switches::kNonce, mojo::PlatformChannel::kHandleSwitch}; +base::FilePath GetBinaryFilePath() { + base::FilePath exe_path; + if (base::PathService::Get(base::DIR_EXE, &exe_path)) { + return exe_path.Append(constants::kBinaryFileName); + } + return exe_path; +} + } // namespace class LinuxKeyRotationCommandTest : public testing::Test { @@ -61,6 +69,7 @@ : test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)), + scoped_path_override_(base::DIR_EXE), rotation_command_( LinuxKeyRotationCommand(mock_launch_callback_.Get(), test_shared_loader_factory_)) {} @@ -88,35 +97,43 @@ void StartTestRotation( std::string process_name, - enterprise_connectors::KeyRotationCommand::Status status) { + enterprise_connectors::KeyRotationCommand::Status expected_status) { KeyRotationCommand::Params params = {kFakeDMToken, kFakeDmServerUrl, kNonce}; + CreateManagementServiceBinary(); - base::RunLoop run_loop; EXPECT_CALL(mock_launch_callback_, Run(_, _)) .WillOnce([&process_name](const base::CommandLine& command_line, const base::LaunchOptions& options) { EXPECT_TRUE(options.allow_new_privs); return LaunchTestProcess(process_name, command_line, options); }); - EXPECT_CALL(mock_trigger_callback_, Run(status)) - .WillOnce([&run_loop](KeyRotationCommand::Status status) { - run_loop.Quit(); - }); - rotation_command_.Trigger(params, mock_trigger_callback_.Get()); - run_loop.Run(); + + base::test::TestFuture<KeyRotationCommand::Status> future_status; + rotation_command_.Trigger(params, future_status.GetCallback()); + EXPECT_EQ(future_status.Get(), expected_status); } - base::HistogramTester histogram_tester_; + void CreateManagementServiceBinary() { + ASSERT_TRUE(base::WriteFile(GetBinaryFilePath(), + base::StringPiece("test_content"))); + } - private: + void ExpectCommandErrorHistogram(KeyRotationCommandError error) { + static constexpr char kErrorHistogram[] = + "Enterprise.DeviceTrust.KeyRotationCommand.Error"; + histogram_tester_.ExpectUniqueSample(kErrorHistogram, error, 1); + } + + base::test::TaskEnvironment task_environment_; + base::HistogramTester histogram_tester_; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; + base::ScopedPathOverride scoped_path_override_; base::MockCallback<LinuxKeyRotationCommand::LaunchCallback> mock_launch_callback_; + LinuxKeyRotationCommand rotation_command_; - base::MockCallback<KeyRotationCommand::Callback> mock_trigger_callback_; - base::test::TaskEnvironment task_environment_; }; // Tests for the key mojo invitation where the chrome management service @@ -159,8 +176,7 @@ TEST_F(LinuxKeyRotationCommandTest, MojoAcceptInvitation) { StartTestRotation("MojoInvitation", KeyRotationCommand::Status::SUCCEEDED); - histogram_tester_.ExpectUniqueSample( - kManagementServicePositiveExitCodeHistogramName, Status::kSuccess, 1); + histogram_tester_.ExpectUniqueSample(kExitCodeHistogram, Status::kSuccess, 1); } // Tests for a key rotation when the chrome management service succeeded. @@ -170,8 +186,7 @@ TEST_F(LinuxKeyRotationCommandTest, RotateSuccess) { StartTestRotation("Success", KeyRotationCommand::Status::SUCCEEDED); - histogram_tester_.ExpectUniqueSample( - kManagementServicePositiveExitCodeHistogramName, Status::kSuccess, 1); + histogram_tester_.ExpectUniqueSample(kExitCodeHistogram, Status::kSuccess, 1); } // Tests for a key rotation failure when the chrome management service failed. @@ -181,8 +196,7 @@ TEST_F(LinuxKeyRotationCommandTest, RotateFailure) { StartTestRotation("Failure", KeyRotationCommand::Status::FAILED); - histogram_tester_.ExpectUniqueSample( - kManagementServicePositiveExitCodeHistogramName, Status::kFailure, 1); + histogram_tester_.ExpectUniqueSample(kExitCodeHistogram, Status::kFailure, 1); } // Tests for a key rotation failure when the chrome management service failed @@ -193,24 +207,33 @@ TEST_F(LinuxKeyRotationCommandTest, RotateFailure_UnknownError) { StartTestRotation("UnknownFailure", KeyRotationCommand::Status::FAILED); - histogram_tester_.ExpectUniqueSample( - kManagementServicePositiveExitCodeHistogramName, Status::kUnknownFailure, - 1); + histogram_tester_.ExpectUniqueSample(kExitCodeHistogram, + Status::kUnknownFailure, 1); } // Tests for a key rotation failure when an invalid process was launched. TEST_F(LinuxKeyRotationCommandTest, RotateFailureInvalidProcess) { StartTestRotation("InvalidProcess", KeyRotationCommand::Status::FAILED); - histogram_tester_.ExpectTotalCount( - kManagementServicePositiveExitCodeHistogramName, 0); + histogram_tester_.ExpectTotalCount(kExitCodeHistogram, 0); } // Tests that the correct histogram is populated when the LogExitCode method // receives a negative exit code. TEST_F(LinuxKeyRotationCommandTest, NegativeExitCode) { - LogManagementServiceExitCode(-1); - histogram_tester_.ExpectUniqueSample( - kManagementServiceNegativeExitCodeHistogramName, 1, 1); + LogKeyRotationExitCode(-1); + histogram_tester_.ExpectUniqueSample(kExitCodeHistogram, -1, 1); +} + +// Tests that the command will fail with the expected message when the +// management service binary is not found. +TEST_F(LinuxKeyRotationCommandTest, MissingServiceBinary) { + KeyRotationCommand::Params params = {kFakeDMToken, kFakeDmServerUrl, kNonce}; + base::test::TestFuture<KeyRotationCommand::Status> future_status; + rotation_command_.Trigger(params, future_status.GetCallback()); + EXPECT_EQ(future_status.Get(), + KeyRotationCommand::Status::FAILED_INVALID_INSTALLATION); + ExpectCommandErrorHistogram( + KeyRotationCommandError::kMissingManagementService); } } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.cc index 04b2268..ddc2d08 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.cc
@@ -8,17 +8,6 @@ namespace enterprise_connectors { -namespace { - -// Max supported value for the UMA histogram exclusive max. -constexpr int kMaxExitCode = 101; -constexpr char kPositiveExitCodeHistogramName[] = - "Enterprise.DeviceTrust.ManagementService.ExitCode.Positive"; -constexpr char kNegativeExitCodeHistogramName[] = - "Enterprise.DeviceTrust.ManagementService.ExitCode.Negative"; - -} // namespace - void LogKeyRotationCommandError(KeyRotationCommandError error) { static constexpr char kErrorHistogram[] = "Enterprise.DeviceTrust.KeyRotationCommand.Error"; @@ -31,16 +20,6 @@ base::UmaHistogramSparse(kExitCodeHistogram, exit_code); } -void LogManagementServiceExitCode(int exit_code) { - if (exit_code < 0) { - base::UmaHistogramExactLinear(kNegativeExitCodeHistogramName, -exit_code, - kMaxExitCode); - } else { - base::UmaHistogramExactLinear(kPositiveExitCodeHistogramName, exit_code, - kMaxExitCode); - } -} - #if BUILDFLAG(IS_WIN) void LogUnexpectedHresult(HRESULT result) { static constexpr char kHresultHistogram[] =
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.h b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.h index 43f78eec..a7bfb81 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.h +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands/metrics_utils.h
@@ -23,7 +23,9 @@ kNoInterface = 3, kUpdaterConcurrency = 4, kUserInstallation = 5, - kMaxValue = kUserInstallation, + kMissingManagementService = 6, + kProcessInvalid = 7, + kMaxValue = kProcessInvalid, }; // Logs the known key rotation command `error`. @@ -33,11 +35,6 @@ // positive and negative values. void LogKeyRotationExitCode(int exit_code); -// Logs the `exit_code` of the management service process after a key rotation -// was performed. -// Deprecated: Use `LogKeyRotationExitCode` instead. -void LogManagementServiceExitCode(int exit_code); - #if BUILDFLAG(IS_WIN) // Logs the unexpected `result` code from trying to communicate with the // installer.
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc index 58c12152..06a8fef 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager_impl.cc
@@ -165,7 +165,8 @@ : RotationStatus::FAILURE_CANNOT_UPLOAD_KEY_RESTORE_FAILED); RecordRotationStatus(is_rotation, status); SYSLOG(ERROR) << "Device trust key rotation failed. Could not send public " - "key to DM server."; + "key to DM server. HTTP Status: " + << response_code; if (upload_key_status == UploadKeyStatus::kFailedKeyConflict) { std::move(result_callback).Run(KeyRotationResult::kFailedKeyConflict); return;
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service.cc index d05ba65..ff36323b 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service.cc
@@ -120,8 +120,9 @@ "Device trust key rotation failed. Command missing rotate key switch."); } - if (!std::move(permissions_callback_).Run()) - return kFailure; + if (!std::move(permissions_callback_).Run()) { + return kFailedInsufficientPermissions; + } auto platform_channel_endpoint = mojo_helper_->GetEndpointFromCommandLine(*command_line);
diff --git a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service_unittest.cc index cad2d687..c3030c5 100644 --- a/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service_unittest.cc +++ b/chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/chrome_management_service_unittest.cc
@@ -87,7 +87,7 @@ EXPECT_CALL(mock_rotation_callback, Run(_)).Times(0); } - ChromeManagementService chrome_management_service = ChromeManagementService( + ChromeManagementService chrome_management_service( mock_permissions_callback.Get(), mock_rotation_callback.Get(), std::move(mojo_helper)); @@ -212,7 +212,7 @@ int exit_code = 0; ASSERT_TRUE(base::WaitForMultiprocessTestChildExit( child_process, TestTimeouts::action_timeout(), &exit_code)); - EXPECT_EQ(kFailure, exit_code); + EXPECT_EQ(exit_code, kFailedInsufficientPermissions); } // Tests when the chrome management service failed due to an invalid platform
diff --git a/chrome/browser/enterprise/connectors/interstitials/enterprise_block_controller_client.cc b/chrome/browser/enterprise/connectors/interstitials/enterprise_block_controller_client.cc index 826dbf8..272e4d83 100644 --- a/chrome/browser/enterprise/connectors/interstitials/enterprise_block_controller_client.cc +++ b/chrome/browser/enterprise/connectors/interstitials/enterprise_block_controller_client.cc
@@ -20,7 +20,7 @@ std::unique_ptr<security_interstitials::MetricsHelper> GetMetricsHelper( const GURL& url) { security_interstitials::MetricsHelper::ReportDetails settings; - settings.metric_prefix = "enterprise-block"; + settings.metric_prefix = "enterprise_block"; return std::make_unique<security_interstitials::MetricsHelper>(url, settings, nullptr);
diff --git a/chrome/browser/enterprise/connectors/interstitials/enterprise_block_page.cc b/chrome/browser/enterprise/connectors/interstitials/enterprise_block_page.cc index a7bc167..581ed381 100644 --- a/chrome/browser/enterprise/connectors/interstitials/enterprise_block_page.cc +++ b/chrome/browser/enterprise/connectors/interstitials/enterprise_block_page.cc
@@ -9,6 +9,7 @@ #include "components/grit/components_resources.h" #include "components/security_interstitials/content/security_interstitial_controller_client.h" #include "components/security_interstitials/core/common_string_util.h" +#include "components/security_interstitials/core/metrics_helper.h" #include "components/security_interstitials/core/urls.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/navigation_entry.h" @@ -32,7 +33,13 @@ : security_interstitials::SecurityInterstitialPage( web_contents, request_url, - std::move(controller_client)) {} + std::move(controller_client)) { + controller()->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW); + controller()->metrics_helper()->RecordUserInteraction( + MetricsHelper::TOTAL_VISITS); + controller()->metrics_helper()->RecordUserDecision( + security_interstitials::MetricsHelper::PROCEEDING_DISABLED); +} EnterpriseBlockPage::~EnterpriseBlockPage() = default; @@ -79,9 +86,13 @@ switch (cmd) { case security_interstitials::CMD_DONT_PROCEED: + controller()->metrics_helper()->RecordUserDecision( + MetricsHelper::DONT_PROCEED); controller()->GoBack(); break; case security_interstitials::CMD_OPEN_HELP_CENTER: + controller()->metrics_helper()->RecordUserInteraction( + MetricsHelper::SHOW_LEARN_MORE); controller()->OpenUrlInNewForegroundTab( GURL(security_interstitials::kEnterpriseInterstitialHelpLink)); break;
diff --git a/chrome/browser/enterprise/connectors/interstitials/enterprise_page_unittest.cc b/chrome/browser/enterprise/connectors/interstitials/enterprise_page_unittest.cc new file mode 100644 index 0000000..42149146 --- /dev/null +++ b/chrome/browser/enterprise/connectors/interstitials/enterprise_page_unittest.cc
@@ -0,0 +1,82 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise/connectors/interstitials/enterprise_block_page.h" +#include "chrome/browser/enterprise/connectors/interstitials/enterprise_warn_page.h" + +#include "base/test/metrics/histogram_tester.h" +#include "chrome/browser/enterprise/connectors/interstitials/enterprise_block_controller_client.h" +#include "chrome/browser/enterprise/connectors/interstitials/enterprise_warn_controller_client.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/security_interstitials/core/metrics_helper.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/test_renderer_host.h" + +namespace { + +constexpr char kBlockDecisionHistogram[] = + "interstitial.enterprise_block.decision"; +constexpr char kWarnDecisionHistogram[] = + "interstitial.enterprise_warn.decision"; + +class EnterprisePageTest : public testing::Test { + public: + EnterprisePageTest() : profile_manager_(TestingBrowserProcess::GetGlobal()) { + EXPECT_TRUE(profile_manager_.SetUp()); + profile_ = profile_manager_.CreateTestingProfile("test-user"); + } + + content::WebContents* web_contents() { + if (!web_contents_) { + content::WebContents::CreateParams params(profile_); + web_contents_ = content::WebContents::Create(params); + } + return web_contents_.get(); + } + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfileManager profile_manager_; + raw_ptr<TestingProfile> profile_; + std::unique_ptr<content::WebContents> web_contents_; +}; + +TEST_F(EnterprisePageTest, EnterpriseBlock_ShownAndMetricsRecorded) { + base::HistogramTester histograms; + + histograms.ExpectTotalCount(kBlockDecisionHistogram, 0); + + EnterpriseBlockPage test_page = + EnterpriseBlockPage(web_contents(), GURL("exampleurl.net"), + std::make_unique<EnterpriseBlockControllerClient>( + web_contents(), GURL("exampleurl.net"))); + + // Total count = pages shown + proceeding disabled on the page that was shown + histograms.ExpectTotalCount(kBlockDecisionHistogram, 2); + histograms.ExpectBucketCount(kBlockDecisionHistogram, + security_interstitials::MetricsHelper::SHOW, 1); + histograms.ExpectBucketCount( + kBlockDecisionHistogram, + security_interstitials::MetricsHelper::PROCEEDING_DISABLED, 1); +} + +TEST_F(EnterprisePageTest, EnterpriseWarn_ShownAndMetricsRecorded) { + base::HistogramTester histograms; + auto unsafe_resources = + safe_browsing::SafeBrowsingBlockingPage::UnsafeResourceList(); + + histograms.ExpectTotalCount(kWarnDecisionHistogram, 0); + + EnterpriseWarnPage test_page = EnterpriseWarnPage( + nullptr, web_contents(), GURL("exampleurl.net"), unsafe_resources, + std::make_unique<EnterpriseWarnControllerClient>(web_contents(), + GURL("exampleurl.net"))); + + histograms.ExpectTotalCount(kWarnDecisionHistogram, 1); + histograms.ExpectBucketCount(kWarnDecisionHistogram, + security_interstitials::MetricsHelper::SHOW, 1); +} +} // namespace
diff --git a/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_controller_client.cc b/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_controller_client.cc index febf334..91e84fd 100644 --- a/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_controller_client.cc +++ b/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_controller_client.cc
@@ -20,7 +20,7 @@ std::unique_ptr<security_interstitials::MetricsHelper> GetMetricsHelper( const GURL& url) { security_interstitials::MetricsHelper::ReportDetails settings; - settings.metric_prefix = "enterprise-warn"; + settings.metric_prefix = "enterprise_warn"; return std::make_unique<security_interstitials::MetricsHelper>(url, settings, nullptr);
diff --git a/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_page.cc b/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_page.cc index 13a77744..59c360e9 100644 --- a/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_page.cc +++ b/chrome/browser/enterprise/connectors/interstitials/enterprise_warn_page.cc
@@ -37,7 +37,11 @@ request_url, std::move(controller_client)), ui_manager_(ui_manager), - unsafe_resources_(unsafe_resources) {} + unsafe_resources_(unsafe_resources) { + controller()->metrics_helper()->RecordUserDecision(MetricsHelper::SHOW); + controller()->metrics_helper()->RecordUserInteraction( + MetricsHelper::TOTAL_VISITS); +} EnterpriseWarnPage::~EnterpriseWarnPage() = default; @@ -90,6 +94,8 @@ controller()->GoBack(); break; case security_interstitials::CMD_PROCEED: { + controller()->metrics_helper()->RecordUserDecision( + MetricsHelper::PROCEED); // Add to allowlist. ui_manager_->OnBlockingPageDone(unsafe_resources_, /*proceed=*/true, web_contents(), request_url(),
diff --git a/chrome/browser/enterprise/platform_auth/platform_auth_policy_observer_browsertest.cc b/chrome/browser/enterprise/platform_auth/platform_auth_policy_observer_browsertest.cc index bd8c016..2d7083da 100644 --- a/chrome/browser/enterprise/platform_auth/platform_auth_policy_observer_browsertest.cc +++ b/chrome/browser/enterprise/platform_auth/platform_auth_policy_observer_browsertest.cc
@@ -127,6 +127,7 @@ : public PlatformAuthPolicyObserverTest { public: void SetUp() override { + scoped_feature_list_.InitAndDisableFeature(enterprise_auth::kCloudApAuth); policy_provider_.SetDefaultReturns( /*is_initialization_complete_return=*/true, /*is_first_policy_load_complete_return=*/true);
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 9cf822e..33e5346 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -805,6 +805,7 @@ "//components/safe_browsing/core/browser:safe_browsing_metrics_collector", "//components/security_interstitials/content:security_interstitial_page", "//components/site_engagement/core/mojom:mojo_bindings", + "//components/supervised_user/core/common:common", "//components/webapps/browser", # TODO(crbug.com/1065748): Remove this dependency:
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index 6c34120..9de71892 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -6741,9 +6741,10 @@ DeclarativeNetRequestBackForwardCacheBrowserTest() { feature_list_.InitWithFeaturesAndParameters( {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"ignore_outstanding_network_request_for_testing", "true"}, - {"all_extensions_allowed", "true"}}}}, + {{"ignore_outstanding_network_request_for_testing", "true"}, + {"all_extensions_allowed", "true"}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, {features::kBackForwardCacheMemoryControls}); }
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc index 478f01f..cec1dcc 100644 --- a/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -66,6 +66,12 @@ constexpr char kPermissionErrorMessage[] = "You do not have permission to access the preference '*'. " "Be sure to declare in your manifest what permissions you need."; +constexpr char kPrivacySandboxWarningMessage[] = + "We’re deprecating the API chrome.privacy.websites.privacySandboxEnabled, " + "though it will remain active for backward compatibility until release " + "M113. Instead, please use chrome.privacy.websites.topicsEnabled, " + "chrome.privacy.websites.fledgeEnabled and " + "chrome.privacy.websites.adMeasurementEnabled."; #if BUILDFLAG(IS_CHROMEOS_LACROS) constexpr char kPrimaryProfileOnlyErrorMessage[] = "You may only access the preference '*' in the primary profile."; @@ -622,6 +628,14 @@ } #endif + // Warning message to developers in DevTools Console that the API + // chrome.privacy.websites.privacySandboxEnabled is being deprecated. + // TODO(b/263568309): Remove this once the deprecated API is retired. + if (prefs::kPrivacySandboxApisEnabled == browser_pref) { + WriteToConsole(blink::mojom::ConsoleMessageLevel::kWarning, + kPrivacySandboxWarningMessage); + } + PrefService* prefs = extensions::preference_helpers::GetProfilePrefService(profile, incognito); @@ -830,6 +844,14 @@ scope, base::Value(false)); } + // Warning message to developers in DevTools Console that the API + // chrome.privacy.websites.privacySandboxEnabled is being deprecated. + // TODO(b/263568309): Remove this once the deprecated API is retired. + if (prefs::kPrivacySandboxApisEnabled == browser_pref) { + WriteToConsole(blink::mojom::ConsoleMessageLevel::kWarning, + kPrivacySandboxWarningMessage); + } + prefs_helper->SetExtensionControlledPref(extension_id(), browser_pref, scope, browser_pref_value->Clone()); #if BUILDFLAG(IS_CHROMEOS_LACROS) @@ -917,6 +939,14 @@ prefs_helper->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); + // Warning message to developers in DevTools Console that the API + // chrome.privacy.websites.privacySandboxEnabled is being deprecated. + // TODO(b/263568309): Remove this once the deprecated API is retired. + if (prefs::kPrivacySandboxApisEnabled == browser_pref) { + WriteToConsole(blink::mojom::ConsoleMessageLevel::kWarning, + kPrivacySandboxWarningMessage); + } + // Whenever an extension clears the |kSafeBrowsingEnabled| preference, // it must also clear |kSafeBrowsingEnhanced|. See crbug.com/1064722 for // more background.
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc index 82e4f24..e640aa07 100644 --- a/chrome/browser/extensions/api/preference/preference_apitest.cc +++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -39,6 +39,7 @@ #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" +#include "extensions/test/test_extension_dir.h" #include "media/media_buildflags.h" #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h" @@ -627,3 +628,151 @@ content_settings::CookieControlsMode::kIncognitoOnly)), /* expected_controlled */ false); } + +namespace extensions { + +class ExtensionPrefDevToolsConsoleTest : public ExtensionPreferenceApiTest { + protected: + static constexpr char kExpectedWarning[] = + "We’re deprecating the API " + "chrome.privacy.websites.privacySandboxEnabled, though it will remain " + "active for backward compatibility until release M113. Instead, please " + "use chrome.privacy.websites.topicsEnabled, " + "chrome.privacy.websites.fledgeEnabled and " + "chrome.privacy.websites.adMeasurementEnabled."; + + // Builds a test extension dir with a simple html file that runs a js that + // can call chrome.privacy.websites.privacySandboxEnabled and another API + // under chrome.privacy (i.e. + // chrome.privacy.websites.hyperlinkAuditingEnabled). + void BuildTestExtensionDir(TestExtensionDir& test_dir) { + constexpr char kManifestTemplate[] = + R"({ + "name": "Bad Icon Path", + "manifest_version": 2, + "version": "0.1", + "permissions": ["privacy"] + })"; + + constexpr char kPageJsTemplate[] = + R"(function runGetScript() { + chrome.privacy.websites.privacySandboxEnabled.get({}, () => { + chrome.test.sendMessage('finish get'); + }); + } + function runSetScript() { + chrome.privacy.websites.privacySandboxEnabled + .set({value: false}, () => { + chrome.test.sendMessage('finish set'); + }); + } + function runClearScript() { + chrome.privacy.websites.privacySandboxEnabled.clear({}, () => { + chrome.test.sendMessage('finish clear'); + }); + } + function runHyperlinkAuditingScript() { + chrome.privacy.websites.hyperlinkAuditingEnabled.get({}, () => { + chrome.test.sendMessage('finish hyperlinkAuditing'); + }); + })"; + + constexpr char kPageHtmlTemplate[] = + R"(<html><script src="page.js"></script></html>)"; + + // Building the test extension. + test_dir.WriteManifest(kManifestTemplate); + test_dir.WriteFile(FILE_PATH_LITERAL("page.html"), kPageHtmlTemplate); + test_dir.WriteFile(FILE_PATH_LITERAL("page.js"), kPageJsTemplate); + } + + // Runs |script| in the background page of the extension with the given + // |extension_id|, and waits for it to send the |finish_message|. + void WaitForScriptToFinish(content::WebContents* web_contents, + const std::string& script, + const std::string finish_message) { + SCOPED_TRACE(script); + ExtensionTestMessageListener listener(finish_message); + content::ExecuteScriptAsync(web_contents, script); + EXPECT_TRUE(listener.WaitUntilSatisfied()) << message_; + } +}; + +INSTANTIATE_TEST_SUITE_P(EventPage, + ExtensionPrefDevToolsConsoleTest, + ::testing::Values(ContextType::kPersistentBackground)); + +// Tests the correct logging of console warning messages when +// PrivacySandboxEnabled API is called by an extension during the migration +// period. +IN_PROC_BROWSER_TEST_P(ExtensionPrefDevToolsConsoleTest, + PrivacySandboxMigrationExpectConsoleMessage) { + // STEP 1. Build extension. + TestExtensionDir test_dir; + BuildTestExtensionDir(test_dir); + + // STEP 2. Load extension. + const Extension* extension = LoadExtension(test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + // STEP 3. Navigate to the extension's html page and get access to its Web + // Contents. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), extension->GetResourceURL("page.html"))); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // STEP 4. Check if the deprecation console warning messages + // |kExpectedWarning| are logged. Calling + // chrome.privacy.websites.privacySandboxEnabled in a non-service worker + // context should log a console warning in that context. + content::WebContentsConsoleObserver console_observer(web_contents); + console_observer.SetPattern(kExpectedWarning); + + WaitForScriptToFinish(web_contents, "runGetScript();", "finish get"); + EXPECT_TRUE(console_observer.Wait()); + EXPECT_EQ(1u, console_observer.messages().size()); + + WaitForScriptToFinish(web_contents, "runClearScript();", "finish clear"); + EXPECT_TRUE(console_observer.Wait()); + EXPECT_EQ(2u, console_observer.messages().size()); + + WaitForScriptToFinish(web_contents, "runSetScript();", "finish set"); + EXPECT_TRUE(console_observer.Wait()); + EXPECT_EQ(3u, console_observer.messages().size()); +} + +// Tests that no console warning messages are logged when other APIs under +// chrome.privacy are called by an extension. +IN_PROC_BROWSER_TEST_P(ExtensionPrefDevToolsConsoleTest, + PrivacySandboxMigrationDoesNotExpectConsoleMessage) { + // STEP 1. Build extension. + TestExtensionDir test_dir; + BuildTestExtensionDir(test_dir); + + // STEP 2. Load extension. + const Extension* extension = LoadExtension(test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + // STEP 3. Navigate to the extension's html and get access to its Web + // Contents. + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), extension->GetResourceURL("page.html"))); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // STEP 4. Check if no console warning message is logged when another API is + // called. + // If another extension API (e.g. under chrome.privacy) is called + // other than chrome.privacy.websites.privacySandboxEnabled, then no + // console message should be logged. + content::WebContentsConsoleObserver console_observer(web_contents); + console_observer.SetPattern(kExpectedWarning); + + WaitForScriptToFinish(web_contents, "runHyperlinkAuditingScript();", + "finish hyperlinkAuditing"); + EXPECT_EQ(0u, console_observer.messages().size()) + << "Found console.warn or console.error with message: " + << console_observer.GetMessageAt(0); +} +} // namespace extensions
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 7d11d99..b2a82636 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -48,6 +48,7 @@ #include "components/search_engines/default_search_manager.h" #include "components/services/screen_ai/buildflags/buildflags.h" #include "components/spellcheck/browser/pref_names.h" +#include "components/supervised_user/core/common/pref_names.h" #include "components/translate/core/browser/translate_pref_names.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/unified_consent/pref_names.h"
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index 76672ad4..a8a94d8 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -51,7 +51,6 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_test_util.h" // nogncheck @@ -59,6 +58,7 @@ #include "chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.h" #include "components/account_id/account_id.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "extensions/common/extension_builder.h" #endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/extensions/back_forward_cache_browsertest.cc b/chrome/browser/extensions/back_forward_cache_browsertest.cc index b1a34e8..9450dea 100644 --- a/chrome/browser/extensions/back_forward_cache_browsertest.cc +++ b/chrome/browser/extensions/back_forward_cache_browsertest.cc
@@ -50,11 +50,12 @@ allow_content_scripts ? "true" : "false"}, {"extension_message_supported", extension_message_support ? "true" : "false"}, - {"TimeToLiveInBackForwardCacheInSeconds", "3600"}, {"all_extensions_allowed", all_extensions_allowed ? "true" : "false"}, {"blocked_extensions", blocked_extensions}, - {"ignore_outstanding_network_request_for_testing", "true"}}}}, + {"ignore_outstanding_network_request_for_testing", "true"}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, {features::kBackForwardCacheMemoryControls}); }
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc index 95d0e8c..0aa0bad 100644 --- a/chrome/browser/extensions/extension_context_menu_model.cc +++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -154,6 +154,8 @@ case ExtensionContextMenuModel::PAGE_ACCESS_ALL_EXTENSIONS_BLOCKED: NOTREACHED(); break; + case ExtensionContextMenuModel::VIEW_WEB_PERMISSIONS: + return ContextMenuAction::kViewWebPermissions; default: break; } @@ -350,8 +352,9 @@ case TOGGLE_VISIBILITY: return !browser_->profile()->IsOffTheRecord() && !IsExtensionForcePinned(*extension, profile_); - // Manage extensions is always enabled. + // Manage extensions and view web permissions are always enabled. case MANAGE_EXTENSIONS: + case VIEW_WEB_PERMISSIONS: return true; default: NOTREACHED() << "Unknown command" << command_id; @@ -398,6 +401,9 @@ chrome::ShowExtensions(browser_, extension->id()); break; } + case VIEW_WEB_PERMISSIONS: + chrome::ShowSiteSettings(browser_, extension->url()); + break; case INSPECT_POPUP: { delegate_->InspectPopup(); break; @@ -498,6 +504,7 @@ if (!is_component_) { AddSeparator(ui::NORMAL_SEPARATOR); AddItemWithStringId(MANAGE_EXTENSIONS, IDS_MANAGE_EXTENSION); + AddItemWithStringId(VIEW_WEB_PERMISSIONS, IDS_VIEW_WEB_PERMISSIONS); } const ActionInfo* action_info = ActionInfo::GetExtensionActionInfo(extension);
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h index f0c9ed1f..35d30bd 100644 --- a/chrome/browser/extensions/extension_context_menu_model.h +++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -44,6 +44,7 @@ PAGE_ACCESS_ALL_EXTENSIONS_GRANTED, PAGE_ACCESS_ALL_EXTENSIONS_BLOCKED, PAGE_ACCESS_PERMISSIONS_PAGE, + VIEW_WEB_PERMISSIONS, // NOTE: If you update this, you probably need to update the // ContextMenuAction enum below. }; @@ -69,7 +70,8 @@ kPageAccessRunOnAllSites = 10, kPageAccessLearnMore = 11, kPageAccessPermissionsPage = 12, - kMaxValue = kPageAccessPermissionsPage, + kViewWebPermissions = 13, + kMaxValue = kViewWebPermissions, }; // Location where the context menu is open from.
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc index 84807e3..6234697 100644 --- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc +++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -537,6 +537,11 @@ GetCommandState(menu, ExtensionContextMenuModel::MANAGE_EXTENSIONS), CommandState::kAbsent); + // A component extension's context menu should not link to site settings. + EXPECT_EQ( + GetCommandState(menu, ExtensionContextMenuModel::VIEW_WEB_PERMISSIONS), + CommandState::kAbsent); + // The "name" option should be present, but not enabled for component // extensions. EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::HOME_PAGE), @@ -563,10 +568,10 @@ } } -// Tests that the standard menu items (home page, uninstall, and manage -// extensions) are always visible for any context menu source. NOTE: -// other menu items visibility is dependent on context, and behavior is checked -// in other tests. +// Tests that the standard menu items (home page, uninstall, manage +// extensions, view web permissions) are always visible for any context menu +// source. NOTE: other menu items visibility is dependent on context, and +// behavior is checked in other tests. TEST_F(ExtensionContextMenuModelTest, ExtensionContextMenuStandardItemsAlwaysVisible) { InitializeEmptyExtensionService(); @@ -587,6 +592,9 @@ EXPECT_NE( GetCommandState(menu, ExtensionContextMenuModel::MANAGE_EXTENSIONS), CommandState::kAbsent); + EXPECT_NE( + GetCommandState(menu, ExtensionContextMenuModel::VIEW_WEB_PERMISSIONS), + CommandState::kAbsent); } }
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc index 804d95e..ae14cb3 100644 --- a/chrome/browser/first_run/first_run.cc +++ b/chrome/browser/first_run/first_run.cc
@@ -198,7 +198,7 @@ void ProcessDefaultBrowserPolicy(bool make_chrome_default_for_user) { // Only proceed if chrome can be made default unattended. In other cases, this // is handled by the first run default browser prompt (on Windows 8+). - if (shell_integration::GetDefaultWebClientSetPermission() == + if (shell_integration::GetDefaultBrowserSetPermission() == shell_integration::SET_DEFAULT_UNATTENDED) { // The policy has precedence over the user's choice. if (g_browser_process->local_state()->IsManagedPreference(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 2864e00..e8e582f 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -919,6 +919,11 @@ "expiry_milestone": 121 }, { + "name": "cct-resizable-side-sheet-for-third-parties", + "owners": ["katzz", "kgrosu", "jinsukkim"], + "expiry_milestone": 123 + }, + { "name": "cct-retaining-state-in-memory", "owners": ["katzz", "wenyufu"], "expiry_milestone": 116 @@ -966,6 +971,11 @@ "expiry_milestone": 122 }, { + "name": "chrome-refresh-2023", + "owners":["chrome-views@google.com"], + "expiry_milestone": 115 + }, + { "name": "chrome-root-store-enabled", "owners": ["hchao", "mattm", "davidben", "chrome-trusty-transport-core@google.com"], "expiry_milestone": 115 @@ -1110,6 +1120,11 @@ "expiry_milestone": 112 }, { + "name": "context-menu-google-lens-search-optimizations", + "owners": [ "apalanki@google.com", "lens-chrome@google.com" ], + "expiry_milestone": 114 + }, + { "name": "context-menu-popup-for-all-screen-sizes", "owners": ["wenyufu", "clank-large-form-factors@google.com"], "expiry_milestone": 112 @@ -1872,6 +1887,11 @@ "expiry_milestone": 120 }, { + "name": "enable-chromevox-q1-fast-track-features", + "owners": [ "josiahk", "//ash/accessibility/OWNERS" ], + "expiry_milestone": 130 + }, + { "name": "enable-close-tab-suggestions", "owners": [ "memex-team@google.com" ], "expiry_milestone": 90 @@ -2182,8 +2202,8 @@ }, { "name": "enable-disco-feed-endpoint", - "owners": [ "adamta", "sczs" ], - "expiry_milestone": 106 + "owners": [ "tinazwang", "sczs" ], + "expiry_milestone": 116 }, { "name": "enable-discount-consent-v2", @@ -2610,6 +2630,11 @@ "expiry_milestone": 95 }, { + "name": "enable-lens-context-menu-alt-text", + "owners": [ "apalanki", "schechter", "hujasonx" ], + "expiry_milestone": 114 + }, + { "name": "enable-lens-image-format-optimizations", "owners": ["mercerd@google.com", "stanfield@google.com", "lens-chrome@google.com"], "expiry_milestone": 112 @@ -3064,6 +3089,16 @@ "expiry_milestone": -1 }, { + "name": "enable-skip-service-worker-check-install-for-promotion", + "owners": [ "camdenking@google.com", "desktop-pwas-team@google.com" ], + "expiry_milestone": 122 + }, + { + "name": "enable-skip-service-worker-check-install-only", + "owners": [ "camdenking@google.com", "desktop-pwas-team@google.com" ], + "expiry_milestone": 122 + }, + { "name": "enable-start-surface", "owners": [ "hanxi", "wychen" ], "expiry_milestone": 115 @@ -3536,6 +3571,11 @@ "expiry_milestone": 90 }, { + "name": "enterprise-reporting-ui", + "owners": ["tylergarrett@google.com", "cros-reporting-team@google.com"], + "expiry_milestone": 130 + }, + { "name": "ev-details-in-page-info", "owners": [ "cthomp" ], "expiry_milestone": 83 @@ -6457,7 +6497,7 @@ { "name": "smart-sorting-new-overflow-menu", "owners": [ "bwwilliams@google.com", "bling-flags@google.com" ], - "expiry_milestone": 111 + "expiry_milestone": 114 }, { "name": "smart-sorting-price-tracking-destination", @@ -6641,6 +6681,11 @@ "expiry_milestone": 110 }, { + "name": "tab-inactivity-threshold", + "owners": [ "alionadangla", "lpromero", "bling-flags@google.com" ], + "expiry_milestone": 120 + }, + { "name": "tab-outlines-in-low-contrast-themes", "owners": [ "dfried" ], "expiry_milestone": 82
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 356b0636..c967b1f8 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -687,6 +687,9 @@ "Access Chrome Labs through the toolbar menu to see featured user-facing " "experimental features."; +const char kChromeRefresh2023Name[] = "Chrome Refresh 2023"; +const char kChromeRefresh2023Description[] = "Refresh of Chrome Desktop UI"; + const char kClosedTabCacheName[] = "Closed Tab Cache"; const char kClosedTabCacheDescription[] = "Enables closed tab cache to instantaneously restore recently closed tabs. " @@ -708,6 +711,11 @@ "Replaces default image search with an intent to Google Lens when " "supported."; +const char kContextMenuGoogleLensSearchOptimizationsName[] = + "Google Lens powered image search string variations in the context menu."; +const char kContextMenuGoogleLensSearchOptimizationsDescription[] = + "Replaces Google Lens string variations when Google Lens is supported."; + const char kClientStorageAccessContextAuditingName[] = "Access contexts for client-side storage"; const char kClientStorageAccessContextAuditingDescription[] = @@ -965,6 +973,18 @@ "Enable PWAs with screenshots to show a detailed install dialog during " "installation"; +const char kSkipServiceWorkerCheckInstallOnlyName[] = + "Skip service worker check for PWA installs"; +const char kSkipServiceWorkerCheckInstallOnlyDescription[] = + "Allows PWAs to be installed without a service worker."; + +const char kSkipServiceWorkerForInstallPromptName[] = + "Promote PWA installation without a service worker"; +const char kSkipServiceWorkerForInstallPromptDescription[] = + "Allows PWAs that can be installed without a service worker to be " + "promoted. Requires #enable-skip-service-worker-check-install-only flag to " + "also be enabled."; + const char kEnablePreinstalledWebAppDuplicationFixerName[] = "Enable the app deduplication fix for migrated preinstalled web apps"; const char kEnablePreinstalledWebAppDuplicationFixerDescription[] = @@ -986,6 +1006,12 @@ "shortcut (docked magnifier, screen magnifier and high contrast) to time " "out instead of remaining pinned."; +const char kChromeVoxQ1FastTrackFeaturesName[] = + "ChromeVox Q1 Fast-Track Features"; +const char kChromeVoxQ1FastTrackFeaturesDescription[] = + "This option enables experimental Accessibility ChromeVox improvements for " + "Chrome OS."; + const char kAccessibilityServiceName[] = "Experimental Accessibility Service"; const char kAccessibilityServiceDescription[] = "This option enables the experimental Accessibility Service and runs some " @@ -3510,6 +3536,10 @@ const char kCCTResizableSideSheetName[] = "Side sheet Custom Tabs"; const char kCCTResizableSideSheetDescription[] = "Enable side sheet Custom Tabs"; +const char kCCTResizableSideSheetForThirdPartiesName[] = + "Side sheet Custom Tabs (third party)"; +const char kCCTResizableSideSheetForThirdPartiesDescription[] = + "Enable side sheet Custom Tabs for third party apps."; const char kCCTRetainingStateInMemoryName[] = "Enable restoring of previous Custom Tab session"; @@ -4954,6 +4984,11 @@ const char kEnableServiceWorkersForChromeUntrustedDescription[] = "When enabled, allows chrome-untrusted:// WebUIs to use service workers."; +const char kEnterpriseReportingUIName[] = + "Enable chrome://enterprise-reporting"; +const char kEnterpriseReportingUIDescription[] = + "When enabled, allows for chrome://enterprise-reporting to be visited"; + const char kCrostiniContainerInstallName[] = "Debian version for new Crostini containers"; const char kCrostiniContainerInstallDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 0a17954..8ebb6f1 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -379,6 +379,9 @@ extern const char kChromeLabsName[]; extern const char kChromeLabsDescription[]; +extern const char kChromeRefresh2023Name[]; +extern const char kChromeRefresh2023Description[]; + extern const char kCommerceHintAndroidName[]; extern const char kCommerceHintAndroidDescription[]; @@ -388,6 +391,9 @@ extern const char kContextMenuSearchWithGoogleLensName[]; extern const char kContextMenuSearchWithGoogleLensDescription[]; +extern const char kContextMenuGoogleLensSearchOptimizationsName[]; +extern const char kContextMenuGoogleLensSearchOptimizationsDescription[]; + extern const char kClientStorageAccessContextAuditingName[]; extern const char kClientStorageAccessContextAuditingDescription[]; @@ -543,6 +549,12 @@ extern const char kDesktopPWAsDetailedInstallDialogName[]; extern const char kDesktopPWAsDetailedInstallDialogDescription[]; +extern const char kSkipServiceWorkerCheckInstallOnlyName[]; +extern const char kSkipServiceWorkerCheckInstallOnlyDescription[]; + +extern const char kSkipServiceWorkerForInstallPromptName[]; +extern const char kSkipServiceWorkerForInstallPromptDescription[]; + extern const char kDeviceForceScheduledRebootName[]; extern const char kDeviceForceScheduledRebootDescription[]; @@ -561,6 +573,9 @@ extern const char kAccessibilityAcceleratorNotificationsTimeoutName[]; extern const char kAccessibilityAcceleratorNotificationsTimeoutDescription[]; +extern const char kChromeVoxQ1FastTrackFeaturesName[]; +extern const char kChromeVoxQ1FastTrackFeaturesDescription[]; + extern const char kAccessibilityServiceName[]; extern const char kAccessibilityServiceDescription[]; @@ -2002,6 +2017,8 @@ extern const char kCCTResizableForThirdPartiesDescription[]; extern const char kCCTResizableSideSheetName[]; extern const char kCCTResizableSideSheetDescription[]; +extern const char kCCTResizableSideSheetForThirdPartiesName[]; +extern const char kCCTResizableSideSheetForThirdPartiesDescription[]; extern const char kCCTRetainingStateInMemoryName[]; extern const char kCCTRetainingStateInMemoryDescription[]; @@ -2843,6 +2860,9 @@ extern const char kEnableServiceWorkersForChromeUntrustedName[]; extern const char kEnableServiceWorkersForChromeUntrustedDescription[]; +extern const char kEnterpriseReportingUIName[]; +extern const char kEnterpriseReportingUIDescription[]; + extern const char kCrostiniContainerInstallName[]; extern const char kCrostiniContainerInstallDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 00f390a..869956b 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -194,6 +194,7 @@ &kCCTResizable90MaximumHeight, &kCCTResizableForThirdParties, &kCCTResizableSideSheet, + &kCCTResizableSideSheetForThirdParties, &kCCTRetainingStateInMemory, &kCCTResourcePrefetch, &kCCTToolbarCustomizations, @@ -208,6 +209,7 @@ &kCommandLineOnNonRooted, &kContextMenuEnableLensShoppingAllowlist, &kContextMenuGoogleLensChip, + &kContextMenuGoogleLensSearchOptimizations, &kContextMenuSearchWithGoogleLens, &kContextMenuShopWithGoogleLens, &kContextMenuSearchAndShopWithGoogleLens, @@ -248,6 +250,7 @@ &kProbabilisticCryptidRenderer, &kReachedCodeProfiler, &kReaderModeInCCT, + &kRecordSuppressionMetrics, &kReengagementNotification, &kRelatedSearches, &kRelatedSearchesInBar, @@ -570,6 +573,10 @@ "CCTResizableSideSheet", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kCCTResizableSideSheetForThirdParties, + "CCTResizableSideSheetForThirdParties", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kCCTResourcePrefetch, "CCTResourcePrefetch", base::FEATURE_ENABLED_BY_DEFAULT); @@ -630,6 +637,10 @@ "ContextMenuPopupForAllScreenSizes", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kContextMenuGoogleLensSearchOptimizations, + "ContextMenuGoogleLensSearchOptimizations", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kContextMenuSearchWithGoogleLens, "ContextMenuSearchWithGoogleLens", base::FEATURE_ENABLED_BY_DEFAULT); @@ -786,6 +797,10 @@ "ReaderModeInCCT", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kRecordSuppressionMetrics, + "RecordSuppressionMetrics", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kReengagementNotification, "ReengagementNotification", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 9efca7d7..de41211 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -54,6 +54,7 @@ BASE_DECLARE_FEATURE(kCCTResizable90MaximumHeight); BASE_DECLARE_FEATURE(kCCTResizableForThirdParties); BASE_DECLARE_FEATURE(kCCTResizableSideSheet); +BASE_DECLARE_FEATURE(kCCTResizableSideSheetForThirdParties); BASE_DECLARE_FEATURE(kCCTResourcePrefetch); BASE_DECLARE_FEATURE(kCCTRetainingStateInMemory); BASE_DECLARE_FEATURE(kCCTToolbarCustomizations); @@ -69,6 +70,7 @@ BASE_DECLARE_FEATURE(kCommandLineOnNonRooted); BASE_DECLARE_FEATURE(kContextMenuEnableLensShoppingAllowlist); BASE_DECLARE_FEATURE(kContextMenuGoogleLensChip); +BASE_DECLARE_FEATURE(kContextMenuGoogleLensSearchOptimizations); BASE_DECLARE_FEATURE(kContextMenuPopupForAllScreenSizes); BASE_DECLARE_FEATURE(kContextMenuSearchWithGoogleLens); BASE_DECLARE_FEATURE(kContextMenuShopWithGoogleLens); @@ -116,6 +118,7 @@ BASE_DECLARE_FEATURE(kReachedCodeProfiler); BASE_DECLARE_FEATURE(kReengagementNotification); BASE_DECLARE_FEATURE(kReaderModeInCCT); +BASE_DECLARE_FEATURE(kRecordSuppressionMetrics); BASE_DECLARE_FEATURE(kRelatedSearches); BASE_DECLARE_FEATURE(kRelatedSearchesInBar); BASE_DECLARE_FEATURE(kRelatedSearchesUi);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/BaseFlagTestRule.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/BaseFlagTestRule.java index a6a6a00..d8f313b9 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/BaseFlagTestRule.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/BaseFlagTestRule.java
@@ -13,7 +13,6 @@ import org.chromium.base.FeatureList; import org.chromium.base.Flag; -import java.util.HashMap; import java.util.Map; /** @@ -43,30 +42,10 @@ static final String FEATURE_A = "FeatureA"; static final String FEATURE_B = "FeatureB"; - static final Map<String, Boolean> A_OFF_B_ON = new HashMap<String, Boolean>() { - { - put(FEATURE_A, false); - put(FEATURE_B, true); - } - }; - static final Map<String, Boolean> A_OFF_B_OFF = new HashMap<String, Boolean>() { - { - put(FEATURE_A, false); - put(FEATURE_B, false); - } - }; - static final Map<String, Boolean> A_ON_B_OFF = new HashMap<String, Boolean>() { - { - put(FEATURE_A, true); - put(FEATURE_B, false); - } - }; - static final Map<String, Boolean> A_ON_B_ON = new HashMap<String, Boolean>() { - { - put(FEATURE_A, true); - put(FEATURE_B, true); - } - }; + static final Map<String, Boolean> A_OFF_B_ON = Map.of(FEATURE_A, false, FEATURE_B, true); + static final Map<String, Boolean> A_OFF_B_OFF = Map.of(FEATURE_A, false, FEATURE_B, false); + static final Map<String, Boolean> A_ON_B_OFF = Map.of(FEATURE_A, true, FEATURE_B, false); + static final Map<String, Boolean> A_ON_B_ON = Map.of(FEATURE_A, true, FEATURE_B, true); static void assertIsEnabledMatches(Map<String, Boolean> state, Flag feature1, Flag feature2) { assertEquals(state.get(FEATURE_A), feature1.isEnabled());
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameterUnitTest.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameterUnitTest.java index ee906c9..e0c5a554 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameterUnitTest.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameterUnitTest.java
@@ -21,8 +21,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -91,33 +89,29 @@ private static final String FEATURE_B = "FeatureB"; - private static final String[] ALL_PARAMS_NATIVE = new String[] {STRING_PARAM_NAME, - STRING_PARAM_NATIVE, BOOLEAN_PARAM_NAME, BOOLEAN_PARAM_NATIVE_STRING, INT_PARAM_NAME, - INT_PARAM_NATIVE_STRING, DOUBLE_PARAM_NAME, DOUBLE_PARAM_NATIVE_STRING}; - private static final Map<String, String> ALL_PARAM_TEST_OVERRIDE = - new HashMap<String, String>() { - { - put(STRING_PARAM_NAME, STRING_PARAM_TEST_OVERRIDE); - put(BOOLEAN_PARAM_NAME, BOOLEAN_PARAM_TEST_OVERRIDE_STRING); - put(INT_PARAM_NAME, INT_PARAM_TEST_OVERRIDE_STRING); - put(DOUBLE_PARAM_NAME, DOUBLE_PARAM_TEST_OVERRIDE_STRING); - } - }; + // clang-format off + private static final String[] ALL_PARAMS_NATIVE = new String[] { + STRING_PARAM_NAME, + STRING_PARAM_NATIVE, + BOOLEAN_PARAM_NAME, + BOOLEAN_PARAM_NATIVE_STRING, + INT_PARAM_NAME, + INT_PARAM_NATIVE_STRING, + DOUBLE_PARAM_NAME, + DOUBLE_PARAM_NATIVE_STRING, + }; + private static final Map<String, String> ALL_PARAM_TEST_OVERRIDE = Map.of( + STRING_PARAM_NAME, STRING_PARAM_TEST_OVERRIDE, + BOOLEAN_PARAM_NAME, BOOLEAN_PARAM_TEST_OVERRIDE_STRING, + INT_PARAM_NAME, INT_PARAM_TEST_OVERRIDE_STRING, + DOUBLE_PARAM_NAME, DOUBLE_PARAM_TEST_OVERRIDE_STRING); + // clang-format on private static final AllCachedFieldTrialParameters ALL_PARAM = new AllCachedFieldTrialParameters(FEATURE_B); private static final List<CachedFieldTrialParameter> PARAMS_TO_CACHE = - new ArrayList<CachedFieldTrialParameter>() { - { - add(STRING_PARAM); - add(BOOLEAN_PARAM); - add(INT_PARAM); - add(DOUBLE_PARAM); - add(STRING2_PARAM); - add(ALL_PARAM); - } - }; + List.of(STRING_PARAM, BOOLEAN_PARAM, INT_PARAM, DOUBLE_PARAM, STRING2_PARAM, ALL_PARAM); @Before public void setUp() {
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 620e47e..6be5205 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
@@ -244,6 +244,8 @@ "CCTResizableAllowResizeByUserGesture"; public static final String CCT_RESIZABLE_FOR_THIRD_PARTIES = "CCTResizableForThirdParties"; public static final String CCT_RESIZABLE_SIDE_SHEET = "CCTResizableSideSheet"; + public static final String CCT_RESIZABLE_SIDE_SHEET_FOR_THIRD_PARTIES = + "CCTResizableSideSheetForThirdParties"; public static final String CCT_RESOURCE_PREFETCH = "CCTResourcePrefetch"; public static final String CCT_RETAINING_STATE_IN_MEMORY = "CCTRetainingStateInMemory"; public static final String CCT_TOOLBAR_CUSTOMIZATIONS = "CCTToolbarCustomizations"; @@ -280,6 +282,8 @@ "ContextMenuPopupForAllScreenSizes"; public static final String CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS = "ContextMenuSearchWithGoogleLens"; + public static final String CONTEXT_MENU_GOOGLE_LENS_SEARCH_OPTIMIZATIONS = + "ContextMenuGoogleLensSearchOptimizations"; public static final String CONTEXT_MENU_TRANSLATE_WITH_GOOGLE_LENS = "ContextMenuTranslateWithGoogleLens"; public static final String CORMORANT = "Cormorant"; @@ -434,6 +438,7 @@ public static final String REACHED_CODE_PROFILER = "ReachedCodeProfiler"; public static final String READER_MODE_IN_CCT = "ReaderModeInCCT"; public static final String READ_LATER = "ReadLater"; + public static final String RECORD_SUPPRESSION_METRICS = "RecordSuppressionMetrics"; public static final String RECOVER_FROM_NEVER_SAVE_ANDROID = "RecoverFromNeverSaveAndroid"; public static final String REENGAGEMENT_NOTIFICATION = "ReengagementNotification"; public static final String RELATED_SEARCHES = "RelatedSearches"; @@ -577,6 +582,8 @@ new CachedFlag(CCT_RESIZABLE_FOR_THIRD_PARTIES, true); public static final CachedFlag sCctResizableSideSheet = new CachedFlag(CCT_RESIZABLE_SIDE_SHEET, false); + public static final CachedFlag sCctResizableSideSheetForThirdParties = + new CachedFlag(CCT_RESIZABLE_SIDE_SHEET_FOR_THIRD_PARTIES, false); public static final CachedFlag sCctRetainableStateInMemory = new CachedFlag(CCT_RETAINING_STATE_IN_MEMORY, false); public static final CachedFlag sCctToolbarCustomizations =
diff --git a/chrome/browser/hid/hid_chooser_context.cc b/chrome/browser/hid/hid_chooser_context.cc index 84fa9d0d..d33e9f2 100644 --- a/chrome/browser/hid/hid_chooser_context.cc +++ b/chrome/browser/hid/hid_chooser_context.cc
@@ -50,27 +50,6 @@ object.FindStringKey(kHidDeviceNameKey); } -base::Value DeviceInfoToValue(const device::mojom::HidDeviceInfo& device) { - base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey( - kHidDeviceNameKey, - base::UTF16ToUTF8(HidChooserContext::DisplayNameFromDeviceInfo(device))); - value.SetIntKey(kHidVendorIdKey, device.vendor_id); - value.SetIntKey(kHidProductIdKey, device.product_id); - if (HidChooserContext::CanStorePersistentEntry(device)) { - // Use the USB serial number as a persistent identifier. If it is - // unavailable, only ephemeral permissions may be granted. - value.SetStringKey(kHidSerialNumberKey, device.serial_number); - } else { - // The GUID is a temporary ID created on connection that remains valid until - // the device is disconnected. Ephemeral permissions are keyed by this ID - // and must be granted again each time the device is connected. - value.SetStringKey(kHidGuidKey, device.guid); - } - DCHECK(!IsPolicyGrantedObject(value)); - return value; -} - base::Value VendorAndProductIdsToValue(uint16_t vendor_id, uint16_t product_id) { base::Value object(base::Value::Type::DICTIONARY); @@ -151,6 +130,29 @@ } // static +base::Value HidChooserContext::DeviceInfoToValue( + const device::mojom::HidDeviceInfo& device) { + base::Value value(base::Value::Type::DICTIONARY); + value.SetStringKey( + kHidDeviceNameKey, + base::UTF16ToUTF8(HidChooserContext::DisplayNameFromDeviceInfo(device))); + value.SetIntKey(kHidVendorIdKey, device.vendor_id); + value.SetIntKey(kHidProductIdKey, device.product_id); + if (HidChooserContext::CanStorePersistentEntry(device)) { + // Use the USB serial number as a persistent identifier. If it is + // unavailable, only ephemeral permissions may be granted. + value.SetStringKey(kHidSerialNumberKey, device.serial_number); + } else { + // The GUID is a temporary ID created on connection that remains valid until + // the device is disconnected. Ephemeral permissions are keyed by this ID + // and must be granted again each time the device is connected. + value.SetStringKey(kHidGuidKey, device.guid); + } + DCHECK(!IsPolicyGrantedObject(value)); + return value; +} + +// static std::u16string HidChooserContext::DisplayNameFromDeviceInfo( const device::mojom::HidDeviceInfo& device) { if (device.product_name.empty()) { @@ -178,6 +180,11 @@ std::string HidChooserContext::GetKeyForObject(const base::Value& object) { if (!IsValidObject(object)) return std::string(); + + if (IsPolicyGrantedObject(object)) { + return *object.FindStringKey(kHidDeviceNameKey); + } + return base::JoinString( {base::NumberToString(*(object.FindIntKey(kHidVendorIdKey))), base::NumberToString(*(object.FindIntKey(kHidProductIdKey))),
diff --git a/chrome/browser/hid/hid_chooser_context.h b/chrome/browser/hid/hid_chooser_context.h index ef269daf..81529ca 100644 --- a/chrome/browser/hid/hid_chooser_context.h +++ b/chrome/browser/hid/hid_chooser_context.h
@@ -55,6 +55,9 @@ HidChooserContext& operator=(const HidChooserContext&) = delete; ~HidChooserContext() override; + static base::Value DeviceInfoToValue( + const device::mojom::HidDeviceInfo& device); + // Returns a human-readable string identifier for |device|. static std::u16string DisplayNameFromDeviceInfo( const device::mojom::HidDeviceInfo& device);
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc index ae4cbcee..3ff52334 100644 --- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc +++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.cc
@@ -241,3 +241,12 @@ textfield); })); } + +void ChromeBrowserMainExtraPartsLacros::PostMainMessageLoopRun() { + // Must be destroyed before |chrome_kiosk_launch_controller_->profile_| is + // destroyed. + chrome_kiosk_launch_controller_.reset(); + // Must be destroyed before |kiosk_session_service_->app_session_->profile_| + // is destroyed. + kiosk_session_service_.reset(); +}
diff --git a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h index d6f7d4bb..05cb3fe 100644 --- a/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h +++ b/chrome/browser/lacros/chrome_browser_main_extra_parts_lacros.h
@@ -68,6 +68,7 @@ void PreProfileInit() override; void PostBrowserStart() override; void PostProfileInit(Profile* profile, bool is_initial_profile) override; + void PostMainMessageLoopRun() override; // Receiver and cache of arc icon info updates. std::unique_ptr<ArcIconCache> arc_icon_cache_;
diff --git a/chrome/browser/lacros/desk_template_client_lacros.cc b/chrome/browser/lacros/desk_template_client_lacros.cc index 2749a15..a638ebd 100644 --- a/chrome/browser/lacros/desk_template_client_lacros.cc +++ b/chrome/browser/lacros/desk_template_client_lacros.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/lacros/desk_template_client_lacros.h" +#include "base/ranges/algorithm.h" #include "chrome/browser/apps/icon_standardizer.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -12,14 +13,54 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chromeos/lacros/lacros_service.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/favicon_util.h" +#include "components/tab_groups/tab_group_id.h" +#include "components/tab_groups/tab_group_info.h" +#include "components/tab_groups/tab_group_visual_data.h" #include "ui/platform_window/platform_window.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h" namespace { +const std::vector<int> ConvertRangeToTabGroupIndices(const gfx::Range& range) { + std::vector<int> indices; + + for (uint32_t index = range.start(); index < range.end(); ++index) { + indices.push_back(static_cast<int>(index)); + } + + return indices; +} + +bool ValidateTabRange(const tab_groups::TabGroupInfo& group_info, + const TabStripModel* tab_strip_model) { + const gfx::Range& range = group_info.tab_range; + + if (range.length() == 0) { + LOG(WARNING) << "group_info: range must have a non-zero length!"; + return false; + } + + if (range.start() > range.end()) { + LOG(WARNING) + << "group_info: range.start() cannot be larger than range.end()!"; + return false; + } + + if (range.GetMax() >= static_cast<uint32_t>(tab_strip_model->count())) { + LOG(WARNING) + << "group_info: range max cannot be larger than count of tabs!"; + return false; + } + + return true; +} + // Creates a callback for when a favicon image is retrieved which creates a // standard icon image and then calls `callback` with the standardized image. base::OnceCallback<void(const favicon_base::FaviconImageResult&)> @@ -36,8 +77,69 @@ std::move(callback)); } +void AddTabGroupToBrowser(TabStripModel* browser_tab_model, + const tab_groups::TabGroupInfo& group_info) { + if (!ValidateTabRange(group_info, browser_tab_model)) { + return; + } + + const std::vector<int> tab_range = + ConvertRangeToTabGroupIndices(group_info.tab_range); + tab_groups::TabGroupId new_group_id = + browser_tab_model->AddToNewGroup(tab_range); + browser_tab_model->group_model() + ->GetTabGroup(new_group_id) + ->SetVisualData(group_info.visual_data); +} + +void PopulateTabGroups(const std::vector<tab_groups::TabGroupInfo>& group_infos, + Browser* out_browser) { + TabStripModel* browser_tab_model = out_browser->tab_strip_model(); + DCHECK(browser_tab_model); + + for (const auto& group : group_infos) { + AddTabGroupToBrowser(browser_tab_model, group); + } +} + +void SetPinnedTabs(const int first_non_pinned_tab_index, Browser* out_browser) { + TabStripModel* browser_tab_model = out_browser->tab_strip_model(); + DCHECK(browser_tab_model); + + if (first_non_pinned_tab_index < 0 || + first_non_pinned_tab_index >= out_browser->tab_strip_model()->count()) { + LOG(WARNING) << "Pinned tab outside of tab bounds!"; + return; + } + + for (int index = 0; index < first_non_pinned_tab_index; ++index) { + browser_tab_model->SetTabPinned(index, /*pinned=*/true); + } +} + +void ConvertTabGroupsToTabGroupInfos( + const TabGroupModel* group_model, + crosapi::mojom::DeskTemplateState* out_state) { + DCHECK(group_model); + const std::vector<tab_groups::TabGroupId>& listed_group_ids = + group_model->ListTabGroups(); + + if (listed_group_ids.size() == 0) { + return; + } + + out_state->groups = std::vector<tab_groups::TabGroupInfo>(); + for (const tab_groups::TabGroupId& group_id : listed_group_ids) { + const TabGroup* tab_group = group_model->GetTabGroup(group_id); + out_state->groups->emplace_back( + gfx::Range(tab_group->ListTabs()), + tab_groups::TabGroupVisualData(*(tab_group->visual_data()))); + } +} + } // namespace +// DeskTemplateClientLacros DeskTemplateClientLacros::DeskTemplateClientLacros() { auto* const lacros_service = chromeos::LacrosService::Get(); if (lacros_service->IsAvailable<crosapi::mojom::DeskTemplate>()) { @@ -57,6 +159,7 @@ const absl::optional<std::string>& browser_app_name = additional_state->browser_app_name; + Browser::CreateParams create_params = browser_app_name.has_value() && !browser_app_name.value().empty() ? Browser::CreateParams::CreateForApp(browser_app_name.value(), @@ -71,12 +174,20 @@ create_params.initial_bounds = bounds; create_params.restore_id = additional_state->restore_window_id; Browser* browser = Browser::Create(create_params); + for (size_t i = 0; i < additional_state->urls.size(); i++) { chrome::AddTabAt( browser, additional_state->urls.at(i), /*index=*/-1, /*foreground=*/ (i == static_cast<size_t>(additional_state->active_index))); } + + if (additional_state->groups.has_value()) { + PopulateTabGroups(additional_state->groups.value(), browser); + } + + SetPinnedTabs(additional_state->first_non_pinned_index, browser); + if (show_state == ui::mojom::WindowShowState::SHOW_STATE_MINIMIZED) { browser->window()->Minimize(); } else { @@ -89,6 +200,7 @@ const std::string& window_unique_id, GetBrowserInformationCallback callback) { Browser* browser = nullptr; + for (auto* b : *BrowserList::GetInstance()) { if (views::DesktopWindowTreeHostLacros::From( b->window()->GetNativeWindow()->GetHost()) @@ -108,10 +220,22 @@ crosapi::mojom::DeskTemplateState::New(); TabStripModel* tab_strip_model = browser->tab_strip_model(); state->active_index = tab_strip_model->active_index(); + state->first_non_pinned_index = tab_strip_model->IndexOfFirstNonPinnedTab(); + + if (browser->type() == Browser::Type::TYPE_APP) { + state->browser_app_name = browser->app_name(); + } + for (int i = 0; i < tab_strip_model->count(); ++i) { state->urls.push_back( tab_strip_model->GetWebContentsAt(i)->GetLastCommittedURL()); } + + if (tab_strip_model->group_model() != nullptr) { + ConvertTabGroupsToTabGroupInfos(tab_strip_model->group_model(), + state.get()); + } + std::move(callback).Run(serial, window_unique_id, std::move(state)); }
diff --git a/chrome/browser/lacros/desk_template_client_lacros.h b/chrome/browser/lacros/desk_template_client_lacros.h index cb06508..8d0423ad 100644 --- a/chrome/browser/lacros/desk_template_client_lacros.h +++ b/chrome/browser/lacros/desk_template_client_lacros.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_LACROS_DESK_TEMPLATE_CLIENT_LACROS_H_ #define CHROME_BROWSER_LACROS_DESK_TEMPLATE_CLIENT_LACROS_H_ +#include "base/observer_list.h" +#include "base/observer_list_types.h" #include "base/task/cancelable_task_tracker.h" #include "chromeos/crosapi/mojom/desk_template.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -19,7 +21,6 @@ DeskTemplateClientLacros& operator=(const DeskTemplateClientLacros&) = delete; ~DeskTemplateClientLacros() override; - private: // DeskTemplateClient: void CreateBrowserWithRestoredData( const gfx::Rect& bounds, @@ -31,7 +32,8 @@ void GetFaviconImage(const GURL& url, GetFaviconImageCallback callback) override; - // The cancelable task tracker used for retreiving icons from the favicon + private: + // The cancelable task tracker used for retrieving icons from the favicon // service. base::CancelableTaskTracker task_tracker_;
diff --git a/chrome/browser/lacros/desk_template_client_lacros_browsertest.cc b/chrome/browser/lacros/desk_template_client_lacros_browsertest.cc new file mode 100644 index 0000000..5368bdc76 --- /dev/null +++ b/chrome/browser/lacros/desk_template_client_lacros_browsertest.cc
@@ -0,0 +1,506 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/lacros/desk_template_client_lacros.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/crosapi/mojom/desk_template.mojom-test-utils.h" +#include "chromeos/crosapi/mojom/desk_template.mojom.h" +#include "chromeos/lacros/lacros_service.h" +#include "components/tab_groups/tab_group_color.h" +#include "components/tab_groups/tab_group_info.h" +#include "components/tab_groups/tab_group_visual_data.h" +#include "content/public/test/browser_test.h" +#include "net/dns/mock_host_resolver.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" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/page_transition_types.h" +#include "ui/gfx/range/range.h" +#include "ui/platform_window/platform_window.h" +#include "ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h" +#include "url/gurl.h" + +namespace { + +constexpr char kTestName[] = "chrome version"; +constexpr char kChromeVersionUrl[] = "chrome://version/"; +constexpr char kGoogleURL[] = "www.google.com"; +constexpr char kAboutBlankURL[] = "about:blank"; + +// Asserts that tab groups are correct based on `expected_state`. +void AssertTabGroupsCorrect( + TabStripModel* browser_tab_model, + const crosapi::mojom::DeskTemplateStatePtr& expected_state) { + TabGroupModel* group_model = browser_tab_model->group_model(); + std::vector<tab_groups::TabGroupId> tab_group_id_list = + group_model->ListTabGroups(); + + EXPECT_TRUE(expected_state->groups.has_value()); + std::vector<tab_groups::TabGroupInfo>& expected_groups = + expected_state->groups.value(); + + for (const auto& group_id : tab_group_id_list) { + TabGroup* current_group = group_model->GetTabGroup(group_id); + + tab_groups::TabGroupInfo current_group_info = tab_groups::TabGroupInfo( + current_group->ListTabs(), + tab_groups::TabGroupVisualData(*current_group->visual_data())); + auto it = std::find(expected_groups.begin(), expected_groups.end(), + current_group_info); + + EXPECT_FALSE(it == expected_groups.end()); + } +} + +// Assertst that `browser` was created correctly based on `expected_state` and +// `initial_bounds`. +void AssertBrowserCreatedCorrectly( + Browser* browser, + const crosapi::mojom::DeskTemplateStatePtr& expected_state, + const gfx::Rect& initial_bounds) { + EXPECT_TRUE(browser); + + EXPECT_EQ(initial_bounds, browser->create_params().initial_bounds); + + if (expected_state->browser_app_name.has_value()) { + EXPECT_EQ(browser->create_params().type, Browser::Type::TYPE_APP); + } else { + EXPECT_EQ(browser->create_params().type, Browser::Type::TYPE_NORMAL); + } + + TabStripModel* browser_tab_model = browser->tab_strip_model(); + EXPECT_TRUE(browser_tab_model); + + EXPECT_EQ(expected_state->urls.size(), + static_cast<uint32_t>(browser_tab_model->count())); + + // We expect order of the browser's tabs to be equivalent to the tabs given. + int tab_index = 0; + for (const auto& expected_url : expected_state->urls) { + EXPECT_EQ(expected_url, + browser_tab_model->GetWebContentsAt(tab_index)->GetURL()); + ++tab_index; + } + + if (browser_tab_model->SupportsTabGroups() && + expected_state->groups.has_value()) { + AssertTabGroupsCorrect(browser_tab_model, expected_state); + } + + EXPECT_EQ( + expected_state->first_non_pinned_index, + static_cast<uint32_t>(browser_tab_model->IndexOfFirstNonPinnedTab())); +} + +} // namespace + +class DeskTemplateClientLacrosBrowserTest : public InProcessBrowserTest { + public: + // Returns the correct GURL object for "www.google.com/test" which is used + // as a testing URL. + GURL GetGoogleTestURL() { + return embedded_test_server()->GetURL(kGoogleURL, "/test"); + } + + // Returns a maximal `DeskTemplateStatePtr` mojom for testing without pinned + // tabs and tab groups. + crosapi::mojom::DeskTemplateStatePtr + MakeTestStateWithoutPinnedTabsOrTabGroup() { + crosapi::mojom::DeskTemplateStatePtr state = + crosapi::mojom::DeskTemplateState::New(); + + state->urls = std::vector<GURL>( + {GURL(kChromeVersionUrl), GURL(kAboutBlankURL), GetGoogleTestURL(), + GURL(kChromeVersionUrl), GURL(kChromeVersionUrl)}); + state->active_index = 0; + + return state; + } + + // Returns a maximal `DeskTemplateStatePtr` mojom for testing. + crosapi::mojom::DeskTemplateStatePtr MakeTestMojom() { + crosapi::mojom::DeskTemplateStatePtr state = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + + // Add in tab groups and pinned tabs. + state->first_non_pinned_index = 1; + state->groups = + std::vector<tab_groups::TabGroupInfo>({tab_groups::TabGroupInfo( + gfx::Range(2, 4), + tab_groups::TabGroupVisualData( + u"tab group one", tab_groups::TabGroupColorId::kGreen))}); + + return state; + } + + // Returns a PWA `DeskTemplateStatePtr` mojom for testing app launches work in + // lacros. + crosapi::mojom::DeskTemplateStatePtr MakeAppTestMojom() { + crosapi::mojom::DeskTemplateStatePtr state = + crosapi::mojom::DeskTemplateState::New(); + + state->urls = std::vector<GURL>({GURL(kChromeVersionUrl)}); + state->active_index = 0; + state->browser_app_name = kTestName; + + return state; + } + + // Returns the result of MakeTestMojom with additional invalid tab groups. + // The result of launching a browser with this should pass + // AssertBrowserCreated correctly with the standard MakeTestMojom object + // passed as the mojom to assert against. + crosapi::mojom::DeskTemplateStatePtr MakeInvalidTabGroupTestMojom() { + crosapi::mojom::DeskTemplateStatePtr state = MakeTestMojom(); + + EXPECT_TRUE(state->groups.has_value()); + + // First group violates the upper bound of the tab range. + state->groups->emplace_back(tab_groups::TabGroupInfo( + gfx::Range(4, 6), + tab_groups::TabGroupVisualData(u"tab_group_two", + tab_groups::TabGroupColorId::kBlue))); + + return state; + } + + // Returns the result of MakeTestStateWithoutPinnedTabsOrTabGroup with an + // invalid first non pinned index The result of launching a browser with this + // should pass AssertBrowserCreated correctley with the standard + // MakeTestStateWithoutPinnedTabsOrTabGroup object passed as the mojom to + // assert against. + crosapi::mojom::DeskTemplateStatePtr MakeInvalidPinnedTabTestMojom() { + crosapi::mojom::DeskTemplateStatePtr state = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + + // first non pinned index in this case will be larger than the count of + // tabs./ + state->first_non_pinned_index = 5; + + return state; + } + + // Request handler method, just returns a simple plaintext response when + // invoked. We're not testing the underlying behavior of the browser, rather + // simply that normal URLs invoked on template launch are handled correctly. + std::unique_ptr<net::test_server::HttpResponse> HandleRequest( + const net::test_server::HttpRequest& request) { + // We're not interested in the contents of the response for this test + // any response should be valid. + auto http_response = + std::make_unique<net::test_server::BasicHttpResponse>(); + http_response->set_code(net::HTTP_OK); + http_response->set_content("hello"); + http_response->set_content_type("text/plain"); + return http_response; + } + + // SetUp for test base class, initializes the embedded test server. + void SetUp() override { + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + InProcessBrowserTest::SetUp(); + } + + // Sets Up embedded test server to listen on IO thread. + void SetUpOnMainThread() override { + host_resolver()->AddRule(kGoogleURL, "127.0.0.1"); + + embedded_test_server()->RegisterRequestHandler( + base::BindRepeating(&DeskTemplateClientLacrosBrowserTest::HandleRequest, + base::Unretained(this))); + embedded_test_server()->StartAcceptingConnections(); + } + + // Helper function that modifies the test's browser() object to match the + // representation produced in the `MakeTestMojom` function. + void MakeTestBrowser() { + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 0, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 2, GetGoogleTestURL(), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 3, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 4, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + + TabStripModel* strip_model = browser()->tab_strip_model(); + + // May not be necessary but guarantees that the correct tab is active. + strip_model->ActivateTabAt(0); + + // Assert we haven't moved the pinned tab. + EXPECT_EQ(0, strip_model->SetTabPinned(0, /*pinned=*/true)); + tab_groups::TabGroupId group_id_one = strip_model->AddToNewGroup({2, 3}); + + TabGroupModel* group_model = strip_model->group_model(); + TabGroup* group_one = group_model->GetTabGroup(group_id_one); + group_one->SetVisualData(tab_groups::TabGroupVisualData( + u"tab group one", tab_groups::TabGroupColorId::kGreen)); + } + + void MakeTestAppBrowser() { + Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); + + Browser::CreateParams create_params = Browser::CreateParams::CreateForApp( + kTestName, /*trusted_source=*/true, {0, 0, 256, 256}, profile, + /*user_gesture=*/false); + Browser::Create(create_params); + + // Close default test browser, we will set browser to the browser created + // by this method. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 0, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + } + + // Instantiates a browser that when captured should assert equivalence with + // MakeTestStateWithoutPinnedTabsOrTabGroups. + void MakeBrowserWithoutTabgroupsOrPinnedTabs() { + Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); + + Browser::CreateParams create_params(profile, /*user_gesture=*/false); + create_params.initial_bounds = gfx::Rect(0, 0, 256, 256); + create_params.are_tab_groups_enabled = false; + Browser::Create(create_params); + + // Close default test browser, we will set browser to the browser created + // by this method. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 0, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 1, GURL(kAboutBlankURL), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 2, GetGoogleTestURL(), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 3, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + EXPECT_TRUE( + AddTabAtIndexToBrowser(browser(), 4, GURL(kChromeVersionUrl), + ui::PageTransition::PAGE_TRANSITION_LINK)); + + TabStripModel* strip_model = browser()->tab_strip_model(); + + // May not be necessary but guarantees that the correct tab is active. + strip_model->ActivateTabAt(0); + } +}; + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + LaunchesBrowserCorrectly) { + // State pointers don't supply a Clone operation. Therefore we will create + // two semantically identical states to test against. + crosapi::mojom::DeskTemplateStatePtr expected_state = MakeTestMojom(); + crosapi::mojom::DeskTemplateStatePtr launch_parameters = MakeTestMojom(); + gfx::Rect expected_bounds(0, 0, 256, 256); + + DeskTemplateClientLacros client; + + client.CreateBrowserWithRestoredData( + expected_bounds, ui::mojom::WindowShowState::SHOW_STATE_DEFAULT, + std::move(launch_parameters)); + + // Close default test browser, we will set browser to the browser created + // by the method under test. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + AssertBrowserCreatedCorrectly(browser(), expected_state, expected_bounds); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + LaunchesBrowserAppCorrectly) { + // State pointers don't supply a Clone operation. Therefore we will create + // two semantically identical states to test against. + crosapi::mojom::DeskTemplateStatePtr expected_state = MakeAppTestMojom(); + crosapi::mojom::DeskTemplateStatePtr launch_parameters = MakeAppTestMojom(); + gfx::Rect expected_bounds(0, 0, 256, 256); + + DeskTemplateClientLacros client; + + client.CreateBrowserWithRestoredData( + expected_bounds, ui::mojom::WindowShowState::SHOW_STATE_DEFAULT, + std::move(launch_parameters)); + + // Close default test browser, we will set browser to the browser created + // by the method under test. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + AssertBrowserCreatedCorrectly(browser(), expected_state, expected_bounds); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + IgnoresInvalidTabGroups) { + // When launched the invalid tab groups should be removed before being + // attached to the browser, so we assert against the regular test mojom. + crosapi::mojom::DeskTemplateStatePtr expected_state = MakeTestMojom(); + crosapi::mojom::DeskTemplateStatePtr launch_parameters = + MakeInvalidTabGroupTestMojom(); + gfx::Rect expected_bounds(0, 0, 256, 256); + + DeskTemplateClientLacros client; + + client.CreateBrowserWithRestoredData( + expected_bounds, ui::mojom::WindowShowState::SHOW_STATE_DEFAULT, + std::move(launch_parameters)); + + // Close default test browser, we will set browser to the browser created + // by the method under test. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + AssertBrowserCreatedCorrectly(browser(), expected_state, expected_bounds); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + LaunchesOldBrowserCorrectly) { + // State pointers don't supply a Clone operation. Therefore we will create + // two semantically identical states to test against. + crosapi::mojom::DeskTemplateStatePtr expected_state = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + crosapi::mojom::DeskTemplateStatePtr launch_parameters = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + gfx::Rect expected_bounds(0, 0, 256, 256); + + DeskTemplateClientLacros client; + + client.CreateBrowserWithRestoredData( + expected_bounds, ui::mojom::WindowShowState::SHOW_STATE_DEFAULT, + std::move(launch_parameters)); + + // Close default test browser, we will set browser to the browser created + // by the method under test. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + AssertBrowserCreatedCorrectly(browser(), expected_state, expected_bounds); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + IgnoresInvalidPinnedTab) { + // State pointers don't supply a Clone operation. Therefore we will create + // two semantically identical states to test against. + crosapi::mojom::DeskTemplateStatePtr expected_state = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + crosapi::mojom::DeskTemplateStatePtr launch_parameters = + MakeInvalidPinnedTabTestMojom(); + gfx::Rect expected_bounds(0, 0, 256, 256); + + DeskTemplateClientLacros client; + + client.CreateBrowserWithRestoredData( + expected_bounds, ui::mojom::WindowShowState::SHOW_STATE_DEFAULT, + std::move(launch_parameters)); + + // Close default test browser, we will set browser to the browser created + // by the method under test. + CloseBrowserSynchronously(browser()); + SelectFirstBrowser(); + + AssertBrowserCreatedCorrectly(browser(), expected_state, expected_bounds); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + CapturesBrowserCorrectly) { + MakeTestBrowser(); + DeskTemplateClientLacros client; + crosapi::mojom::DeskTemplateClientAsyncWaiter waiter(&client); + std::string window_id = views::DesktopWindowTreeHostLacros::From( + browser()->window()->GetNativeWindow()->GetHost()) + ->platform_window() + ->GetWindowUniqueId(); + + uint32_t out_serial; + std::string out_window_id; + crosapi::mojom::DeskTemplateStatePtr out_state; + waiter.GetBrowserInformation(/*serial=*/0, window_id, &out_serial, + &out_window_id, &out_state); + + crosapi::mojom::DeskTemplateStatePtr test_mojom = MakeTestMojom(); + EXPECT_EQ(out_state->urls, test_mojom->urls); + EXPECT_EQ(out_state->active_index, test_mojom->active_index); + EXPECT_EQ(out_state->first_non_pinned_index, + test_mojom->first_non_pinned_index); + EXPECT_TRUE(test_mojom->groups.has_value()); + EXPECT_TRUE(out_state->groups.has_value()); + + // We don't care about the order of tab groups. + EXPECT_THAT(out_state->groups.value(), + testing::UnorderedElementsAreArray(test_mojom->groups.value())); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + CapturesBrowserWithoutPinnedTabsOrTabGroupsCorrectly) { + MakeBrowserWithoutTabgroupsOrPinnedTabs(); + DeskTemplateClientLacros client; + crosapi::mojom::DeskTemplateClientAsyncWaiter waiter(&client); + std::string window_id = views::DesktopWindowTreeHostLacros::From( + browser()->window()->GetNativeWindow()->GetHost()) + ->platform_window() + ->GetWindowUniqueId(); + + uint32_t out_serial; + std::string out_window_id; + crosapi::mojom::DeskTemplateStatePtr out_state; + waiter.GetBrowserInformation(/*serial=*/0, window_id, &out_serial, + &out_window_id, &out_state); + + crosapi::mojom::DeskTemplateStatePtr test_mojom = + MakeTestStateWithoutPinnedTabsOrTabGroup(); + EXPECT_EQ(out_state->urls, test_mojom->urls); + EXPECT_EQ(out_state->active_index, test_mojom->active_index); + + // first_non_pinned_index defaults to zero so it should be zero when unset. + // This value would be ignored if launched as is asserted in tests above. + EXPECT_EQ(out_state->first_non_pinned_index, 0u); + + // This state should not contain tab groups. + EXPECT_FALSE(out_state->groups.has_value()); +} + +IN_PROC_BROWSER_TEST_F(DeskTemplateClientLacrosBrowserTest, + CapturesBrowserAppCorrectly) { + MakeTestAppBrowser(); + DeskTemplateClientLacros client; + crosapi::mojom::DeskTemplateClientAsyncWaiter waiter(&client); + std::string window_id = views::DesktopWindowTreeHostLacros::From( + browser()->window()->GetNativeWindow()->GetHost()) + ->platform_window() + ->GetWindowUniqueId(); + + uint32_t out_serial; + std::string out_window_id; + crosapi::mojom::DeskTemplateStatePtr out_state; + waiter.GetBrowserInformation(/*serial=*/0, window_id, &out_serial, + &out_window_id, &out_state); + + crosapi::mojom::DeskTemplateStatePtr test_mojom = MakeAppTestMojom(); + EXPECT_EQ(out_state->urls, test_mojom->urls); + EXPECT_EQ(out_state->browser_app_name, test_mojom->browser_app_name); +}
diff --git a/chrome/browser/load_library_perf_test.cc b/chrome/browser/load_library_perf_test.cc index 1ad53ee..d0ff6d3 100644 --- a/chrome/browser/load_library_perf_test.cc +++ b/chrome/browser/load_library_perf_test.cc
@@ -20,6 +20,7 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "media/cdm/cdm_paths.h" +#include "media/cdm/clear_key_cdm_common.h" #endif namespace {
diff --git a/chrome/browser/mac/relauncher.mm b/chrome/browser/mac/relauncher.mm index fcb3726..aab5837 100644 --- a/chrome/browser/mac/relauncher.mm +++ b/chrome/browser/mac/relauncher.mm
@@ -5,8 +5,7 @@ #include "chrome/browser/mac/relauncher.h" #import <AppKit/AppKit.h> - -#include <AvailabilityMacros.h> +#include <CoreFoundation/CoreFoundation.h> #include <crt_externs.h> #include <dlfcn.h> #include <stddef.h> @@ -19,9 +18,12 @@ #include <string> #include <vector> +#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/logging.h" +#include "base/mac/bundle_locations.h" +#include "base/mac/launch_application.h" #include "base/mac/mac_logging.h" #include "base/mac/scoped_nsobject.h" #include "base/path_service.h" @@ -42,7 +44,7 @@ // The "magic" file descriptor that the relauncher process' write side of the // pipe shows up on. Chosen to avoid conflicting with stdin, stdout, and // stderr. -const int kRelauncherSyncFD = STDERR_FILENO + 1; +constexpr int kRelauncherSyncFD = STDERR_FILENO + 1; // The argument separating arguments intended for the relauncher process from // those intended for the relaunched process. "---" is chosen instead of "--" @@ -51,17 +53,19 @@ // arguments intended for the relaunched process, to get the correct settings // for such things as logging and the user-data-dir in case it affects crash // reporting. -const char kRelauncherArgSeparator[] = "---"; +constexpr char kRelauncherArgSeparator[] = "---"; // When this argument is supplied to the relauncher process, it will launch // the relaunched process without bringing it to the foreground. -const char kRelauncherBackgroundArg[] = "--background"; +constexpr char kRelauncherBackgroundArg[] = "--background"; // The beginning of the "process serial number" argument that Launch Services // sometimes inserts into command lines. A process serial number is only valid // for a single process, so any PSN arguments will be stripped from command -// lines during relaunch to avoid confusion. -const char kPSNArg[] = "-psn_"; +// lines during relaunch to avoid confusion. When using the CommandLine +// interface, -psn_ may have been rewritten as --psn_. Look for both. +constexpr char kPSNArg[] = "-psn_"; +constexpr char kAltPSNArg[] = "--psn_"; // Returns the "type" argument identifying a relauncher process // ("--type=relauncher"). @@ -94,12 +98,13 @@ const std::vector<std::string>& relauncher_args, const std::vector<std::string>& args) { std::vector<std::string> relaunch_args; + relaunch_args.reserve(relauncher_args.size() + args.size() + 4); relaunch_args.push_back(helper); relaunch_args.push_back(RelauncherTypeArg()); // If this application isn't in the foreground, the relaunched one shouldn't // be either. - if (![NSApp isActive]) { + if (!NSApp.active) { relaunch_args.push_back(kRelauncherBackgroundArg); } @@ -108,14 +113,15 @@ relaunch_args.push_back(kRelauncherArgSeparator); - // When using the CommandLine interface, -psn_ may have been rewritten as - // --psn_. Look for both. - const char alt_psn_arg[] = "--psn_"; - for (size_t index = 0; index < args.size(); ++index) { - // Strip any -psn_ arguments, as they apply to a specific process. - if (args[index].compare(0, strlen(kPSNArg), kPSNArg) != 0 && - args[index].compare(0, strlen(alt_psn_arg), alt_psn_arg) != 0) { - relaunch_args.push_back(args[index]); + // The first item of `args` is the path to the executable, but launch APIs + // require the path to the bundle. Rather than try to derive the bundle path + // from the executable path, substitute in the bundle path. + relaunch_args.push_back(base::mac::OuterBundlePath().value()); + for (size_t i = 1; i < args.size(); ++i) { + // Strip any PSN arguments, as they apply to a specific process. + if (args[i].compare(0, strlen(kPSNArg), kPSNArg) != 0 && + args[i].compare(0, strlen(kAltPSNArg), kAltPSNArg) != 0) { + relaunch_args.push_back(args[i]); } } @@ -143,8 +149,7 @@ "kRelauncherSyncFD must not conflict with stdio fds"); base::LaunchOptions options; - options.fds_to_remap.push_back( - std::make_pair(pipe_write_fd.get(), kRelauncherSyncFD)); + options.fds_to_remap.emplace_back(pipe_write_fd.get(), kRelauncherSyncFD); if (!base::LaunchProcess(relaunch_args, options).IsValid()) { LOG(ERROR) << "base::LaunchProcess failed"; return false; @@ -204,7 +209,7 @@ struct kevent change = { 0 }; EV_SET(&change, parent_pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); - if (kevent(kq.get(), &change, 1, NULL, 0, NULL) == -1) { + if (kevent(kq.get(), &change, 1, nullptr, 0, nullptr) == -1) { PLOG(ERROR) << "kevent (add)"; return; } @@ -219,7 +224,7 @@ // write above to complete. The parent process is now free to exit. Wait for // that to happen. struct kevent event; - int events = kevent(kq.get(), NULL, 0, &event, 1, NULL); + int events = kevent(kq.get(), nullptr, 0, &event, 1, nullptr); if (events != 1) { if (events < 0) { PLOG(ERROR) << "kevent (monitor)"; @@ -276,16 +281,16 @@ RelauncherSynchronizeWithParent(); - // The capacity for relaunch_args is 4 less than argc, because it - // won't contain the argv[0] of the relauncher process, the - // RelauncherTypeArg() at argv[1], kRelauncherArgSeparator, or the - // executable path of the process to be launched. - base::scoped_nsobject<NSMutableArray> relaunch_args( - [[NSMutableArray alloc] initWithCapacity:argc - 4]); + // The capacity for relaunch_args is 4 less than argc, because it won't + // contain the argv[0] of the relauncher process, the RelauncherTypeArg() at + // argv[1], kRelauncherArgSeparator, or the executable path of the process + // to be launched. + std::vector<std::string> relaunch_args; + relaunch_args.reserve(argc - 4); // Figure out what to execute, what arguments to pass it, and whether to - // start it in the background. - bool background = false; + // start it activated. + bool activate = true; bool in_relaunch_args = false; std::string dmg_bsd_device_name; bool seen_relaunch_executable = false; @@ -304,7 +309,7 @@ if (arg == kRelauncherArgSeparator) { in_relaunch_args = true; } else if (arg == kRelauncherBackgroundArg) { - background = true; + activate = false; } else if (arg.compare(0, relauncher_dmg_device_arg.size(), relauncher_dmg_device_arg) == 0) { dmg_bsd_device_name.assign( @@ -312,19 +317,14 @@ } } else { if (!seen_relaunch_executable) { - // The first argument after kRelauncherBackgroundArg is the path to - // the executable file or .app bundle directory. The Launch Services - // interface wants this separate from the rest of the arguments. In - // the relaunched process, this path will still be visible at argv[0]. + // The first argument after kRelauncherArgSeparator is the path to the + // .app bundle directory. The Launch Services interface wants this + // separate from the rest of the arguments. In the relaunched process, + // the executable path will still be visible at argv[0]. relaunch_executable.assign(arg); seen_relaunch_executable = true; } else { - NSString* arg_string = base::SysUTF8ToNSString(arg); - if (!arg_string) { - LOG(ERROR) << "base::SysUTF8ToNSString failed for " << arg; - return 1; - } - [relaunch_args addObject:arg_string]; + relaunch_args.push_back(arg); } } } @@ -334,28 +334,24 @@ return 1; } - NSString* path = base::SysUTF8ToNSString(relaunch_executable); - base::scoped_nsobject<NSURL> url([[NSURL alloc] initFileURLWithPath:path]); - NSDictionary* configuration = - @{NSWorkspaceLaunchConfigurationArguments : (relaunch_args.get())}; + base::mac::LaunchApplication( + base::FilePath(relaunch_executable), relaunch_args, /*url_specs=*/{}, + {.activate = activate, + .create_new_instance = true, + .prompt_user_if_needed = true}, + base::BindOnce( + [](base::expected<NSRunningApplication*, NSError*> result) { + if (!result.has_value()) { + LOG(ERROR) << "Failed to relaunch: " + << base::SysNSStringToUTF8( + result.error().description); + } - NSRunningApplication* application = [[NSWorkspace sharedWorkspace] - launchApplicationAtURL:url - options:NSWorkspaceLaunchDefault | - NSWorkspaceLaunchWithErrorPresentation | - (background ? NSWorkspaceLaunchWithoutActivation - : 0) | - NSWorkspaceLaunchNewInstance - configuration:configuration - error:nil]; - if (!application) { - LOG(ERROR) << "Failed to relaunch " << relaunch_executable; - return 1; - } + CFRunLoopStop(CFRunLoopGetMain()); + })); - // The application should have relaunched (or is in the process of - // relaunching). From this point on, only clean-up tasks should occur, and - // failures are tolerable. + // This is running the main thread. + CFRunLoopRun(); if (!dmg_bsd_device_name.empty()) { EjectAndTrashDiskImage(dmg_bsd_device_name);
diff --git a/chrome/browser/media/DEPS b/chrome/browser/media/DEPS index cc7fc17..5a572d1 100644 --- a/chrome/browser/media/DEPS +++ b/chrome/browser/media/DEPS
@@ -4,8 +4,7 @@ "+media/audio", "+media/base", "+media/cast", - "+media/cdm/media_foundation_cdm_data.h", - "+media/cdm/supported_cdm_versions.h", + "+media/cdm", "+media/media_buildflags.h", "+media/mojo/mojom", # safe_dial_device_description_parser_unittest.cc needs DataDecoderService.
diff --git a/chrome/browser/media/cast_mirroring_performance_browsertest.cc b/chrome/browser/media/cast_mirroring_performance_browsertest.cc index 851ec67..b311fac 100644 --- a/chrome/browser/media/cast_mirroring_performance_browsertest.cc +++ b/chrome/browser/media/cast_mirroring_performance_browsertest.cc
@@ -893,8 +893,7 @@ mirroring::mojom::SessionType::AUDIO_AND_VIDEO, endpoint.address(), "model_name", "friendly_name", "sender-123", "receiver-456", base::Milliseconds(kTargetPlayoutDelayMs), - false /* is_remote_playback */, absl::nullopt /** refresh_interval */, - false /** force_letterboxing */); + false /* is_remote_playback */, false /** force_letterboxing */); host_->Start(std::move(session_params), std::move(observer_remote), std::move(channel_remote), channel_to_service_.BindNewPipeAndPassReceiver(), "Sink Name");
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc index e294bc08..49a8a35a 100644 --- a/chrome/browser/media/encrypted_media_browsertest.cc +++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -32,6 +32,7 @@ #include "media/base/key_system_names.h" #include "media/base/media_switches.h" #include "media/base/test_data_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/supported_cdm_versions.h" #include "media/media_buildflags.h" #include "testing/gtest/include/gtest/gtest-spi.h" @@ -44,35 +45,11 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "chrome/browser/media/library_cdm_test_helper.h" -#include "media/cdm/cdm_paths.h" #endif -// Available key systems. -const char kClearKeyKeySystem[] = "org.w3.clearkey"; -const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; - #if BUILDFLAG(ENABLE_LIBRARY_CDMS) -// Variants of External Clear Key key system to test different scenarios. -// To add a new variant, make sure you also update: -// - media/test/data/eme_player_js/globals.js -// - media/test/data/eme_player_js/player_utils.js -// - CreateCdmInstance() in clear_key_cdm.cc -const char kExternalClearKeyMessageTypeTestKeySystem[] = - "org.chromium.externalclearkey.messagetypetest"; -const char kExternalClearKeyFileIOTestKeySystem[] = - "org.chromium.externalclearkey.fileiotest"; const char kExternalClearKeyInitializeFailKeySystem[] = "org.chromium.externalclearkey.initializefail"; -const char kExternalClearKeyPlatformVerificationTestKeySystem[] = - "org.chromium.externalclearkey.platformverificationtest"; -const char kExternalClearKeyCrashKeySystem[] = - "org.chromium.externalclearkey.crash"; -#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) -const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = - "org.chromium.externalclearkey.verifycdmhosttest"; -#endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) -const char kExternalClearKeyStorageIdTestKeySystem[] = - "org.chromium.externalclearkey.storageidtest"; #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) // Sessions to load. @@ -124,9 +101,10 @@ class EncryptedMediaTestBase : public MediaBrowserTest { public: bool IsExternalClearKey(const std::string& key_system) { - if (key_system == kExternalClearKeyKeySystem) + if (key_system == media::kExternalClearKeyKeySystem) { return true; - std::string prefix = std::string(kExternalClearKeyKeySystem) + '.'; + } + std::string prefix = std::string(media::kExternalClearKeyKeySystem) + '.'; return key_system.substr(0, prefix.size()) == prefix; } @@ -340,7 +318,7 @@ int GetCdmInterfaceVersion() { return GetParam(); } // We use special |key_system| names to do non-playback related tests, - // e.g. kExternalClearKeyFileIOTestKeySystem is used to test file IO. + // e.g. media::kExternalClearKeyFileIOTestKeySystem is used to test file IO. void TestNonPlaybackCases(const std::string& key_system, const std::string& expected_title) { // Since we do not test playback, arbitrarily choose a test file and source @@ -361,7 +339,8 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); - SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, command_line); + SetUpCommandLineForKeySystem(media::kExternalClearKeyKeySystem, + command_line); // Override enabled CDM interface version for testing. command_line->AppendSwitchASCII( switches::kOverrideEnabledCdmInterfaceVersion, @@ -395,7 +374,8 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); - SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, command_line); + SetUpCommandLineForKeySystem(media::kExternalClearKeyKeySystem, + command_line); // The output protection tests create a MediaRecorder on a MediaStream, // so this allows for a fake stream to be created. command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); @@ -408,7 +388,7 @@ class ECKIncognitoEncryptedMediaTest : public EncryptedMediaTestBase { public: // We use special |key_system| names to do non-playback related tests, - // e.g. kExternalClearKeyFileIOTestKeySystem is used to test file IO. + // e.g. media::kExternalClearKeyFileIOTestKeySystem is used to test file IO. void TestNonPlaybackCases(const std::string& key_system, const std::string& expected_title) { // Since we do not test playback, arbitrarily choose a test file and source @@ -421,7 +401,8 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); - SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, command_line); + SetUpCommandLineForKeySystem(media::kExternalClearKeyKeySystem, + command_line); command_line->AppendSwitch(switches::kIncognito); } }; @@ -543,34 +524,34 @@ INSTANTIATE_TEST_SUITE_P(MSE_ClearKey, EncryptedMediaTest, - Combine(Values(kClearKeyKeySystem), + Combine(Values(media::kClearKeyKeySystem), Values(SrcType::MSE))); INSTANTIATE_TEST_SUITE_P(MSE_ClearKey, MseEncryptedMediaTest, - Values(kClearKeyKeySystem)); + Values(media::kClearKeyKeySystem)); // External Clear Key is currently only used on platforms that use library CDMs. #if BUILDFLAG(ENABLE_LIBRARY_CDMS) INSTANTIATE_TEST_SUITE_P(SRC_ExternalClearKey, EncryptedMediaTest, - Combine(Values(kExternalClearKeyKeySystem), + Combine(Values(media::kExternalClearKeyKeySystem), Values(SrcType::SRC))); INSTANTIATE_TEST_SUITE_P(MSE_ExternalClearKey, EncryptedMediaTest, - Combine(Values(kExternalClearKeyKeySystem), + Combine(Values(media::kExternalClearKeyKeySystem), Values(SrcType::MSE))); INSTANTIATE_TEST_SUITE_P(MSE_ExternalClearKey, MseEncryptedMediaTest, - Values(kExternalClearKeyKeySystem)); + Values(media::kExternalClearKeyKeySystem)); #else // BUILDFLAG(ENABLE_LIBRARY_CDMS) // To reduce test time, only run ClearKey SRC tests when we are not running // ExternalClearKey SRC tests. INSTANTIATE_TEST_SUITE_P(SRC_ClearKey, EncryptedMediaTest, - Combine(Values(kClearKeyKeySystem), + Combine(Values(media::kClearKeyKeySystem), Values(SrcType::SRC))); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) @@ -583,7 +564,7 @@ INSTANTIATE_TEST_SUITE_P(MSE_Widevine, MseEncryptedMediaTest, Values(kWidevineKeySystem)); -#endif // #if BUILDFLAG(BUNDLE_WIDEVINE_CDM) +#endif // BUILDFLAG(BUNDLE_WIDEVINE_CDM) IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) { TestSimplePlayback("bear-320x240-av_enc-a.webm"); @@ -825,17 +806,19 @@ // When CDM crashes, we should still get a decode error and all sessions should // be closed. IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, MAYBE_CDMCrashDuringDecode) { - TestNonPlaybackCases(kExternalClearKeyCrashKeySystem, + TestNonPlaybackCases(media::kExternalClearKeyCrashKeySystem, kEmeSessionClosedAndError); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, FileIOTest) { - TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem, kUnitTestSuccess); + TestNonPlaybackCases(media::kExternalClearKeyFileIOTestKeySystem, + kUnitTestSuccess); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, PlatformVerificationTest) { - TestNonPlaybackCases(kExternalClearKeyPlatformVerificationTestKeySystem, - kUnitTestSuccess); + TestNonPlaybackCases( + media::kExternalClearKeyPlatformVerificationTestKeySystem, + kUnitTestSuccess); } // Intermittent leaks on ASan/LSan runs: crbug.com/889923 @@ -845,8 +828,8 @@ #define MAYBE_MessageTypeTest MessageTypeTest #endif IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, MAYBE_MessageTypeTest) { - TestPlaybackCase(kExternalClearKeyMessageTypeTestKeySystem, kNoSessionToLoad, - media::kEndedTitle); + TestPlaybackCase(media::kExternalClearKeyMessageTypeTestKeySystem, + kNoSessionToLoad, media::kEndedTitle); int num_received_message_types = 0; EXPECT_TRUE(content::ExecuteScriptAndExtractInt( @@ -861,34 +844,32 @@ } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, LoadPersistentLicense) { - TestPlaybackCase(kExternalClearKeyKeySystem, kPersistentLicense, + TestPlaybackCase(media::kExternalClearKeyKeySystem, kPersistentLicense, media::kEndedTitle); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, LoadUnknownSession) { - TestPlaybackCase(kExternalClearKeyKeySystem, kUnknownSession, + TestPlaybackCase(media::kExternalClearKeyKeySystem, kUnknownSession, kEmeSessionNotFound); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, LoadSessionAfterClose) { - base::StringPairs query_params{{"keySystem", kExternalClearKeyKeySystem}}; + base::StringPairs query_params{ + {"keySystem", media::kExternalClearKeyKeySystem}}; RunEncryptedMediaTestPage("eme_load_session_after_close_test.html", - kExternalClearKeyKeySystem, query_params, + media::kExternalClearKeyKeySystem, query_params, media::kEndedTitle); } -const char kExternalClearKeyDecryptOnlyKeySystem[] = - "org.chromium.externalclearkey.decryptonly"; - IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, DecryptOnly_VideoAudio_WebM) { RunSimpleEncryptedMediaTest("bear-320x240-av_enc-av.webm", - kExternalClearKeyDecryptOnlyKeySystem, + media::kExternalClearKeyDecryptOnlyKeySystem, SrcType::MSE); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, DecryptOnly_VideoOnly_MP4_VP9) { RunSimpleEncryptedMediaTest("bear-320x240-v_frag-vp9-cenc.mp4", - kExternalClearKeyDecryptOnlyKeySystem, + media::kExternalClearKeyDecryptOnlyKeySystem, SrcType::MSE); } @@ -900,8 +881,8 @@ std::string expected_result = GetCdmInterfaceVersion() >= 10 ? media::kEndedTitle : media::kErrorTitle; RunEncryptedMediaTest(kDefaultEmePlayer, "bear-640x360-v_frag-cbcs.mp4", - kExternalClearKeyDecryptOnlyKeySystem, SrcType::MSE, - kNoSessionToLoad, false, PlayCount::ONCE, + media::kExternalClearKeyDecryptOnlyKeySystem, + SrcType::MSE, kNoSessionToLoad, false, PlayCount::ONCE, expected_result); } @@ -909,18 +890,18 @@ // content/browser/media/encrypted_media_browsertest.cc. IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, Playback_Encryption_CENC) { RunEncryptedMediaMultipleFileTest( - kExternalClearKeyKeySystem, "bear-640x360-v_frag-cenc.mp4", + media::kExternalClearKeyKeySystem, "bear-640x360-v_frag-cenc.mp4", "bear-640x360-a_frag-cenc.mp4", media::kEndedTitle); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, Playback_Encryption_CBC1) { - RunEncryptedMediaMultipleFileTest(kExternalClearKeyKeySystem, + RunEncryptedMediaMultipleFileTest(media::kExternalClearKeyKeySystem, "bear-640x360-v_frag-cbc1.mp4", std::string(), media::kErrorTitle); } IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, Playback_Encryption_CENS) { - RunEncryptedMediaMultipleFileTest(kExternalClearKeyKeySystem, + RunEncryptedMediaMultipleFileTest(media::kExternalClearKeyKeySystem, "bear-640x360-v_frag-cens.mp4", std::string(), media::kErrorTitle); } @@ -931,7 +912,7 @@ std::string expected_result = GetCdmInterfaceVersion() >= 10 ? media::kEndedTitle : media::kErrorTitle; RunEncryptedMediaMultipleFileTest( - kExternalClearKeyKeySystem, "bear-640x360-v_frag-cbcs.mp4", + media::kExternalClearKeyKeySystem, "bear-640x360-v_frag-cbcs.mp4", "bear-640x360-a_frag-cbcs.mp4", expected_result); } @@ -939,13 +920,13 @@ #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, VerifyCdmHostTest) { - TestNonPlaybackCases(kExternalClearKeyVerifyCdmHostTestKeySystem, + TestNonPlaybackCases(media::kExternalClearKeyVerifyCdmHostTestKeySystem, kUnitTestSuccess); } #endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) IN_PROC_BROWSER_TEST_P(ECKEncryptedMediaTest, StorageIdTest) { - TestNonPlaybackCases(kExternalClearKeyStorageIdTestKeySystem, + TestNonPlaybackCases(media::kExternalClearKeyStorageIdTestKeySystem, kUnitTestSuccess); } @@ -992,14 +973,16 @@ IN_PROC_BROWSER_TEST_F(ECKIncognitoEncryptedMediaTest, FileIO) { // Try the FileIO test using the default CDM API while running in incognito. - TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem, kUnitTestSuccess); + TestNonPlaybackCases(media::kExternalClearKeyFileIOTestKeySystem, + kUnitTestSuccess); } IN_PROC_BROWSER_TEST_F(ECKIncognitoEncryptedMediaTest, LoadSessionAfterClose) { // Loading a session should work in incognito mode. - base::StringPairs query_params{{"keySystem", kExternalClearKeyKeySystem}}; + base::StringPairs query_params{ + {"keySystem", media::kExternalClearKeyKeySystem}}; RunEncryptedMediaTestPage("eme_load_session_after_close_test.html", - kExternalClearKeyKeySystem, query_params, + media::kExternalClearKeyKeySystem, query_params, media::kEndedTitle); } #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
diff --git a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc index f897371b..58a8c5d 100644 --- a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc +++ b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
@@ -31,6 +31,7 @@ #include "content/public/test/browser_test_utils.h" #include "media/base/media_switches.h" #include "media/base/test_data_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "third_party/widevine/cdm/buildflags.h" @@ -38,7 +39,6 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "chrome/browser/media/library_cdm_test_helper.h" -#include "media/cdm/cdm_paths.h" #endif #if BUILDFLAG(IS_ANDROID) @@ -47,8 +47,9 @@ namespace { -const char kClearKey[] = "org.w3.clearkey"; -const char kExternalClearKey[] = "org.chromium.externalclearkey"; +const char* kClearKey = media::kClearKeyKeySystem; +const char* kExternalClearKey = media::kExternalClearKeyKeySystem; + const char kWidevine[] = "com.widevine.alpha"; const char kWidevineExperiment[] = "com.widevine.alpha.experiment";
diff --git a/chrome/browser/media/library_cdm_test_helper.cc b/chrome/browser/media/library_cdm_test_helper.cc index 1220bf1..11e3df3 100644 --- a/chrome/browser/media/library_cdm_test_helper.cc +++ b/chrome/browser/media/library_cdm_test_helper.cc
@@ -12,6 +12,7 @@ #include "base/path_service.h" #include "media/base/media_switches.h" #include "media/cdm/cdm_paths.h" +#include "media/cdm/clear_key_cdm_common.h" void RegisterClearKeyCdm(base::CommandLine* command_line, bool use_wrong_cdm_path) {
diff --git a/chrome/browser/media/router/media_router_feature.cc b/chrome/browser/media/router/media_router_feature.cc index 5332a14..b4cc0b78 100644 --- a/chrome/browser/media/router/media_router_feature.cc +++ b/chrome/browser/media/router/media_router_feature.cc
@@ -9,11 +9,9 @@ #include <utility> #include "base/base64.h" -#include "base/command_line.h" #include "base/containers/flat_map.h" #include "base/feature_list.h" #include "base/no_destructor.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "build/build_config.h" #include "chrome/browser/profiles/incognito_helpers.h" @@ -177,20 +175,6 @@ MediaRouterEnabled(context); } -absl::optional<base::TimeDelta> GetMirroringRefreshInterval() { - const std::string refresh_interval_str = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - "mirroring-refresh-interval-ms"); - if (!refresh_interval_str.empty()) { - int64_t refresh_interval; - if (base::StringToInt64(refresh_interval_str, &refresh_interval) && - refresh_interval > 0) { - return base::Milliseconds(refresh_interval); - } - } - return absl::nullopt; -} - #endif // !BUILDFLAG(IS_ANDROID) } // namespace media_router
diff --git a/chrome/browser/media/router/media_router_feature.h b/chrome/browser/media/router/media_router_feature.h index 7abbf02..81bffab5 100644 --- a/chrome/browser/media/router/media_router_feature.h +++ b/chrome/browser/media/router/media_router_feature.h
@@ -6,9 +6,7 @@ #define CHROME_BROWSER_MEDIA_ROUTER_MEDIA_ROUTER_FEATURE_H_ #include "base/feature_list.h" -#include "base/time/time.h" #include "build/build_config.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class PrefRegistrySimple; class PrefService; @@ -76,12 +74,6 @@ // Returns true if global media controls are used to start and stop casting and // Media Router is enabled for |context|. bool GlobalMediaControlsCastStartStopEnabled(content::BrowserContext* context); - -// Returns the command-line flag value to override the default mirroring refresh -// interval, if set. -// TODO(crbug.com/1394392): Remove this after CastFastRefreshFrames is launched. -absl::optional<base::TimeDelta> GetMirroringRefreshInterval(); - #endif // !BUILDFLAG(IS_ANDROID) } // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.cc b/chrome/browser/media/router/providers/cast/mirroring_activity.cc index 959397b..5f535b8 100644 --- a/chrome/browser/media/router/providers/cast/mirroring_activity.cc +++ b/chrome/browser/media/router/providers/cast/mirroring_activity.cc
@@ -542,7 +542,6 @@ sink_.sink().name(), session.destination_id(), message_handler_->source_id(), cast_source->target_playout_delay(), route().media_source().IsRemotePlaybackSource(), - GetMirroringRefreshInterval(), ShouldForceLetterboxing(cast_data_.model_name)), std::move(observer_remote), std::move(channel_remote), std::move(channel_to_service_receiver_), route_.media_sink_name());
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 2b003f94..92ba79fc 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -14,7 +14,6 @@ #include "base/base64.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/functional/bind.h" @@ -498,7 +497,6 @@ metrics::MetricsStateManager* state_manager) : metrics_state_manager_(state_manager) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - RecordCommandLineMetrics(); incognito_observer_ = IncognitoObserver::Create( base::BindRepeating(&ChromeMetricsServiceClient::UpdateRunningServices, weak_ptr_factory_.GetWeakPtr())); @@ -1038,18 +1036,6 @@ std::move(collect_final_metrics_done_callback_).Run(); } -void ChromeMetricsServiceClient::RecordCommandLineMetrics() { - // Get stats on use of command line. - const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess()); - if (command_line->HasSwitch(switches::kUserDataDir)) { - UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1); - } - - if (command_line->HasSwitch(switches::kApp)) { - UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1); - } -} - bool ChromeMetricsServiceClient::RegisterObservers() { omnibox_url_opened_subscription_ = OmniboxEventGlobalTracker::GetInstance()->RegisterCallback( @@ -1332,6 +1318,13 @@ return metrics_service_->ShouldResetClientIdsOnClonedInstall(); } +base::CallbackListSubscription +ChromeMetricsServiceClient::AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) { + return metrics_state_manager_->AddOnClonedInstallDetectedCallback( + std::move(callback)); +} + #if BUILDFLAG(IS_CHROMEOS_ASH) bool ChromeMetricsServiceClient::ShouldUploadMetricsForUserId(
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index 01717a1..4b3efa9 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -11,6 +11,7 @@ #include <queue> #include <string> +#include "base/callback_list.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" @@ -117,6 +118,8 @@ static void SetNotificationListenerSetupFailedForTesting( bool simulate_failure); bool ShouldResetClientIdsOnClonedInstall() override; + base::CallbackListSubscription AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) override; #if BUILDFLAG(IS_CHROMEOS_ASH) bool ShouldUploadMetricsForUserId(const uint64_t user_id) override; void InitPerUserMetrics() override; @@ -184,9 +187,6 @@ void OnMemoryDetailCollectionDone(); void OnHistogramSynchronizationDone(); - // Records metrics about the switches present on the command line. - void RecordCommandLineMetrics(); - // Registers |this| as an observer for notifications which indicate that a // user is performing work. This is useful to allow some features to sleep, // until the machine becomes active, such as precluding UMA uploads unless @@ -201,12 +201,6 @@ // Called when a URL is opened from the Omnibox. void OnURLOpenedFromOmnibox(OmniboxLog* log); -#if BUILDFLAG(IS_WIN) - // Counts (and removes) the browser crash dump attempt signals left behind by - // any previous browser processes which generated a crash dump. - void CountBrowserCrashDumpAttempts(); -#endif // BUILDFLAG(IS_WIN) - #if BUILDFLAG(IS_CHROMEOS_ASH) // Helper function for initialization of system profile provider. virtual void AsyncInitSystemProfileProvider();
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc index 4ce00b3..7d60010 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -1422,10 +1422,17 @@ if (process_node->GetProcessId() == base::kNullProcessId) continue; - ProcessInfo process_info; + // First add all processes and their basic information. + ProcessInfo& process_info = process_infos.emplace_back(); process_info.pid = process_node->GetProcessId(); process_info.launch_time = process_node->GetLaunchTime(); + // Then add information about their associated page nodes. Only renderers + // are associated with page nodes. + if (process_node->GetProcessType() != content::PROCESS_TYPE_RENDERER) { + continue; + } + base::flat_set<const performance_manager::PageNode*> page_nodes = performance_manager::GraphOperations::GetAssociatedPageNodes( process_node); @@ -1436,7 +1443,7 @@ if (page_id_map.find(page_node) == page_id_map.end()) page_id_map.insert(std::make_pair(page_node, page_id_map.size() + 1)); - PageInfo page_info; + PageInfo& page_info = process_info.page_infos.emplace_back(); page_info.ukm_source_id = page_node->GetUkmSourceID(); DCHECK(page_id_map.find(page_node) != page_id_map.end()); @@ -1447,9 +1454,7 @@ page_node->GetTimeSinceLastVisibilityChange(); page_info.time_since_last_navigation = page_node->GetTimeSinceLastNavigation(); - process_info.page_infos.push_back(std::move(page_info)); } - process_infos.push_back(std::move(process_info)); } std::move(callback).Run(std::move(process_infos)); }
diff --git a/chrome/browser/net/storage_test_utils.cc b/chrome/browser/net/storage_test_utils.cc index 6561496..c36ddf9 100644 --- a/chrome/browser/net/storage_test_utils.cc +++ b/chrome/browser/net/storage_test_utils.cc
@@ -170,4 +170,16 @@ .ExtractBool(); } +std::string FetchWithCredentials(content::RenderFrameHost* frame, + const GURL& url, + const bool cors_enabled) { + constexpr char script[] = R"( + fetch($1, {mode: $2, credentials: 'include'}) + .then((result) => result.text()); + )"; + const std::string mode = cors_enabled ? "cors" : "no-cors"; + return content::EvalJs(frame, content::JsReplace(script, url, mode)) + .ExtractString(); +} + } // namespace storage::test
diff --git a/chrome/browser/net/storage_test_utils.h b/chrome/browser/net/storage_test_utils.h index b54023e..94b462e 100644 --- a/chrome/browser/net/storage_test_utils.h +++ b/chrome/browser/net/storage_test_utils.h
@@ -7,6 +7,8 @@ #include <string> +class GURL; + namespace content { class RenderFrameHost; } // namespace content @@ -45,6 +47,13 @@ // value of true; false otherwise. bool HasStorageAccessForFrame(content::RenderFrameHost* frame); +// Helper to see if a credentialed fetch has cookies access via top-level +// storage access grants. Returns the content of the response if the promise +// resolves. `cors_enabled` sets fetch RequestMode to be "cors" or "no-cors". +std::string FetchWithCredentials(content::RenderFrameHost* frame, + const GURL& url, + const bool cors_enabled); + } // namespace test } // namespace storage #endif // CHROME_BROWSER_NET_STORAGE_TEST_UTILS_H_
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 39d85278..aa9ce8f 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -16,6 +16,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/metrics/ukm_background_recorder_service.h" @@ -47,8 +48,10 @@ #include "third_party/blink/public/mojom/notifications/notification.mojom.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification_types.h" #include "ui/message_center/public/cpp/notifier_id.h" +#include "ui/strings/grit/ui_strings.h" #include "url/origin.h" #if !BUILDFLAG(IS_ANDROID) @@ -528,6 +531,35 @@ if (notification_data.require_interaction) notification.set_never_timeout(true); + notification.set_scenario(message_center::NotificationScenario::DEFAULT); + if (base::FeatureList::IsEnabled(features::kIncomingCallNotifications) && + notification_data.scenario == + blink::mojom::NotificationScenario::INCOMING_CALL) { + // If the origin is not installed, the notification scenario should be set + // to DEFAULT. + if (IsActivelyInstalledWebAppScope(web_app_hint_url)) { + notification.set_scenario( + message_center::NotificationScenario::INCOMING_CALL); + } else { + notification.set_scenario(message_center::NotificationScenario::DEFAULT); + } + + // Create the default incoming call dismiss button and set the button types + // accordingly to fit the incoming call scenario - i.e., developer supplied + // action buttond are of type ButtonType::ACKNOWLEDGE and the default dimiss + // button is of type ButtonType::DISMISS + message_center::ButtonInfo default_dismiss_button( + l10n_util::GetStringUTF16(IDS_APP_CLOSE)); + default_dismiss_button.type = message_center::ButtonType::DISMISS; + for (auto& button : buttons) { + button.type = message_center::ButtonType::ACKNOWLEDGE; + } + // Insert the default dismiss button at the end of the vector and reset the + // notification buttons. + buttons.push_back(default_dismiss_button); + notification.set_buttons(buttons); + } + return notification; } @@ -573,3 +605,24 @@ return absl::nullopt; } + +bool PlatformNotificationServiceImpl::IsActivelyInstalledWebAppScope( + const GURL& web_app_url) const { +#if BUILDFLAG(IS_ANDROID) + // TODO(peter): Investigate whether it makes sense to consider installed + // WebAPKs and TWAs on Android here, when depending features are considered. + return false; +#else + web_app::WebAppProvider* web_app_provider = + web_app::WebAppProvider::GetForLocalAppsUnchecked(profile_); + if (!web_app_provider) { + return false; + } + + const absl::optional<web_app::AppId> app_id = + web_app_provider->registrar_unsafe().FindAppWithUrlInScope(web_app_url); + return app_id.has_value() && + web_app_provider->registrar_unsafe().IsActivelyInstalled( + app_id.value()); +#endif +}
diff --git a/chrome/browser/notifications/platform_notification_service_impl.h b/chrome/browser/notifications/platform_notification_service_impl.h index dfbfbf4..380a2da 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.h +++ b/chrome/browser/notifications/platform_notification_service_impl.h
@@ -95,6 +95,7 @@ DisplayNameForContextMessage); FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest, RecordNotificationUkmEvent); + FRIEND_TEST_ALL_PREFIXES(PlatformNotificationServiceTest, IncomingCallWebApp); FRIEND_TEST_ALL_PREFIXES( PlatformNotificationServiceTest_WebAppNotificationIconAndTitle, FindWebAppIconAndTitle_NoApp); @@ -141,6 +142,10 @@ absl::optional<WebAppIconAndTitle> FindWebAppIconAndTitle( const GURL& web_app_hint_url) const; + // Identifies whether the notification was sent from an installed web app or + // not. + bool IsActivelyInstalledWebAppScope(const GURL& web_app_url) const; + // Clears |closed_notifications_|. Should only be used for testing purposes. void ClearClosedNotificationsForTesting() { closed_notifications_.clear(); }
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index a00d2b1..04ada4d 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -20,6 +20,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/notifications/notification_common.h" #include "chrome/browser/notifications/notification_display_service_impl.h" #include "chrome/browser/notifications/notification_display_service_tester.h" @@ -34,6 +35,8 @@ #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/web_app.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -50,8 +53,11 @@ #include "net/base/filename_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/message_center/public/cpp/notification.h" +#include "ui/strings/grit/ui_strings.h" #if BUILDFLAG(ENABLE_BACKGROUND_MODE) #include "components/keep_alive_registry/keep_alive_registry.h" @@ -396,6 +402,8 @@ EXPECT_FALSE(default_notification.silent()); EXPECT_FALSE(default_notification.never_timeout()); EXPECT_EQ(0u, default_notification.buttons().size()); + EXPECT_EQ(message_center::NotificationScenario::DEFAULT, + default_notification.scenario()); // Verifies that the notification's default timestamp is set in the last 30 // seconds. This number has no significance, but it needs to be significantly @@ -441,6 +449,8 @@ EXPECT_FALSE(all_options_notification.buttons()[0].icon.IsEmpty()); EXPECT_EQ(kIconWidth, all_options_notification.buttons()[0].icon.Width()); EXPECT_EQ(kIconHeight, all_options_notification.buttons()[0].icon.Height()); + EXPECT_EQ(message_center::ButtonType::DEFAULT, + all_options_notification.buttons()[0].type); } // Chrome OS shows the notification settings inline. @@ -1144,3 +1154,178 @@ // notification should be shown without an image. EXPECT_TRUE(notifications[0].image().IsEmpty()); } + +class PlatformNotificationServiceIncomingCallTest + : public PlatformNotificationServiceBrowserTest { + public: + // InProcessBrowserTest overrides. + void SetUpInProcessBrowserTestFixture() override { + scoped_feature_list_.InitWithFeatures( + {blink::features::kIncomingCallNotifications, + features::kIncomingCallNotifications}, + {}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceIncomingCallTest, + DisplayIncomingCallNotificationWithActionButtons) { + GrantNotificationPermissionForTest(); + + std::string script_result; + ASSERT_TRUE(RunScript("DisplayIncomingCallNotificationWithActionButton()", + &script_result)); + EXPECT_EQ("ok", script_result); + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(1u, notifications.size()); + + // When sent from an origin that does not have an installed web app, the + // scenario should be set to DEFAULT and the default dismiss button should be + // present. + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ("Title", base::UTF16ToUTF8(notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(notification.message())); + EXPECT_EQ(message_center::NotificationScenario::DEFAULT, + notification.scenario()); + ASSERT_EQ(2u, notification.buttons().size()); + EXPECT_EQ("actionTitle1", base::UTF16ToUTF8(notification.buttons()[0].title)); + EXPECT_EQ(message_center::ButtonType::ACKNOWLEDGE, + notification.buttons()[0].type); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + notification.buttons()[1].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + notification.buttons()[1].type); + + // Install the web app. + const GURL web_app_url = TestPageUrl(); + const web_app::AppId app_id = web_app::test::InstallDummyWebApp( + browser()->profile(), "Web App Title", web_app_url); + + ASSERT_TRUE(RunScript("DisplayIncomingCallNotificationWithActionButton()", + &script_result)); + EXPECT_EQ("ok", script_result); + + notifications = GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(2u, notifications.size()); + + // After installing the origin's web app, the scenario is set to + // INCOMING_CALL. + const message_center::Notification& app_notification = notifications[1]; + EXPECT_EQ("Title", base::UTF16ToUTF8(app_notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(app_notification.message())); + EXPECT_EQ(message_center::NotificationScenario::INCOMING_CALL, + app_notification.scenario()); + ASSERT_EQ(2u, app_notification.buttons().size()); + EXPECT_EQ("actionTitle1", + base::UTF16ToUTF8(app_notification.buttons()[0].title)); + EXPECT_EQ(message_center::ButtonType::ACKNOWLEDGE, + app_notification.buttons()[0].type); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + app_notification.buttons()[1].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + app_notification.buttons()[1].type); + + web_app::test::UninstallWebApp(browser()->profile(), app_id); + + ASSERT_TRUE(RunScript("DisplayIncomingCallNotificationWithActionButton()", + &script_result)); + EXPECT_EQ("ok", script_result); + + notifications = GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(3u, notifications.size()); + + // After uninstalling the origin's web app, the scenario should be set + // back to DEFAULT. + const message_center::Notification& uninstall_notification = notifications[2]; + EXPECT_EQ("Title", base::UTF16ToUTF8(uninstall_notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(uninstall_notification.message())); + EXPECT_EQ(message_center::NotificationScenario::DEFAULT, + uninstall_notification.scenario()); + ASSERT_EQ(2u, uninstall_notification.buttons().size()); + EXPECT_EQ("actionTitle1", + base::UTF16ToUTF8(uninstall_notification.buttons()[0].title)); + EXPECT_EQ(message_center::ButtonType::ACKNOWLEDGE, + uninstall_notification.buttons()[0].type); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + uninstall_notification.buttons()[1].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + uninstall_notification.buttons()[1].type); +} + +IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceIncomingCallTest, + DisplayIncomingCallNotificationWithoutActionButtons) { + GrantNotificationPermissionForTest(); + + std::string script_result; + ASSERT_TRUE(RunScript("DisplayIncomingCallNotification()", &script_result)); + EXPECT_EQ("ok", script_result); + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(1u, notifications.size()); + + // When sent from an origin that does not have an installed web app, the + // scenario should be set to DEFAULT and the default dismiss button should be + // present, even though no action button was supplied by the origin. + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ("Title", base::UTF16ToUTF8(notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(notification.message())); + EXPECT_EQ(message_center::NotificationScenario::DEFAULT, + notification.scenario()); + ASSERT_EQ(1u, notification.buttons().size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + notification.buttons()[0].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + notification.buttons()[0].type); + + // Install the web app. + const GURL web_app_url = TestPageUrl(); + const web_app::AppId app_id = web_app::test::InstallDummyWebApp( + browser()->profile(), "Web App Title", web_app_url); + + ASSERT_TRUE(RunScript("DisplayIncomingCallNotification()", &script_result)); + EXPECT_EQ("ok", script_result); + + notifications = GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(2u, notifications.size()); + + // After installing the origin's web app, the scenario is set to + // INCOMING_CALL and the default dismiss button should be + // present, even though no action button was supplied by the origin. + const message_center::Notification& app_notification = notifications[1]; + EXPECT_EQ("Title", base::UTF16ToUTF8(app_notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(app_notification.message())); + EXPECT_EQ(message_center::NotificationScenario::INCOMING_CALL, + app_notification.scenario()); + ASSERT_EQ(1u, app_notification.buttons().size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + app_notification.buttons()[0].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + app_notification.buttons()[0].type); + + web_app::test::UninstallWebApp(browser()->profile(), app_id); + + ASSERT_TRUE(RunScript("DisplayIncomingCallNotification()", &script_result)); + EXPECT_EQ("ok", script_result); + + notifications = GetDisplayedNotifications(true /* is_persistent */); + ASSERT_EQ(3u, notifications.size()); + + // After uninstalling the origin's web app, the scenario should be set + // back to DEFAULT and the default dismiss button should be + // present, even though no action button was supplied by the origin. + const message_center::Notification& uninstall_notification = notifications[2]; + EXPECT_EQ("Title", base::UTF16ToUTF8(uninstall_notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(uninstall_notification.message())); + EXPECT_EQ(message_center::NotificationScenario::DEFAULT, + uninstall_notification.scenario()); + ASSERT_EQ(1u, uninstall_notification.buttons().size()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_CLOSE), + uninstall_notification.buttons()[0].title); + EXPECT_EQ(message_center::ButtonType::DISMISS, + uninstall_notification.buttons()[0].type); +}
diff --git a/chrome/browser/notifications/platform_notification_service_unittest.cc b/chrome/browser/notifications/platform_notification_service_unittest.cc index b68b7d1b..ce9ce01 100644 --- a/chrome/browser/notifications/platform_notification_service_unittest.cc +++ b/chrome/browser/notifications/platform_notification_service_unittest.cc
@@ -17,6 +17,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/notifications/metrics/mock_notification_metrics_logger.h" #include "chrome/browser/notifications/metrics/notification_metrics_logger_factory.h" @@ -24,6 +25,7 @@ #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/notifications/platform_notification_service_factory.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_service.h" @@ -350,6 +352,44 @@ EXPECT_LT(first_id, second_id); } +#if !BUILDFLAG(IS_ANDROID) + +TEST_F(PlatformNotificationServiceTest, IncomingCallWebApp) { + // If there is no WebAppProvider, IsActivelyInstalledWebAppScope should return + // false. + const GURL web_app_url{"https://example.org/"}; + EXPECT_FALSE(service()->IsActivelyInstalledWebAppScope(web_app_url)); + + // If there is no web app installed for the provided url, + // IsActivelyInstalledWebAppScope should return false. + web_app::FakeWebAppProvider* provider = + web_app::FakeWebAppProvider::Get(profile_.get()); + provider->Start(); + EXPECT_FALSE(service()->IsActivelyInstalledWebAppScope(web_app_url)); + + // IsActivelyInstalledWebAppScope should return true only if there is an + // installed web app for the provided URL. + std::unique_ptr<web_app::WebApp> web_app = web_app::test::CreateWebApp(); + const GURL installed_web_app_url = web_app->start_url(); + const web_app::AppId app_id = web_app->app_id(); + web_app->SetName("Web App Title"); + + provider->GetRegistrarMutable().registry().emplace(app_id, + std::move(web_app)); + + EXPECT_TRUE(service()->IsActivelyInstalledWebAppScope(installed_web_app_url)); + + // If the app is not installed anymore, IsActivelyInstalledWebAppScope should + // return false. + raw_ptr<web_app::WebApp> installed_web_app = + provider->GetRegistrarMutable().GetAppByIdMutable(app_id); + installed_web_app->SetIsUninstalling(true); + EXPECT_FALSE( + service()->IsActivelyInstalledWebAppScope(installed_web_app_url)); +} + +#endif // !BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(ENABLE_EXTENSIONS) TEST_F(PlatformNotificationServiceTest, DisplayNameForContextMessage) {
diff --git a/chrome/browser/notifications/win/notification_template_builder.cc b/chrome/browser/notifications/win/notification_template_builder.cc index bcd7be46..1cb0ce7 100644 --- a/chrome/browser/notifications/win/notification_template_builder.cc +++ b/chrome/browser/notifications/win/notification_template_builder.cc
@@ -50,14 +50,17 @@ const char kBindingElementTemplateAttribute[] = "template"; const char kContent[] = "content"; const char kContextMenu[] = "contextMenu"; +const char kCritical[] = "Critical"; const char kDuration[] = "duration"; const char kDurationLong[] = "long"; const char kForeground[] = "foreground"; const char kHero[] = "hero"; +const char kHintButtonStyle[] = "hint-buttonStyle"; const char kHintCrop[] = "hint-crop"; const char kHintCropNone[] = "none"; const char kImageElement[] = "image"; const char kImageUri[] = "imageUri"; +const char kIncomingCall[] = "incomingCall"; const char kIndeterminate[] = "indeterminate"; const char kInputElement[] = "input"; const char kInputId[] = "id"; @@ -71,10 +74,12 @@ const char kScenario[] = "scenario"; const char kSilent[] = "silent"; const char kSrc[] = "src"; +const char kSuccess[] = "Success"; const char kText[] = "text"; const char kTextElement[] = "text"; const char kToastElementDisplayTimestamp[] = "displayTimestamp"; const char kTrue[] = "true"; +const char kUseButtonStyle[] = "useButtonStyle"; const char kUserResponse[] = "userResponse"; const char kValue[] = "value"; const char kVisualElement[] = "visual"; @@ -103,7 +108,13 @@ xml_writer->StartElement(kNotificationToastElement); xml_writer->AddAttribute(kNotificationLaunchAttribute, launch_id.Serialize()); - if (notification.never_timeout()) { + // Only notifications created by an installed web app should be allowed to + // have increased priority, colored buttons, and a ringtone. + if (notification.scenario() == + message_center::NotificationScenario::INCOMING_CALL) { + xml_writer->AddAttribute(kScenario, kIncomingCall); + xml_writer->AddAttribute(kUseButtonStyle, kTrue); + } else if (notification.never_timeout()) { if (base::FeatureList::IsEnabled( features::kNotificationDurationLongForRequireInteraction)) { xml_writer->AddAttribute(kDuration, kDurationLong); @@ -256,9 +267,25 @@ int index, NotificationLaunchId copied_launch_id) { xml_writer->StartElement(kActionElement); - xml_writer->AddAttribute(kActivationType, kForeground); + + // All notifications buttons in the incoming-call scenario should be green, + // except for the default dismiss button added by Chromium (not by the Action + // Center), which should be red. This attribute will take effect only if the + // 'useButtonStyle' attribute has been added to the toast XML element - i.e., + // when the notification scenario is INCOMING_CALL. + if (button.type == message_center::ButtonType::DISMISS) { + xml_writer->AddAttribute(kActivationType, kBackground); + copied_launch_id.set_is_for_dismiss_button(); + xml_writer->AddAttribute(kHintButtonStyle, kCritical); + } else { + xml_writer->AddAttribute(kActivationType, kForeground); + copied_launch_id.set_button_index(index); + if (button.type == message_center::ButtonType::ACKNOWLEDGE) { + xml_writer->AddAttribute(kHintButtonStyle, kSuccess); + } + } + xml_writer->AddAttribute(kContent, base::UTF16ToUTF8(button.title)); - copied_launch_id.set_button_index(index); xml_writer->AddAttribute(kArguments, copied_launch_id.Serialize()); if (!button.icon.IsEmpty()) { @@ -296,8 +323,9 @@ xml_writer->EndElement(); } - for (size_t i = 0; i < buttons.size(); ++i) + for (size_t i = 0; i < buttons.size(); ++i) { WriteActionElement(xml_writer, image_retainer, buttons[i], i, launch_id); + } } // Writes the <audio silent="true"> element.
diff --git a/chrome/browser/notifications/win/notification_template_builder_unittest.cc b/chrome/browser/notifications/win/notification_template_builder_unittest.cc index 2e587c79..edbcf0e6 100644 --- a/chrome/browser/notifications/win/notification_template_builder_unittest.cc +++ b/chrome/browser/notifications/win/notification_template_builder_unittest.cc
@@ -563,3 +563,72 @@ ASSERT_NO_FATAL_FAILURE(VerifyXml(notification, kExpectedXml)); } + +TEST_F(NotificationTemplateBuilderTest, IncomingCallFromWebApp) { + message_center::Notification notification = BuildNotification(); + notification.set_scenario( + message_center::NotificationScenario::INCOMING_CALL); + + std::vector<message_center::ButtonInfo> buttons; + message_center::ButtonInfo acknowledge_button(u"Acknowledge"); + acknowledge_button.type = message_center::ButtonType::ACKNOWLEDGE; + buttons.push_back(acknowledge_button); + message_center::ButtonInfo dismiss_button(u"Close"); + dismiss_button.type = message_center::ButtonType::DISMISS; + buttons.push_back(dismiss_button); + notification.set_buttons(buttons); + + const wchar_t kExpectedXml[] = + LR"(<toast launch="0|0|Default|0|https://example.com/|notification_id" scenario="incomingCall" useButtonStyle="true" displayTimestamp="1998-09-04T01:02:03Z"> + <visual> + <binding template="ToastGeneric"> + <text>My Title</text> + <text>My Message</text> + <text placement="attribution">example.com</text> + </binding> + </visual> + <actions> + <action activationType="foreground" hint-buttonStyle="Success" content="Acknowledge" arguments="1|0|0|Default|0|https://example.com/|notification_id"/> + <action activationType="background" hint-buttonStyle="Critical" content="Close" arguments="3|0|Default|0|https://example.com/|notification_id"/> + <action content="settings" placement="contextMenu" activationType="foreground" arguments="2|0|Default|0|https://example.com/|notification_id"/> + </actions> +</toast> +)"; + + ASSERT_NO_FATAL_FAILURE(VerifyXml(notification, kExpectedXml)); +} + +TEST_F(NotificationTemplateBuilderTest, IncomingCallFromNonInstalledOrigin) { + message_center::Notification notification = BuildNotification(); + + std::vector<message_center::ButtonInfo> buttons; + message_center::ButtonInfo acknowledge_button(u"Acknowledge"); + acknowledge_button.type = message_center::ButtonType::ACKNOWLEDGE; + buttons.push_back(acknowledge_button); + message_center::ButtonInfo dismiss_button(u"Close"); + dismiss_button.type = message_center::ButtonType::DISMISS; + buttons.push_back(dismiss_button); + notification.set_buttons(buttons); + + // In this case, the toast wont' have the "scenario" and "useButtonStyle" + // arguments being set. Thus, even if the action buttons have the + // "hint-buttonStyle" argument set, it should not take effect. + const wchar_t kExpectedXml[] = + LR"(<toast launch="0|0|Default|0|https://example.com/|notification_id" displayTimestamp="1998-09-04T01:02:03Z"> + <visual> + <binding template="ToastGeneric"> + <text>My Title</text> + <text>My Message</text> + <text placement="attribution">example.com</text> + </binding> + </visual> + <actions> + <action activationType="foreground" hint-buttonStyle="Success" content="Acknowledge" arguments="1|0|0|Default|0|https://example.com/|notification_id"/> + <action activationType="background" hint-buttonStyle="Critical" content="Close" arguments="3|0|Default|0|https://example.com/|notification_id"/> + <action content="settings" placement="contextMenu" activationType="foreground" arguments="2|0|Default|0|https://example.com/|notification_id"/> + </actions> +</toast> +)"; + + ASSERT_NO_FATAL_FAILURE(VerifyXml(notification, kExpectedXml)); +}
diff --git a/chrome/browser/obsolete_system/OWNERS b/chrome/browser/obsolete_system/OWNERS index 205b083..6f66759 100644 --- a/chrome/browser/obsolete_system/OWNERS +++ b/chrome/browser/obsolete_system/OWNERS
@@ -1,7 +1,11 @@ # Use any owner for non-platform-specific issues. + # Mac mark@chromium.org +avi@chromium.org + # Windows brucedawson@chromium.org + # Linux thestig@chromium.org
diff --git a/chrome/browser/obsolete_system/obsolete_system.h b/chrome/browser/obsolete_system/obsolete_system.h index 570a351a..23ab1997 100644 --- a/chrome/browser/obsolete_system/obsolete_system.h +++ b/chrome/browser/obsolete_system/obsolete_system.h
@@ -7,39 +7,36 @@ #include <string> -class ObsoleteSystem { - public: - ObsoleteSystem() = delete; - ObsoleteSystem(const ObsoleteSystem&) = delete; - ObsoleteSystem& operator=(const ObsoleteSystem&) = delete; +namespace ObsoleteSystem { - // Returns true if the system is already considered obsolete, or if it'll be - // considered obsolete soon. Used to control whether to show messaging about - // deprecation within the app. - static bool IsObsoleteNowOrSoon(); +// Returns true if the system is already considered obsolete, or if it'll be +// considered obsolete soon. Used to control whether to show messaging about +// deprecation within the app. +bool IsObsoleteNowOrSoon(); - // Returns a localized string informing users that their system will either - // soon be unsupported by future versions of the application, or that they - // are already using the last version of the application that supports their - // system. Do not use the returned string unless IsObsoleteNowOrSoon() returns - // true. - static std::u16string LocalizedObsoleteString(); +// Returns a localized string informing users that their system will either soon +// be unsupported by future versions of the application, or that they are +// already using the last version of the application that supports their system. +// Do not use the returned string unless IsObsoleteNowOrSoon() returns true. +std::u16string LocalizedObsoleteString(); - // Returns true if this is the final release milestone. This is only valid - // when IsObsoleteNowOrSoon() returns true. - // If true, about:help will stop showing "Checking for updates... Chrome is up - // to date", and users can no longer manually check for updates by refreshing - // about:help. This is typically done when the last milestone supporting an - // obsolete OS version is reached, to make it clear that Chrome will no longer - // check for major updates. Note that even if the implementation returns true - // when the last supported milestone has been reached, users will continue to - // get any released minor updates for that milestone despite the lack of a - // "Checking for updates..." message on about:help. - static bool IsEndOfTheLine(); +// Returns true if this is the final release milestone. This is only valid +// when IsObsoleteNowOrSoon() returns true. +// +// If true, about:help will stop showing "Checking for updates... Chrome is up +// to date", and users can no longer manually check for updates by refreshing +// about:help. This is typically done when the last milestone supporting an +// obsolete OS version is reached, to make it clear that Chrome will no longer +// check for major updates. Note that even if the implementation returns true +// when the last supported milestone has been reached, users will continue to +// get any released minor updates for that milestone despite the lack of a +// "Checking for updates..." message on about:help. +bool IsEndOfTheLine(); - // A help URL to explain the deprecation. Do not use the returned string - // unless IsObsoleteNowOrSoon() returns true. - static const char* GetLinkURL(); -}; +// A help URL to explain the deprecation. Do not use the returned string +// unless IsObsoleteNowOrSoon() returns true. +const char* GetLinkURL(); + +} // namespace ObsoleteSystem #endif // CHROME_BROWSER_OBSOLETE_SYSTEM_OBSOLETE_SYSTEM_H_
diff --git a/chrome/browser/obsolete_system/obsolete_system_linux.cc b/chrome/browser/obsolete_system/obsolete_system_linux.cc index 902f910..5953872e 100644 --- a/chrome/browser/obsolete_system/obsolete_system_linux.cc +++ b/chrome/browser/obsolete_system/obsolete_system_linux.cc
@@ -19,27 +19,28 @@ "Fedora 30", "Fedora 31", "openSUSE Leap 15.0", "openSUSE Leap 15.1", }; -// static -bool ObsoleteSystem::IsObsoleteNowOrSoon() { +namespace ObsoleteSystem { + +bool IsObsoleteNowOrSoon() { auto distro = base::GetLinuxDistro(); for (const char* obsolete : kObsoleteDistros) { - if (base::StartsWith(distro, obsolete)) + if (base::StartsWith(distro, obsolete)) { return true; + } } return false; } -// static -std::u16string ObsoleteSystem::LocalizedObsoleteString() { +std::u16string LocalizedObsoleteString() { return l10n_util::GetStringUTF16(IDS_LINUX_OBSOLETE); } -// static -bool ObsoleteSystem::IsEndOfTheLine() { +bool IsEndOfTheLine() { return false; } -// static -const char* ObsoleteSystem::GetLinkURL() { +const char* GetLinkURL() { return kLinuxObsoleteUrl; } + +} // namespace ObsoleteSystem
diff --git a/chrome/browser/obsolete_system/obsolete_system_mac.cc b/chrome/browser/obsolete_system/obsolete_system_mac.cc index 6b8b57e4..e9e09d5f5 100644 --- a/chrome/browser/obsolete_system/obsolete_system_mac.cc +++ b/chrome/browser/obsolete_system/obsolete_system_mac.cc
@@ -37,13 +37,13 @@ } // namespace -// static -bool ObsoleteSystem::IsObsoleteNowOrSoon() { +namespace ObsoleteSystem { + +bool IsObsoleteNowOrSoon() { return OsObsoleteness() != Obsoleteness::NotObsolete; } -// static -std::u16string ObsoleteSystem::LocalizedObsoleteString() { +std::u16string LocalizedObsoleteString() { switch (OsObsoleteness()) { case Obsoleteness::MacOS1011Obsolete: return l10n_util::GetStringUTF16(IDS_MAC_10_11_OBSOLETE); @@ -54,12 +54,12 @@ } } -// static -bool ObsoleteSystem::IsEndOfTheLine() { +bool IsEndOfTheLine() { return CHROME_VERSION_MAJOR >= 103; } -// static -const char* ObsoleteSystem::GetLinkURL() { +const char* GetLinkURL() { return chrome::kMacOsObsoleteURL; } + +} // namespace ObsoleteSystem
diff --git a/chrome/browser/obsolete_system/obsolete_system_stub.cc b/chrome/browser/obsolete_system/obsolete_system_stub.cc index 9e482f1..142a353 100644 --- a/chrome/browser/obsolete_system/obsolete_system_stub.cc +++ b/chrome/browser/obsolete_system/obsolete_system_stub.cc
@@ -4,29 +4,22 @@ #include "chrome/browser/obsolete_system/obsolete_system.h" -#include "base/cpu.h" -#include "build/build_config.h" -#include "chrome/common/chrome_version.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/chromium_strings.h" -#include "ui/base/l10n/l10n_util.h" +namespace ObsoleteSystem { -// static -bool ObsoleteSystem::IsObsoleteNowOrSoon() { +bool IsObsoleteNowOrSoon() { return false; } -// static -std::u16string ObsoleteSystem::LocalizedObsoleteString() { +std::u16string LocalizedObsoleteString() { return std::u16string(); } -// static -bool ObsoleteSystem::IsEndOfTheLine() { +bool IsEndOfTheLine() { return true; } -// static -const char* ObsoleteSystem::GetLinkURL() { +const char* GetLinkURL() { return ""; } + +} // namespace ObsoleteSystem
diff --git a/chrome/browser/obsolete_system/obsolete_system_win.cc b/chrome/browser/obsolete_system/obsolete_system_win.cc index f1a79ac..541d764 100644 --- a/chrome/browser/obsolete_system/obsolete_system_win.cc +++ b/chrome/browser/obsolete_system/obsolete_system_win.cc
@@ -28,35 +28,39 @@ } // namespace -// static -bool ObsoleteSystem::IsObsoleteNowOrSoon() { +namespace ObsoleteSystem { + +bool IsObsoleteNowOrSoon() { return IsObsoleteOsVersion(); } -// static -std::u16string ObsoleteSystem::LocalizedObsoleteString() { +std::u16string LocalizedObsoleteString() { const auto version = GetRealOSVersion(); - if (version == base::win::Version::WIN7) + if (version == base::win::Version::WIN7) { return l10n_util::GetStringUTF16(IDS_WIN_7_OBSOLETE); - if (version == base::win::Version::WIN8) + } + if (version == base::win::Version::WIN8) { return l10n_util::GetStringUTF16(IDS_WIN_8_OBSOLETE); - if (version == base::win::Version::WIN8_1) + } + if (version == base::win::Version::WIN8_1) { return l10n_util::GetStringUTF16(IDS_WIN_8_1_OBSOLETE); + } return l10n_util::GetStringUTF16(IDS_WIN_XP_VISTA_OBSOLETE); } -// static -bool ObsoleteSystem::IsEndOfTheLine() { +bool IsEndOfTheLine() { // M109 was the last milestone to support Win 7/8/8.1, the last deprecated // Windows version. Future deprecations should update this to the last // milestone that supports the soon-to-be-deprecated Windows version. return CHROME_VERSION_MAJOR >= 109; } -// static -const char* ObsoleteSystem::GetLinkURL() { +const char* GetLinkURL() { const auto version = GetRealOSVersion(); - if (version < base::win::Version::WIN7) + if (version < base::win::Version::WIN7) { return chrome::kWindowsXPVistaDeprecationURL; + } return chrome::kWindows78DeprecationURL; } + +} // namespace ObsoleteSystem
diff --git a/chrome/browser/origin_trials/origin_trials_browsertest.cc b/chrome/browser/origin_trials/origin_trials_browsertest.cc index 07e3cd6a..22e1979 100644 --- a/chrome/browser/origin_trials/origin_trials_browsertest.cc +++ b/chrome/browser/origin_trials/origin_trials_browsertest.cc
@@ -36,6 +36,7 @@ "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA="; const char kTrialEnabledDomain[] = "example.com"; +const char kEmbeddingDomain[] = "embedding.com"; const char kFrobulatePersistentTrialName[] = "FrobulatePersistent"; // Generated with // tools/origin_trials/generate_token.py https://example.com \ @@ -51,6 +52,8 @@ const char kPageWithOriginTrialResourcePath[] = "/has-origin-trial-resource"; +const char kPageWithEmbeddedFramePath[] = "/has-embedded-frame"; + const char kOriginTrialResourceJavascriptPath[] = "/origin-trial-script.js"; class OriginTrialsBrowserTest : public PlatformBrowserTest { @@ -104,6 +107,10 @@ base::StrAppend(&body, {"<!DOCTYPE html><head><script src=\"", kOriginTrialResourceJavascriptPath, "\"></script>"}); + } else if (path == kPageWithEmbeddedFramePath) { + base::StrAppend(&body, {"<!DOCTYPE html><body><iframe src=\"https://", + kTrialEnabledDomain, kCriticalTrialEnabledPath, + "\"></iframe>"}); } content::URLLoaderInterceptor::WriteResponse(headers, body, @@ -123,12 +130,16 @@ PlatformBrowserTest::TearDownOnMainThread(); } - base::flat_set<std::string> GetOriginTrialsForEnabledOrigin() { + base::flat_set<std::string> GetOriginTrialsForEnabledOrigin( + const std::string& partition_site) { url::Origin origin = url::Origin::CreateFromNormalizedTuple( "https", kTrialEnabledDomain, 443); + url::Origin partition_domain = + url::Origin::CreateFromNormalizedTuple("https", partition_site, 443); content::OriginTrialsControllerDelegate* delegate = browser()->profile()->GetOriginTrialsControllerDelegate(); - return delegate->GetPersistedTrialsForOrigin(origin, base::Time::Now()); + return delegate->GetPersistedTrialsForOrigin(origin, partition_domain, + base::Time::Now()); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -154,6 +165,13 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); } + // Navigate to a third-party page that embeds an origin trial-enabling page + void RequestForEmbeddedOriginTrial() { + GURL url(base::StrCat( + {"https://", kEmbeddingDomain, kPageWithEmbeddedFramePath})); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + } + protected: base::test::ScopedFeatureList test_features_; std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_; @@ -162,27 +180,42 @@ IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, NoHeaderDoesNotEnableResponse) { RequestWithoutHeaders(); - base::flat_set<std::string> trials = GetOriginTrialsForEnabledOrigin(); + base::flat_set<std::string> trials = + GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain); EXPECT_TRUE(trials.empty()); } IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, ResponseEnablesOriginTrial) { RequestForOriginTrial(kTrialEnabledPath); - base::flat_set<std::string> trials = GetOriginTrialsForEnabledOrigin(); + base::flat_set<std::string> trials = + GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain); ASSERT_FALSE(trials.empty()); EXPECT_EQ(kFrobulatePersistentTrialName, *(trials.begin())); } IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, + EmbeddedResponseEnablesPartitionedTrial) { + RequestForEmbeddedOriginTrial(); + + base::flat_set<std::string> trials = + GetOriginTrialsForEnabledOrigin(kEmbeddingDomain); + ASSERT_FALSE(trials.empty()); + EXPECT_EQ(kFrobulatePersistentTrialName, *(trials.begin())); + + ASSERT_TRUE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); +} + +IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, TrialEnabledAfterNavigationToOtherDomain) { // Navigate to a page that enables a persistent origin trial RequestForOriginTrial(kTrialEnabledPath); - EXPECT_FALSE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_FALSE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // Navigate to a different domain RequestToHttpDomain(); // The trial should still be enabled - base::flat_set<std::string> trials = GetOriginTrialsForEnabledOrigin(); + base::flat_set<std::string> trials = + GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain); ASSERT_FALSE(trials.empty()); EXPECT_EQ(kFrobulatePersistentTrialName, *(trials.begin())); } @@ -191,18 +224,18 @@ TrialDisabledAfterNavigationToSameDomain) { // Navigate to a page that enables a persistent origin trial RequestForOriginTrial(kTrialEnabledPath); - EXPECT_FALSE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_FALSE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // Navigate to same domain without the Origin-Trial header set RequestWithoutHeaders(); // The trial should no longer be enabled - EXPECT_TRUE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_TRUE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); } IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, CriticalOriginTrialRestartsRequest) { RequestForOriginTrial(kCriticalTrialEnabledPath); - EXPECT_FALSE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_FALSE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // The trial was critical, so expect two requests due to restart. EXPECT_EQ(2, received_request_counts_[kCriticalTrialEnabledPath]); @@ -213,7 +246,7 @@ // Load the original page again received_request_counts_[kCriticalTrialEnabledPath] = 0; RequestForOriginTrial(kCriticalTrialEnabledPath); - EXPECT_FALSE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_FALSE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // The trial should already be persisted, so no restart should have happened EXPECT_EQ(1, received_request_counts_[kCriticalTrialEnabledPath]); @@ -222,7 +255,7 @@ IN_PROC_BROWSER_TEST_F(OriginTrialsBrowserTest, NonCriticalTrialDoesNotRestart) { RequestForOriginTrial(kTrialEnabledPath); - EXPECT_FALSE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_FALSE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // The trial was not critical, so expect one request. EXPECT_EQ(1, received_request_counts_[kTrialEnabledPath]); @@ -233,7 +266,7 @@ RequestForOriginTrial(kPageWithOriginTrialResourcePath); // We do not expect the trial to be set, since // |kPageWithOriginTrialResourcePath| doesn't set the header on navigation. - EXPECT_TRUE(GetOriginTrialsForEnabledOrigin().empty()); + EXPECT_TRUE(GetOriginTrialsForEnabledOrigin(kTrialEnabledDomain).empty()); // The main page did not have any origin trial headers, so we only expect one // request.
diff --git a/chrome/browser/page_load_metrics/integration_tests/data/lcp_type.html b/chrome/browser/page_load_metrics/integration_tests/data/lcp_type.html index b3a5475..c5eb93c 100644 --- a/chrome/browser/page_load_metrics/integration_tests/data/lcp_type.html +++ b/chrome/browser/page_load_metrics/integration_tests/data/lcp_type.html
@@ -14,16 +14,4 @@ document.body.appendChild(paragraph); } - const wait_for_lcp_entry_emission = async (expected_count) => { - let expected_entries = []; - await new Promise(resolve => { - new PerformanceObserver((list, observer) => { - expected_entries = expected_entries.concat(list.getEntries()); - if (expected_entries.length >= expected_count) { - observer.disconnect(); - resolve(); - } - }).observe({ type: "largest-contentful-paint", buffered: true }); - }); - }; </script>
diff --git a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc index b295292e..d186dd60 100644 --- a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc +++ b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
@@ -533,21 +533,112 @@ } class LargestContentfulPaintTypeTest : public MetricIntegrationTest { + public: + void SetUpOnMainThread() override { + MetricIntegrationTest::SetUpOnMainThread(); + waiter_ = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( + web_contents()); + } + + protected: + enum class ElementOrder { kImageFirst, kTextFirst }; + + void Wait() { waiter_->Wait(); } + + void TestImage(std::string& imgSrc, + blink::LargestContentfulPaintType flagSet) { + AddMinimumLargestContentfulPaintImageExpectation(1); + + Navigate("/lcp_type.html"); + + AddImage(imgSrc); + + Wait(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); + + ExpectUKMPageLoadMetricFlagSetExactMatch( + PageLoad::kPaintTiming_LargestContentfulPaintTypeName, + LargestContentfulPaintTypeToUKMFlags(flagSet)); + } + + void TestText(std::string& text, blink::LargestContentfulPaintType flagSet) { + AddMinimumLargestContentfulPaintTextExpectation(1); + + Navigate("/lcp_type.html"); + + AddText(text); + + Wait(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); + + ExpectUKMPageLoadMetricFlagSetExactMatch( + PageLoad::kPaintTiming_LargestContentfulPaintTypeName, + LargestContentfulPaintTypeToUKMFlags(flagSet)); + } + + void TestTextAndImage(ElementOrder elementOrder, + std::string& text, + std::string& imgSrc, + blink::LargestContentfulPaintType flagSet) { + Navigate("/lcp_type.html"); + + if (elementOrder == ElementOrder::kTextFirst) { + AddMinimumLargestContentfulPaintTextExpectation(1); + + AddText(text); + + Wait(); + + AddMinimumLargestContentfulPaintImageExpectation(1); + + AddImage(imgSrc); + } else { + AddMinimumLargestContentfulPaintImageExpectation(1); + + AddImage(imgSrc); + + Wait(); + + AddMinimumLargestContentfulPaintTextExpectation(1); + + AddText(text); + } + + Wait(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); + + ExpectUKMPageLoadMetricFlagSetExactMatch( + PageLoad::kPaintTiming_LargestContentfulPaintTypeName, + LargestContentfulPaintTypeToUKMFlags(flagSet)); + } + + void TestVideoDataURI(blink::LargestContentfulPaintType flagSet) { + AddMinimumLargestContentfulPaintImageExpectation(1); + Navigate("/lcp_type_video_data_uri.html"); + + Wait(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); + + ExpectUKMPageLoadMetricFlagSetExactMatch( + PageLoad::kPaintTiming_LargestContentfulPaintTypeName, + LargestContentfulPaintTypeToUKMFlags(flagSet)); + } + private: - std::unique_ptr<page_load_metrics::PageLoadMetricsTestWaiter> - AddWaiterAndExpectation(uint32_t expectedResourceCount = 1) { - auto waiter = - std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( - web_contents()); + std::unique_ptr<page_load_metrics::PageLoadMetricsTestWaiter> waiter_; - waiter->AddPageExpectation(page_load_metrics::PageLoadMetricsTestWaiter:: - TimingField::kLargestContentfulPaint); + void AddMinimumLargestContentfulPaintTextExpectation( + uint32_t expected_count) { + waiter_->AddMinimumLargestContentfulPaintTextExpectation(expected_count); + } - // Passing expectedResourceCount + 1 as in addition to the elements on the - // page, the html page itself is a completed resource. - waiter->AddMinimumCompleteResourcesExpectation(expectedResourceCount + 1); - - return waiter; + void AddMinimumLargestContentfulPaintImageExpectation( + uint32_t expected_count) { + waiter_->AddMinimumLargestContentfulPaintImageExpectation(expected_count); } void Navigate(std::string url) { @@ -568,125 +659,6 @@ .error, ""); } - - void WaitForLcpEmission(int32_t expectedLCPEntryCount = 1) { - EXPECT_EQ(EvalJs(web_contents()->GetPrimaryMainFrame(), - content::JsReplace("wait_for_lcp_entry_emission($1)", - expectedLCPEntryCount)) - .error, - ""); - } - - void WaitForUKMReporting() { - std::string script = R"( - ( - async () => { - await new Promise(resolve => { - setTimeout(resolve, 200); - }) - } - )(); - )"; - - EXPECT_EQ(EvalJs(web_contents()->GetPrimaryMainFrame(), script).error, ""); - } - - // navigate away from the test html page so that metrics are flushed. - void NavigateAway( - std::unique_ptr<page_load_metrics::PageLoadMetricsTestWaiter> waiter) { - // Wait for LCP element to be updated. - WaitForUKMReporting(); - - ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); - - waiter->Wait(); - - // Wait for UKM metrics to be flushed. - WaitForUKMReporting(); - } - - public: - enum class ElementOrder { kImageFirst, kTextFirst }; - void TestImage(std::string& imgSrc, - blink::LargestContentfulPaintType flagSet) { - auto waiter = AddWaiterAndExpectation(); - - Navigate("/lcp_type.html"); - - AddImage(imgSrc); - - WaitForLcpEmission(); - - NavigateAway(std::move(waiter)); - - ExpectUKMPageLoadMetricFlagSetExactMatch( - PageLoad::kPaintTiming_LargestContentfulPaintTypeName, - LargestContentfulPaintTypeToUKMFlags(flagSet)); - } - - void TestText(std::string& text, blink::LargestContentfulPaintType flagSet) { - auto waiter = AddWaiterAndExpectation(); - - Navigate("/lcp_type.html"); - - AddText(text); - - WaitForLcpEmission(); - - NavigateAway(std::move(waiter)); - - ExpectUKMPageLoadMetricFlagSetExactMatch( - PageLoad::kPaintTiming_LargestContentfulPaintTypeName, - LargestContentfulPaintTypeToUKMFlags(flagSet)); - } - - void TestTextAndImage(ElementOrder elementOrder, - std::string& text, - std::string& imgSrc, - uint32_t expectedLCPEntryCount, - blink::LargestContentfulPaintType flagSet) { - auto waiter = AddWaiterAndExpectation(2); - - Navigate("/lcp_type.html"); - - if (elementOrder == ElementOrder::kTextFirst) { - AddText(text); - // Wait for LCP emission for 1st element before adding the 2nd - // element.This is to prevent the case that a larger 2nd element replaces - // the 1st element as LCP element before an LCP entry is emitted for the - // 1st element. - if (expectedLCPEntryCount > 1) - WaitForLcpEmission(); - AddImage(imgSrc); - } else { - AddImage(imgSrc); - if (expectedLCPEntryCount > 1) - WaitForLcpEmission(); - AddText(text); - } - - WaitForLcpEmission(expectedLCPEntryCount); - - NavigateAway(std::move(waiter)); - - ExpectUKMPageLoadMetricFlagSetExactMatch( - PageLoad::kPaintTiming_LargestContentfulPaintTypeName, - LargestContentfulPaintTypeToUKMFlags(flagSet)); - } - - void TestVideoDataURI(blink::LargestContentfulPaintType flagSet) { - auto waiter = AddWaiterAndExpectation(); - - Navigate("/lcp_type_video_data_uri.html"); - - WaitForLcpEmission(); - - NavigateAway(std::move(waiter)); - - ExpectUKMPageLoadMetricFlagSetExactMatch( - PageLoad::kPaintTiming_LargestContentfulPaintTypeName, - LargestContentfulPaintTypeToUKMFlags(flagSet)); - } }; IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, ImageType_PNG) { @@ -733,28 +705,16 @@ TestImage(imgSrc, flag_set); } -// (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ. -#if BUILDFLAG(IS_MAC) -#define MAYBE_TextType DISABLED_TextType -#else -#define MAYBE_TextType TextType -#endif -IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, MAYBE_TextType) { +IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, TextType) { auto flag_set = blink::LargestContentfulPaintType::kText; std::string text = "This is to test LargestContentfulPaintType::kText"; TestText(text, flag_set); } -// (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ. -#if BUILDFLAG(IS_MAC) -#define MAYBE_LargeTextAndImage_TextType DISABLED_LargeTextAndImage_TextType -#else -#define MAYBE_LargeTextAndImage_TextType LargeTextAndImage_TextType -#endif // Case when text that is larger and comes before an image. The // LargestContentfulPaintType should be those of a text element. IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, - MAYBE_LargeTextAndImage_TextType) { + LargeTextAndImage_TextType) { auto flag_set = blink::LargestContentfulPaintType::kText; std::string text = "This is a text that is larger and comes before an image. The " @@ -762,19 +722,13 @@ std::string imgSrc = "images/green-2x2.png"; // The larger element comes first so 1 LCP entry is expected. - TestTextAndImage(ElementOrder::kTextFirst, text, imgSrc, 1, flag_set); + TestTextAndImage(ElementOrder::kTextFirst, text, imgSrc, flag_set); } -// (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ. -#if BUILDFLAG(IS_MAC) -#define MAYBE_ImageAndLargeText_TextType DISABLED_ImageAndLargeText_TextType -#else -#define MAYBE_ImageAndLargeText_TextType ImageAndLargeText_TextType -#endif // Case when text that is larger and comes after an image. The // LargestContentfulPaintType should be those of a text element. IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, - MAYBE_ImageAndLargeText_TextType) { + ImageAndLargeText_TextType) { auto flag_set = blink::LargestContentfulPaintType::kText; std::string text = "This is a text that is larger and comes after an image. The " @@ -782,19 +736,13 @@ std::string imgSrc = "images/green-2x2.png"; // The larger element comes later so 2 LCP entries are expected. - TestTextAndImage(ElementOrder::kImageFirst, text, imgSrc, 2, flag_set); + TestTextAndImage(ElementOrder::kImageFirst, text, imgSrc, flag_set); } -// (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ. -#if BUILDFLAG(IS_MAC) -#define MAYBE_TextAndLargeImage_ImageType DISABLED_TextAndLargeImage_ImageType -#else -#define MAYBE_TextAndLargeImage_ImageType TextAndLargeImage_ImageType -#endif // Case when a text that is smaller and comes before an Image. The // LargestContentfulPaintType should be those of an image element. IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, - MAYBE_TextAndLargeImage_ImageType) { + TextAndLargeImage_ImageType) { auto flag_set = blink::LargestContentfulPaintType::kImage | blink::LargestContentfulPaintType::kGIF | blink::LargestContentfulPaintType::kAnimatedImage; @@ -803,19 +751,13 @@ "This is a text that is smaller and comes before an image. The " "LargestContentfulPaintType should be those of an image element"; std::string imgSrc = "images/fail.gif"; - TestTextAndImage(ElementOrder::kTextFirst, text, imgSrc, 2, flag_set); + TestTextAndImage(ElementOrder::kTextFirst, text, imgSrc, flag_set); } -// (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ. -#if BUILDFLAG(IS_MAC) -#define MAYBE_LargeImageAndText_ImageType DISABLED_LargeImageAndText_ImageType -#else -#define MAYBE_LargeImageAndText_ImageType LargeImageAndText_ImageType -#endif // Case when a text that is smaller and comes after an Image. The // LargestContentfulPaintType should be those of an image element. IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTypeTest, - MAYBE_LargeImageAndText_ImageType) { + LargeImageAndText_ImageType) { auto flag_set = blink::LargestContentfulPaintType::kImage | blink::LargestContentfulPaintType::kGIF | blink::LargestContentfulPaintType::kAnimatedImage; @@ -823,7 +765,7 @@ "This is a text that is smaller and comes after an Image. The " "LargestContentfulPaintType should be those of an image element."; std::string imgSrc = "images/fail.gif"; - TestTextAndImage(ElementOrder::kImageFirst, text, imgSrc, 1, flag_set); + TestTextAndImage(ElementOrder::kImageFirst, text, imgSrc, flag_set); } // (https://crbug.com/1385713): Flaky on mac12-arm64-rel M1 Mac CQ.
diff --git a/chrome/browser/page_load_metrics/observers/README.md b/chrome/browser/page_load_metrics/observers/README.md index f10e551..7e8fdd57 100644 --- a/chrome/browser/page_load_metrics/observers/README.md +++ b/chrome/browser/page_load_metrics/observers/README.md
@@ -210,8 +210,13 @@ ## Best practices ### Implementation basics -* Header, implementation, and unit tests for new observers should be added to - the [chrome/browser/page_load_metrics/observers/](/chrome/browser/page_load_metrics/observers/) directory. +* If your new observer has no outside dependencies, and does not require + embedder support, then header, implementation, and unit tests for new + observers should be added to the + [components/page_load_metrics/browser/observers/](/components/page_load_metrics/browser/observers/) + directory. Otherwise, it should be added to the + [chrome/browser/page_load_metrics/observers/](/chrome/browser/page_load_metrics/observers/) + directory. * You may wish to add browser tests to [page_load_metrics_browsertest.cc](/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc). * Instantiate your observer in the `PageLoadMetricsEmbedder::RegisterObservers` method in [page_load_metrics_initialize.cc](/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc).
diff --git a/chrome/browser/page_load_metrics/observers/back_forward_cache_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/back_forward_cache_page_load_metrics_observer_browsertest.cc index 44267b5..ec204cd1 100644 --- a/chrome/browser/page_load_metrics/observers/back_forward_cache_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/back_forward_cache_page_load_metrics_observer_browsertest.cc
@@ -36,8 +36,9 @@ void SetUpCommandLine(base::CommandLine* command_line) override { feature_list_.InitWithFeaturesAndParameters( {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"ignore_outstanding_network_request_for_testing", "true"}}}, + {{"ignore_outstanding_network_request_for_testing", "true"}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}, {internal::kBackForwardCacheEmitZeroSamplesForKeyMetrics, {{}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls});
diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc index d5955ca..abd30ae 100644 --- a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.cc
@@ -43,8 +43,6 @@ const char kHistogramFromGWSParseStartToFirstContentfulPaint[] = "PageLoad.Clients.FromGoogleSearch.PaintTiming." "ParseStartToFirstContentfulPaint"; -const char kHistogramFromGWSParseDuration[] = - "PageLoad.Clients.FromGoogleSearch.ParseTiming.ParseDuration"; const char kHistogramFromGWSParseStart[] = "PageLoad.Clients.FromGoogleSearch.ParseTiming.NavigationToParseStart"; const char kHistogramFromGWSFirstInputDelay[] = @@ -516,11 +514,6 @@ logger_.OnParseStart(timing, GetDelegate()); } -void FromGWSPageLoadMetricsObserver::OnParseStop( - const page_load_metrics::mojom::PageLoadTiming& timing) { - logger_.OnParseStop(timing, GetDelegate()); -} - void FromGWSPageLoadMetricsObserver::OnComplete( const page_load_metrics::mojom::PageLoadTiming& timing) { logger_.OnComplete(timing, GetDelegate()); @@ -757,17 +750,6 @@ } } -void FromGWSPageLoadMetricsLogger::OnParseStop( - const page_load_metrics::mojom::PageLoadTiming& timing, - const page_load_metrics::PageLoadMetricsObserverDelegate& delegate) { - if (ShouldLogForegroundEventAfterCommit(timing.parse_timing->parse_stop, - delegate)) { - PAGE_LOAD_HISTOGRAM(internal::kHistogramFromGWSParseDuration, - timing.parse_timing->parse_stop.value() - - timing.parse_timing->parse_start.value()); - } -} - void FromGWSPageLoadMetricsLogger::OnUserInput( const blink::WebInputEvent& event, const page_load_metrics::mojom::PageLoadTiming& timing,
diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h index a92787ee..658404a 100644 --- a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h
@@ -21,7 +21,6 @@ extern const char kHistogramFromGWSFirstContentfulPaint[]; extern const char kHistogramFromGWSLargestContentfulPaint[]; extern const char kHistogramFromGWSParseStartToFirstContentfulPaint[]; -extern const char kHistogramFromGWSParseDuration[]; extern const char kHistogramFromGWSParseStart[]; extern const char kHistogramFromGWSFirstInputDelay[]; extern const char kHistogramFromGWSAbortStopBeforePaint[]; @@ -114,9 +113,6 @@ void OnParseStart( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadMetricsObserverDelegate& delegate); - void OnParseStop( - const page_load_metrics::mojom::PageLoadTiming& timing, - const page_load_metrics::PageLoadMetricsObserverDelegate& delegate); void OnUserInput( const blink::WebInputEvent& event, const page_load_metrics::mojom::PageLoadTiming& timing, @@ -201,8 +197,6 @@ const page_load_metrics::mojom::PageLoadTiming& timing) override; void OnParseStart( const page_load_metrics::mojom::PageLoadTiming& timing) override; - void OnParseStop( - const page_load_metrics::mojom::PageLoadTiming& timing) override; void OnComplete( const page_load_metrics::mojom::PageLoadTiming& timing) override;
diff --git a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc index b303467d..0ed86b8 100644 --- a/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer_unittest.cc
@@ -256,15 +256,6 @@ timing.paint_timing->first_image_paint.value().InMilliseconds(), 1); tester()->histogram_tester().ExpectTotalCount( - internal::kHistogramFromGWSParseDuration, 1); - tester()->histogram_tester().ExpectBucketCount( - internal::kHistogramFromGWSParseDuration, - (timing.parse_timing->parse_stop.value() - - timing.parse_timing->parse_start.value()) - .InMilliseconds(), - 1); - - tester()->histogram_tester().ExpectTotalCount( internal::kHistogramFromGWSDomContentLoaded, 1); tester()->histogram_tester().ExpectBucketCount( internal::kHistogramFromGWSDomContentLoaded,
diff --git a/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc index 405f085..6752c1e 100644 --- a/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/prerender_page_load_metrics_observer_browsertest.cc
@@ -66,6 +66,12 @@ protected: void CheckResponsivenessMetrics(const GURL& url) { + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent:: + kRecordNormalizedResponsivenessMetrics, + 1); + std::vector<std::string> ukm_list = { "InteractiveTiming.WorstUserInteractionLatency.MaxEventDuration", "InteractiveTiming.AverageUserInteractionLatencyOverBudget." @@ -125,6 +131,10 @@ GURL prerender_url = embedded_test_server()->GetURL("/title2.html"); prerender_helper_.AddPrerender(prerender_url); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + // Activate and wait for FCP. auto waiter = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( web_contents()); @@ -133,18 +143,30 @@ prerender_helper_.NavigatePrimaryPage(prerender_url); waiter->Wait(); - // Expect only FP and FCP for prerender are recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderNavigationToActivation, content::PrerenderTriggerType::kSpeculationRule, ""), 1); + + // Expect only FP and FCP for prerender are recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToFirstPaint, content::PrerenderTriggerType::kSpeculationRule, ""), 1); histogram_tester().ExpectTotalCount(internal::kHistogramFirstPaint, 0); + + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage, + 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToFirstContentfulPaint, @@ -161,6 +183,9 @@ waiter->Wait(); // Expect only FID for prerender is recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstInputInPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderFirstInputDelay4, @@ -174,6 +199,12 @@ ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); // Expect only LCP for prerender is recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToLargestContentfulPaint2, @@ -182,6 +213,10 @@ histogram_tester().ExpectTotalCount( internal::kHistogramLargestContentfulPaint, 0); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordLayoutShiftScoreMetrics, + 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderCumulativeShiftScore, @@ -270,6 +305,10 @@ GURL prerender_url = embedded_test_server()->GetURL("/title2.html"); prerender_helper_.AddPrerender(prerender_url); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + // Start an activation. prerender_helper_.NavigatePrimaryPage(prerender_url); @@ -283,6 +322,13 @@ ASSERT_TRUE( ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); + auto entries = GetMergedUkmEntries(PrerenderPageLoad::kEntryName); EXPECT_EQ(2u, entries.size()); @@ -335,6 +381,10 @@ int host_id = prerender_helper_.GetHostForUrl(prerender_url); EXPECT_NE(host_id, content::RenderFrameHost::kNoFrameTreeNodeId); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + // Activate and wait for FCP. auto waiter = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( web_contents()); @@ -348,13 +398,20 @@ /*is_renderer_initiated=*/false)); waiter->Wait(); - // Expect only FP and FCP for prerender are recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderNavigationToActivation, content::PrerenderTriggerType::kEmbedder, prerender_utils::kDirectUrlInputMetricSuffix), 1); + + // Expect only FP and FCP for prerender are recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToFirstPaint, @@ -362,6 +419,11 @@ prerender_utils::kDirectUrlInputMetricSuffix), 1); histogram_tester().ExpectTotalCount(internal::kHistogramFirstPaint, 0); + + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage, + 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToFirstContentfulPaint, @@ -379,6 +441,9 @@ waiter->Wait(); // Expect only FID for prerender is recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstInputInPage, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderFirstInputDelay4, @@ -393,6 +458,12 @@ ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); // Expect only LCP for prerender is recorded. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderActivationToLargestContentfulPaint2, @@ -402,6 +473,10 @@ histogram_tester().ExpectTotalCount( internal::kHistogramLargestContentfulPaint, 0); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordLayoutShiftScoreMetrics, + 1); histogram_tester().ExpectTotalCount( prerender_helper_.GenerateHistogramName( internal::kHistogramPrerenderCumulativeShiftScore, @@ -437,6 +512,10 @@ GURL prerender_url = embedded_test_server()->GetURL("/title2.html"); const int host_id = prerender_helper_.AddPrerender(prerender_url); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + content::test::PrerenderHostObserver observer(*web_contents(), host_id); prerender_helper_.CancelPrerenderedPage(host_id); observer.WaitForDestroyed(); @@ -446,6 +525,23 @@ ASSERT_TRUE( ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage, 0); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 0); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage, + 0); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); + // As the prerender was cancelled, no prerendering metrics are recorded. EXPECT_EQ(0u, histogram_tester() .GetTotalCountsForPrefix("PageLoad.Clients.Prerender.") @@ -475,6 +571,10 @@ redirected_url.spec()); prerender_helper_.AddPrerender(prerender_url); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + // Activate and wait for FCP. auto waiter = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( web_contents()); @@ -483,12 +583,30 @@ prerender_helper_.NavigatePrimaryPage(prerender_url); waiter->Wait(); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage, + 1); + // Force navigation to another page, which should force logging of histograms // persisted at the end of the page load lifetime. ASSERT_TRUE( ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); - // Verify that UKM records the URL after the redirection. + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); + + // Verify that UKM records the URL after the redirection, not the initial URL. auto entries = GetMergedUkmEntries(PrerenderPageLoad::kEntryName); ASSERT_FALSE(base::Contains(entries, prerender_url)); const ukm::mojom::UkmEntry* prerendered_page_entry = @@ -535,6 +653,10 @@ registry_observer.WaitForTrigger(kPrerenderingUrl); } + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart, 1); + int host_id = prerender_helper_.GetHostForUrl(kPrerenderingUrl); content::test::PrerenderHostObserver prerender_observer(*web_contents(), host_id); @@ -551,14 +673,38 @@ main_document_response.WaitForRequest(); main_document_response.Send(kResponseWithNoStore); main_document_response.Done(); + + auto waiter = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( + web_contents()); + waiter->AddPageExpectation(page_load_metrics::PageLoadMetricsTestWaiter:: + TimingField::kFirstContentfulPaint); primary_page_manager.WaitForNavigationFinished(); prerender_observer.WaitForActivation(); + waiter->Wait(); + + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage, 1); // Force navigation to another page, which should force logging of metrics // persisted at the end of the page load lifetime. ASSERT_TRUE( ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL))); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage, + 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete, 1); + histogram_tester().ExpectBucketCount( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms, 1); + auto entries = GetMergedUkmEntries(PrerenderPageLoad::kEntryName); EXPECT_EQ(2u, entries.size()); @@ -574,4 +720,8 @@ ukm_recorder().ExpectEntryMetric( prerendered_page_entry, PrerenderPageLoad::kMainFrameResource_RequestHasNoStoreName, 1); + + EXPECT_TRUE(ukm_recorder().EntryHasMetric( + prerendered_page_entry, + PrerenderPageLoad::kTiming_ActivationToLargestContentfulPaintName)); }
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_browsertest.cc index d9a7c112..794cdb91 100644 --- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/test/scoped_logging_settings.h" #include "components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h" #include "build/build_config.h" @@ -12,6 +13,7 @@ #include "content/public/common/content_features.h" #include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" namespace { @@ -27,6 +29,7 @@ content::DefaultEnabledBackForwardCacheParametersForTests(), content::DefaultDisabledBackForwardCacheParametersForTests()); MetricIntegrationTest::SetUpCommandLine(command_line); + vmodule_switches_.InitWithSwitches("back_forward_cache_impl=1"); } protected: @@ -41,6 +44,7 @@ } base::test::ScopedFeatureList feature_list_; + logging::ScopedVmoduleSwitches vmodule_switches_; }; } // namespace @@ -62,24 +66,23 @@ GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html")); // Navigate to A. - EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url_a)); - content::RenderFrameHost* rfh_a = top_frame_host(); - page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(rfh_a, + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_a)); + content::RenderFrameHostWrapper rfh_a(top_frame_host()); + page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(rfh_a.get(), features_0); // Navigate to B. - EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url_b)); - EXPECT_EQ(rfh_a->GetLifecycleState(), + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_b)); + ASSERT_EQ(rfh_a->GetLifecycleState(), content::RenderFrameHost::LifecycleState::kInBackForwardCache); // Go back to A. - web_contents()->GetController().GoBack(); - EXPECT_TRUE(WaitForLoadStop(web_contents())); + ASSERT_TRUE(content::HistoryGoBack(web_contents())); EXPECT_TRUE(rfh_a->IsInPrimaryMainFrame()); EXPECT_NE(rfh_a->GetLifecycleState(), content::RenderFrameHost::LifecycleState::kInBackForwardCache); - page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(rfh_a, + page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(rfh_a.get(), features_1); // The RenderFrameHost for the page B was likely in the back-forward cache @@ -87,13 +90,12 @@ // outstanding-network request. // Navigate to B again. - EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url_b)); - EXPECT_EQ(rfh_a->GetLifecycleState(), + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_b)); + ASSERT_EQ(rfh_a->GetLifecycleState(), content::RenderFrameHost::LifecycleState::kInBackForwardCache); // Go back to A again. - web_contents()->GetController().GoBack(); - EXPECT_TRUE(WaitForLoadStop(web_contents())); + ASSERT_TRUE(content::HistoryGoBack(web_contents())); EXPECT_TRUE(rfh_a->IsInPrimaryMainFrame()); EXPECT_NE(rfh_a->GetLifecycleState(), content::RenderFrameHost::LifecycleState::kInBackForwardCache);
diff --git a/chrome/browser/paint_preview/paint_preview_browsertest.cc b/chrome/browser/paint_preview/paint_preview_browsertest.cc index f33d48ad..c5cc535 100644 --- a/chrome/browser/paint_preview/paint_preview_browsertest.cc +++ b/chrome/browser/paint_preview/paint_preview_browsertest.cc
@@ -162,8 +162,8 @@ base::ScopedAllowBlockingForTesting scoped_blocking; auto it = recording_map->find( - base::UnguessableToken::Deserialize2(frame_proto.embedding_token_high(), - frame_proto.embedding_token_low()) + base::UnguessableToken::Deserialize(frame_proto.embedding_token_high(), + frame_proto.embedding_token_low()) .value()); ASSERT_NE(it, recording_map->end());
diff --git a/chrome/browser/password_manager/android/password_manager_android_browsertest.cc b/chrome/browser/password_manager/android/password_manager_android_browsertest.cc index 8721562..55f949cb 100644 --- a/chrome/browser/password_manager/android/password_manager_android_browsertest.cc +++ b/chrome/browser/password_manager/android/password_manager_android_browsertest.cc
@@ -21,18 +21,11 @@ autofill::PasswordFormFillData GetTestFillData() { autofill::PasswordFormFillData fill_data; - autofill::FormFieldData username_field; - username_field.name = u"username_field"; - fill_data.username_field = username_field; - autofill::FormFieldData password_field; - password_field.name = u"password_field"; - password_field.form_control_type = "password"; - fill_data.password_field = password_field; // Renderer IDs should match real elements' IDs. They cannot be retrieved in a // content::BrowserTestBase, so they are guessed based on the fact the // username and password fields are the first two elements on the page. - fill_data.username_field.unique_renderer_id = autofill::FieldRendererId(1); - fill_data.password_field.unique_renderer_id = autofill::FieldRendererId(2); + fill_data.username_element_renderer_id = autofill::FieldRendererId(1); + fill_data.password_element_renderer_id = autofill::FieldRendererId(2); return fill_data; }
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc index 43f6140..46e0514 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.cc
@@ -146,10 +146,10 @@ } if (account_info.has_value()) { - if (base::FeatureList::IsEnabled( - chrome::android::kHideNonDisplayableAccountEmail) && - account_info->capabilities.can_have_email_address_displayed() == - signin::Tribool::kFalse) { + if (account_info->capabilities.can_have_email_address_displayed() == + signin::Tribool::kFalse && + base::FeatureList::IsEnabled( + chrome::android::kHideNonDisplayableAccountEmail)) { account_email_ = account_info.value().full_name; } else { account_email_ = account_info.value().email;
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate.h b/chrome/browser/password_manager/android/save_update_password_message_delegate.h index 42294cff..6de7dd04 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate.h +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate.h
@@ -153,6 +153,8 @@ PasswordEditDialogFactory password_edit_dialog_factory_; raw_ptr<content::WebContents> web_contents_ = nullptr; + + // Can be the empty string, the account email, or the account full name. std::string account_email_; bool update_password_ = false;
diff --git a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc index 6e14c5e..0a40643b 100644 --- a/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc +++ b/chrome/browser/password_manager/android/save_update_password_message_delegate_unittest.cc
@@ -16,6 +16,7 @@ #include "base/test/with_feature_override.h" #include "chrome/browser/android/android_theme_resources.h" #include "chrome/browser/android/resource_mapper.h" +#include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -27,6 +28,7 @@ #include "components/password_manager/core/browser/password_form_metrics_recorder.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/common/password_manager_features.h" +#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" @@ -52,6 +54,8 @@ constexpr char16_t kPassword[] = u"password"; constexpr char kAccountEmail[] = "account@example.com"; constexpr char16_t kAccountEmail16[] = u"account@example.com"; +constexpr char kAccountFullName[] = "First Last"; +constexpr char16_t kAccountFullName16[] = u"First Last"; constexpr char kSaveUIDismissalReasonHistogramName[] = "PasswordManager.SaveUIDismissalReason"; constexpr char kUpdateUIDismissalReasonHistogramName[] = @@ -113,7 +117,8 @@ void EnqueueMessage(std::unique_ptr<PasswordFormManagerForUI> form_to_save, bool user_signed_in, - bool update_password); + bool update_password, + absl::optional<AccountInfo> account_info = {}); void TriggerActionClick(); void TriggerPasswordEditDialog(bool update_password); void TriggerNeverSaveMenuItem(); @@ -245,6 +250,10 @@ password_manager::features::kExploratorySaveUpdatePasswordStrings); } + // This feature only concerns AccountInfo with configured AccountCapabilities. + enabled_features.push_back( + {chrome::android::kHideNonDisplayableAccountEmail, {}}); + scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features, disabled_features); } @@ -292,9 +301,9 @@ void SaveUpdatePasswordMessageDelegateTest::EnqueueMessage( std::unique_ptr<PasswordFormManagerForUI> form_to_save, bool user_signed_in, - bool update_password) { - absl::optional<AccountInfo> account_info; - if (user_signed_in) { + bool update_password, + absl::optional<AccountInfo> account_info) { + if (user_signed_in && !account_info) { account_info = AccountInfo(); account_info.value().email = kAccountEmail; } @@ -503,7 +512,7 @@ GetMessageWrapper()->GetDescription().find(kAccountEmail16)); } - // Validate remainig message fields + // Validate remaining message fields if (GetParam().with_unified_password_manager_android) { // password_manager::features::kUnifiedPasswordManagerAndroid is enabled EXPECT_EQ(ResourceMapper::MapToJavaDrawableId( @@ -664,6 +673,50 @@ DismissMessage(messages::DismissReason::UNKNOWN); } +// Tests that the description is set correctly when the signed-in user with a +// non-displayable email saves a password. +TEST_P(SaveUpdatePasswordMessageDelegateTest, + SignedInDescription_SavePasswordNonDisplayableEmail) { + SetPendingCredentials(kUsername, kPassword); + auto form_manager = + CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); + const bool is_signed_in = true; + const bool is_update = false; + + absl::optional<AccountInfo> account_info; + account_info = AccountInfo(); + account_info.value().email = kAccountEmail; + account_info.value().full_name = kAccountFullName; + AccountCapabilitiesTestMutator mutator(&account_info.value().capabilities); + mutator.set_can_have_email_address_displayed(false); + + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update, account_info); + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountFullName16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { + // password_manager::features::kUnifiedPasswordManagerAndroid is enabled + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountFullName16), + GetMessageWrapper()->GetDescription()); + } else { + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kUsername)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kPassword)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kAccountEmail16)); + EXPECT_NE(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kAccountFullName16)); + } + DismissMessage(messages::DismissReason::UNKNOWN); +} + // Tests that the description is set correctly when signed-in user updates a // password. TEST_P(SaveUpdatePasswordMessageDelegateTest, @@ -699,6 +752,50 @@ DismissMessage(messages::DismissReason::UNKNOWN); } +// Tests that the description is set correctly when the signed-in user with a +// non-displayable email updates a password. +TEST_P(SaveUpdatePasswordMessageDelegateTest, + SignedInDescription_UpdatePasswordNonDisplayableEmail) { + SetPendingCredentials(kUsername, kPassword); + auto form_manager = + CreateFormManager(GURL(kDefaultUrl), empty_best_matches()); + const bool is_signed_in = true; + const bool is_update = true; + + absl::optional<AccountInfo> account_info; + account_info = AccountInfo(); + account_info.value().email = kAccountEmail; + account_info.value().full_name = kAccountFullName; + AccountCapabilitiesTestMutator mutator(&account_info.value().capabilities); + mutator.set_can_have_email_address_displayed(false); + + EnqueueMessage(std::move(form_manager), /*user_signed_in=*/is_signed_in, + /*update_password=*/is_update, account_info); + if (GetParam().with_exploratory_save_update_password_strings) { + // password_manager::features::kExploratorySaveUpdatePasswordStrings is + // enabled + EXPECT_EQ(GetExploratoryStringsMessageDescription( + is_update, is_signed_in, kAccountFullName16, + GetParam().save_update_prompt_syncing_string_version), + GetMessageWrapper()->GetDescription()); + } else if (GetParam().with_unified_password_manager_android) { + // password_manager::features::kUnifiedPasswordManagerAndroid is enabled + EXPECT_EQ(GetUnifiedPasswordManagerMessageDescription( + is_update, is_signed_in, kAccountFullName16), + GetMessageWrapper()->GetDescription()); + } else { + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kUsername)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kPassword)); + EXPECT_EQ(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kAccountEmail16)); + EXPECT_NE(std::u16string::npos, + GetMessageWrapper()->GetDescription().find(kAccountFullName16)); + } + DismissMessage(messages::DismissReason::UNKNOWN); +} + // Tests that the previous prompt gets dismissed when the new one is enqueued. TEST_P(SaveUpdatePasswordMessageDelegateTest, OnlyOnePromptAtATime) { SetPendingCredentials(kUsername, kPassword);
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 1dd7f24..b8d5fb7 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -55,6 +55,7 @@ #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/logging/log_receiver.h" #include "components/autofill/core/browser/ui/suggestion.h" +#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #include "components/autofill/core/common/password_generation_util.h" #include "components/back_forward_cache/back_forward_cache_disable.h" #include "components/browsing_data/content/browsing_data_helper.h" @@ -1173,6 +1174,9 @@ popup_controller_->GeneratedPasswordRejected(); } + driver->SetSuggestionAvailability( + ui_data.generation_element_id, + autofill::mojom::AutofillState::kAutofillAvailable); return; } @@ -1682,6 +1686,12 @@ popup_controller_->Show( PasswordGenerationPopupController::kOfferGeneration); } + + driver->SetSuggestionAvailability( + ui_data.generation_element_id, + popup_controller_->IsVisible() + ? autofill::mojom::AutofillState::kAutofillAvailable + : autofill::mojom::AutofillState::kNoSuggestions); } gfx::RectF ChromePasswordManagerClient::TransformToRootCoordinates(
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index ac11ae8..48ac8cb2 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -168,8 +168,9 @@ LOG(INFO) << "SetUpCommandLine started."; scoped_feature_list_.InitWithFeaturesAndParameters( {{::features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"ignore_outstanding_network_request_for_testing", "true"}}}}, + {{"ignore_outstanding_network_request_for_testing", "true"}}}, + {::features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {::features::kBackForwardCacheMemoryControls}); PasswordManagerBrowserTest::SetUpCommandLine(command_line);
diff --git a/chrome/browser/performance_manager/policies/bfcache_policy_browsertest.cc b/chrome/browser/performance_manager/policies/bfcache_policy_browsertest.cc index fe1c590f..67407b3f 100644 --- a/chrome/browser/performance_manager/policies/bfcache_policy_browsertest.cc +++ b/chrome/browser/performance_manager/policies/bfcache_policy_browsertest.cc
@@ -87,8 +87,9 @@ EnableFeature(::features::kBackForwardCache, {{"foreground_cache_size", "10"}, {"cache_size", "10"}, - {"TimeToLiveInBackForwardCacheInSeconds", "3600"}, {"ignore_outstanding_network_request_for_testing", "true"}}); + EnableFeature(::features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}); DisableFeature(::features::kBackForwardCacheMemoryControls); // Occlusion can cause the web_contents to be marked visible between the // time the test calls WasHidden and BFCachePolicy::MaybeFlushBFCache is
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc index dbbff9a7..8032e91 100644 --- a/chrome/browser/permissions/permission_request_manager_browsertest.cc +++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -235,8 +235,9 @@ PermissionRequestManagerBrowserTest::SetUpCommandLine(command_line); feature_list_.InitWithFeaturesAndParameters( {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"ignore_outstanding_network_request_for_testing", "true"}}}}, + {{"ignore_outstanding_network_request_for_testing", "true"}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/chrome/browser/permissions/permission_revocation_request.cc b/chrome/browser/permissions/permission_revocation_request.cc index 79e0f02..05dfca0 100644 --- a/chrome/browser/permissions/permission_revocation_request.cc +++ b/chrome/browser/permissions/permission_revocation_request.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/permissions/constants.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_uma_util.h" @@ -22,7 +23,6 @@ namespace { constexpr char kExcludedKey[] = "exempted"; -constexpr char kRevokedKey[] = "revoked"; constexpr char kPermissionName[] = "notifications"; struct OriginStatus { @@ -51,9 +51,9 @@ status.is_exempt_from_future_revocations = dict->FindBoolPath(kExcludedKey).value(); } - if (dict->FindBoolPath(kRevokedKey).has_value()) { + if (dict->FindBoolPath(permissions::kRevokedKey).has_value()) { status.has_been_previously_revoked = - dict->FindBoolPath(kRevokedKey).value(); + dict->FindBoolPath(permissions::kRevokedKey).value(); } return status; @@ -65,7 +65,8 @@ base::Value::Dict dict; base::Value::Dict permission_dict; permission_dict.Set(kExcludedKey, status.is_exempt_from_future_revocations); - permission_dict.Set(kRevokedKey, status.has_been_previously_revoked); + permission_dict.Set(permissions::kRevokedKey, + status.has_been_previously_revoked); dict.Set(kPermissionName, std::move(permission_dict)); permissions::PermissionsClient::Get()
diff --git a/chrome/browser/policy/test/developer_tools_policy_browsertest.cc b/chrome/browser/policy/test/developer_tools_policy_browsertest.cc index a47ab44..1feedb67 100644 --- a/chrome/browser/policy/test/developer_tools_policy_browsertest.cc +++ b/chrome/browser/policy/test/developer_tools_policy_browsertest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/policy_constants.h" @@ -117,6 +118,40 @@ EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents)); } +// Test for https://b/263040629 +IN_PROC_BROWSER_TEST_F(PolicyTest, AvailabilityWins) { + // DeveloperToolsDisabled is true, but DeveloperToolsAvailability wins. + PolicyMap policies; + policies.Set(key::kDeveloperToolsAvailability, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, + base::Value(1 /* DeveloperToolsAllowed */), nullptr); + policies.Set(key::kDeveloperToolsDisabled, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true), + nullptr); + UpdateProviderPolicy(policies); + + EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS)); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + DevToolsWindow* devtools_window = + DevToolsWindow::GetInstanceForInspectedWebContents(contents); + EXPECT_TRUE(devtools_window); + + // Clearing DeveloperToolsAvailability leaves behind + // DeveloperToolsDisabled, so the DevTools window gets closed. + content::WebContentsDestroyedWatcher close_observer( + DevToolsWindowTesting::Get(devtools_window)->main_web_contents()); + policies.Erase(key::kDeveloperToolsAvailability); + UpdateProviderPolicy(policies); + // wait for devtools close + close_observer.Wait(); + // The existing devtools window should have closed. + EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents)); + // And it's not possible to open it again. + EXPECT_FALSE(chrome::ExecuteCommand(browser(), IDC_DEV_TOOLS)); + EXPECT_FALSE(DevToolsWindow::GetInstanceForInspectedWebContents(contents)); +} + IN_PROC_BROWSER_TEST_F(PolicyTest, ViewSourceDisabledByDeveloperToolsAvailability) { // Verifies that entry points to ViewSource can be disabled by setting the
diff --git a/chrome/browser/policy/test/send_mouse_events_disabled_form_controls_policy_browsertest.cc b/chrome/browser/policy/test/send_mouse_events_disabled_form_controls_policy_browsertest.cc index adf4ca32..500a604 100644 --- a/chrome/browser/policy/test/send_mouse_events_disabled_form_controls_policy_browsertest.cc +++ b/chrome/browser/policy/test/send_mouse_events_disabled_form_controls_policy_browsertest.cc
@@ -15,6 +15,20 @@ #include "content/public/test/browser_test.h" #include "url/gurl.h" +#if BUILDFLAG(IS_ANDROID) +#define MAYBE_SendMouseEventsdisabledFormControlsPolicyTest \ + DISABLED_SendMouseEventsdisabledFormControlsPolicyTest +#else +#define MAYBE_SendMouseEventsdisabledFormControlsPolicyTest SendMouseEventsdisabledFormControlsPolicyTest +#endif +// "All/DISABLED_SendMouseEventsdisabledFormControlsPolicyTest" does not work. We need +// "DISABLED_All/...". TODO(https://crbug.com/1096416) delete when fixed. +#if BUILDFLAG(IS_ANDROID) +#define MAYBE_All DISABLED_All +#else +#define MAYBE_All All +#endif + namespace policy { enum class SendMouseEventsDisabledFormControlsPolicyValue { @@ -23,7 +37,7 @@ kDisabled, }; -class SendMouseEventsDisabledFormControlsPolicyTest +class MAYBE_SendMouseEventsDisabledFormControlsPolicyTest : public testing::WithParamInterface< SendMouseEventsDisabledFormControlsPolicyValue>, public PolicyTest { @@ -72,15 +86,15 @@ } }; -IN_PROC_BROWSER_TEST_P(SendMouseEventsDisabledFormControlsPolicyTest, Test) { +IN_PROC_BROWSER_TEST_P(MAYBE_SendMouseEventsDisabledFormControlsPolicyTest, Test) { bool expected_enabled = GetParam() == SendMouseEventsDisabledFormControlsPolicyValue::kEnabled; AssertSendMouseEventsDisabledFormControlsEnabled(expected_enabled); } INSTANTIATE_TEST_SUITE_P( - /* no prefix */, - SendMouseEventsDisabledFormControlsPolicyTest, + MAYBE_All, + MAYBE_SendMouseEventsDisabledFormControlsPolicyTest, ::testing::Values( SendMouseEventsDisabledFormControlsPolicyValue::kEnabled, SendMouseEventsDisabledFormControlsPolicyValue::kDisabled));
diff --git a/chrome/browser/predictors/network_hints_handler_impl.cc b/chrome/browser/predictors/network_hints_handler_impl.cc index 6e3f4ca..2ba7b74 100644 --- a/chrome/browser/predictors/network_hints_handler_impl.cc +++ b/chrome/browser/predictors/network_hints_handler_impl.cc
@@ -43,7 +43,8 @@ std::move(receiver)); } -void NetworkHintsHandlerImpl::PrefetchDNS(const std::vector<GURL>& urls) { +void NetworkHintsHandlerImpl::PrefetchDNS( + const std::vector<url::SchemeHostPort>& urls) { if (!preconnect_manager_) return; @@ -52,17 +53,20 @@ if (!render_frame_host) return; + std::vector<GURL> gurls; + for (const auto& url : urls) { + gurls.emplace_back(url.GetURL()); + } preconnect_manager_->StartPreresolveHosts( - urls, GetPendingNetworkAnonymizationKey(render_frame_host)); + gurls, GetPendingNetworkAnonymizationKey(render_frame_host)); } -void NetworkHintsHandlerImpl::Preconnect(const GURL& url, +void NetworkHintsHandlerImpl::Preconnect(const url::SchemeHostPort& url, bool allow_credentials) { if (!preconnect_manager_) return; - if (!url.is_valid() || !url.has_host() || !url.has_scheme() || - !url.SchemeIsHTTPOrHTTPS()) { + if (url.scheme() != url::kHttpScheme && url.scheme() != url::kHttpsScheme) { return; } @@ -75,7 +79,7 @@ return; preconnect_manager_->StartPreconnectUrl( - url, allow_credentials, + url.GetURL(), allow_credentials, GetPendingNetworkAnonymizationKey(render_frame_host)); }
diff --git a/chrome/browser/predictors/network_hints_handler_impl.h b/chrome/browser/predictors/network_hints_handler_impl.h index 22450737..4c7a29f 100644 --- a/chrome/browser/predictors/network_hints_handler_impl.h +++ b/chrome/browser/predictors/network_hints_handler_impl.h
@@ -29,8 +29,9 @@ receiver); // network_hints::mojom::NetworkHintsHandler methods: - void PrefetchDNS(const std::vector<GURL>& urls) override; - void Preconnect(const GURL& url, bool allow_credentials) override; + void PrefetchDNS(const std::vector<url::SchemeHostPort>& urls) override; + void Preconnect(const url::SchemeHostPort& url, + bool allow_credentials) override; private: explicit NetworkHintsHandlerImpl(content::RenderFrameHost* frame_host);
diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn index 5d3019ff..b520755 100644 --- a/chrome/browser/preferences/BUILD.gn +++ b/chrome/browser/preferences/BUILD.gn
@@ -45,6 +45,7 @@ "//components/privacy_sandbox/privacy_sandbox_prefs.cc", "//components/safe_browsing/core/common/safe_browsing_prefs.cc", "//components/signin/public/base/signin_pref_names.cc", + "//components/supervised_user/core/common/pref_names.cc", "//components/translate/core/browser/translate_pref_names.cc", ]
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java index 249276bd..a7787641 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java
@@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -499,12 +498,7 @@ @Test @SmallTest public void testWriteStrings() { - mSubject.writeStrings(new HashMap<String, String>() { - { - put(PREFIXED_KEY_1, "first"); - put("string_key", "second"); - } - }); + mSubject.writeStrings(Map.of(PREFIXED_KEY_1, "first", "string_key", "second")); // Verify values can be read assertEquals("first", mSubject.readString(PREFIXED_KEY_1, "")); @@ -514,12 +508,7 @@ @Test @SmallTest public void testWriteInts() { - mSubject.writeInts(new HashMap<String, Integer>() { - { - put(PREFIXED_KEY_1, 1001); - put("int_key", 1002); - } - }); + mSubject.writeInts(Map.of(PREFIXED_KEY_1, 1001, "int_key", 1002)); // Verify values can be read assertEquals(1001, mSubject.readInt(PREFIXED_KEY_1)); @@ -529,12 +518,7 @@ @Test @SmallTest public void testWriteLongs() { - mSubject.writeLongs(new HashMap<String, Long>() { - { - put(PREFIXED_KEY_1, 21474836470001L); - put("long_key", 21474836470002L); - } - }); + mSubject.writeLongs(Map.of(PREFIXED_KEY_1, 21474836470001L, "long_key", 21474836470002L)); // Verify values can be read assertEquals(21474836470001L, mSubject.readLong(PREFIXED_KEY_1)); @@ -544,12 +528,7 @@ @Test @SmallTest public void testWriteFloats() { - mSubject.writeFloats(new HashMap<String, Float>() { - { - put(PREFIXED_KEY_1, 1.5f); - put("float_key", 2.5f); - } - }); + mSubject.writeFloats(Map.of(PREFIXED_KEY_1, 1.5f, "float_key", 2.5f)); // Verify values can be read assertEquals(1.5f, mSubject.readFloat(PREFIXED_KEY_1, 0f), 1e-10); @@ -559,12 +538,7 @@ @Test @SmallTest public void testWriteDoubles() { - mSubject.writeDoubles(new HashMap<String, Double>() { - { - put(PREFIXED_KEY_1, 1.5); - put("double_key", 2.5); - } - }); + mSubject.writeDoubles(Map.of(PREFIXED_KEY_1, 1.5, "double_key", 2.5)); // Verify values can be read assertEquals(1.5, mSubject.readDouble(PREFIXED_KEY_1, 0.0), 1e-10); @@ -574,12 +548,7 @@ @Test @SmallTest public void testWriteBooleans() { - mSubject.writeBooleans(new HashMap<String, Boolean>() { - { - put(PREFIXED_KEY_1, true); - put("long_key", false); - } - }); + mSubject.writeBooleans(Map.of(PREFIXED_KEY_1, true, "long_key", false)); // Verify values can be read assertTrue(mSubject.readBoolean(PREFIXED_KEY_1, false));
diff --git a/chrome/browser/prefetch/prefetch_prefs_unittest.cc b/chrome/browser/prefetch/prefetch_prefs_unittest.cc index 3f02125..146d2cf5 100644 --- a/chrome/browser/prefetch/prefetch_prefs_unittest.cc +++ b/chrome/browser/prefetch/prefetch_prefs_unittest.cc
@@ -6,6 +6,7 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/battery/battery_saver.h" +#include "chrome/browser/data_saver/data_saver.h" #include "chrome/browser/prefetch/pref_names.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_registry_simple.h" @@ -228,3 +229,28 @@ EXPECT_EQ(prefetch::IsSomePreloadingEnabled(prefs), content::PreloadingEligibility::kBatterySaverEnabled); } + +class PrefetchPrefsWithDataSaverTest : public ::testing::Test { + public: + PrefetchPrefsWithDataSaverTest() = default; + ~PrefetchPrefsWithDataSaverTest() override = default; + + void TearDown() override { data_saver::ResetIsDataSaverEnabledForTesting(); } + + // IsSomePreloadingEnabledIgnoringFinch() requires a threaded environment. + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(PrefetchPrefsWithDataSaverTest, IsSomePreloadingEnabledIgnoringFinch) { + TestingPrefServiceSimple prefs; + prefs.registry()->RegisterIntegerPref( + prefs::kNetworkPredictionOptions, + static_cast<int>(prefetch::NetworkPredictionOptions::kDefault)); + data_saver::OverrideIsDataSaverEnabledForTesting(false); + EXPECT_EQ(prefetch::IsSomePreloadingEnabledIgnoringFinch(prefs), + content::PreloadingEligibility::kEligible); + + data_saver::OverrideIsDataSaverEnabledForTesting(true); + EXPECT_EQ(prefetch::IsSomePreloadingEnabledIgnoringFinch(prefs), + content::PreloadingEligibility::kDataSaverEnabled); +}
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 7e917c31..193d174d 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -1530,7 +1530,6 @@ #else // BUILDFLAG(IS_ANDROID) browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry); BrowserFeaturePromoSnoozeService::RegisterProfilePrefs(registry); - captions::LiveCaptionController::RegisterProfilePrefs(registry); captions::LiveTranslateController::RegisterProfilePrefs(registry); ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry); DeviceServiceImpl::RegisterProfilePrefs(registry); @@ -1564,6 +1563,9 @@ UnifiedAutoplayConfig::RegisterProfilePrefs(registry); CartService::RegisterProfilePrefs(registry); commerce::ShoppingListUiTabHelper::RegisterProfilePrefs(registry); +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + captions::LiveCaptionController::RegisterProfilePrefs(registry); +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc b/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc index 84853a6..3e54f91 100644 --- a/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc +++ b/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc
@@ -76,9 +76,9 @@ return helper->IsEnabled(); } -bool ChromePrefetchServiceDelegate::IsSomePreloadingEnabled() { - return prefetch::IsSomePreloadingEnabled(*profile_->GetPrefs()) == - content::PreloadingEligibility::kEligible; +content::PreloadingEligibility +ChromePrefetchServiceDelegate::IsSomePreloadingEnabled() { + return prefetch::IsSomePreloadingEnabled(*profile_->GetPrefs()); } bool ChromePrefetchServiceDelegate::IsExtendedPreloadingEnabled() {
diff --git a/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h b/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h index 3ae8185..d8cf15ef 100644 --- a/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h +++ b/chrome/browser/preloading/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h
@@ -41,7 +41,7 @@ bool IsOriginOutsideRetryAfterWindow(const GURL& url) override; void ClearData() override; bool DisableDecoysBasedOnUserSettings() override; - bool IsSomePreloadingEnabled() override; + content::PreloadingEligibility IsSomePreloadingEnabled() override; bool IsExtendedPreloadingEnabled() override; bool IsDomainInPrefetchAllowList(const GURL& referring_url) override; void OnPrefetchLikely(content::WebContents* web_contents) override;
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 92b86fa..226bc49f 100644 --- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc +++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc
@@ -147,6 +147,12 @@ content::PreloadingFailureReason ToPreloadingFailureReason( SearchPrefetchServingReason reason) { + // If you are copying this pattern for another prefetch use case beyond + // SearchPrefetchServingReason, please take care to ensure that you use a + // non-overlapping range after kPreloadingFailureReasonContentEnd. It is + // probably a good idea to centralize the allocation of enum ranges whenever a + // second case emerges. + // TODO(sreejakshetty): Assert that the reasons do not overlap. return static_cast<content::PreloadingFailureReason>( static_cast<int>(reason) + static_cast<int>(content::PreloadingFailureReason::
diff --git a/chrome/browser/printing/print_backend_service_manager.cc b/chrome/browser/printing/print_backend_service_manager.cc index 1bb7f06..b92119ee 100644 --- a/chrome/browser/printing/print_backend_service_manager.cc +++ b/chrome/browser/printing/print_backend_service_manager.cc
@@ -132,6 +132,14 @@ return *RegisterClient(ClientType::kPrintDocument, printer_name); } +PrintBackendServiceManager::ClientId +PrintBackendServiceManager::RegisterPrintDocumentClientReusingClientRemote( + ClientId id) { + DCHECK(query_with_ui_clients_.contains(id)); + return *RegisterClient(ClientType::kPrintDocument, + query_with_ui_clients_[id]); +} + void PrintBackendServiceManager::UnregisterClient(ClientId id) { // Determine which client type has this ID, and remove it once found. absl::optional<ClientType> client_type; @@ -522,10 +530,15 @@ } absl::optional<PrintBackendServiceManager::ClientId> -PrintBackendServiceManager::RegisterClient(ClientType client_type, - const std::string& printer_name) { +PrintBackendServiceManager::RegisterClient( + ClientType client_type, + absl::variant<std::string, RemoteId> destination) { ClientId client_id = ClientId(++last_client_id_); - RemoteId remote_id = GetRemoteIdForPrinterName(printer_name); + RemoteId remote_id = + absl::holds_alternative<std::string>(destination) + ? GetRemoteIdForPrinterName( + /*printer_name=*/absl::get<std::string>(destination)) + : absl::get<RemoteId>(destination); VLOG(1) << "Registering a client with ID " << client_id << " for print backend service."; @@ -538,7 +551,7 @@ if (!query_with_ui_clients_.empty()) return absl::nullopt; #endif - query_with_ui_clients_.insert(client_id); + query_with_ui_clients_.insert({client_id, remote_id}); break; case ClientType::kPrintDocument: print_document_clients_[remote_id].insert(client_id); @@ -568,8 +581,10 @@ } else { // Service not already available, so launch it now so that it will be // ready by the time the client gets to point of invoking a Mojo call. + DCHECK(absl::holds_alternative<std::string>(destination)); bool is_sandboxed; - GetService(printer_name, client_type, &is_sandboxed); + GetService(/*printer_name=*/absl::get<std::string>(destination), + client_type, &is_sandboxed); } return client_id; @@ -749,6 +764,16 @@ } } +bool PrintBackendServiceManager::HasQueryWithUiClientForRemoteId( + const RemoteId& remote_id) const { + for (auto& item : query_with_ui_clients_) { + if (item.second == remote_id) { + return true; + } + } + return false; +} + bool PrintBackendServiceManager::HasPrintDocumentClientForRemoteId( const RemoteId& remote_id) const { return GetPrintDocumentClientsCountForRemoteId(remote_id) > 0; @@ -830,7 +855,7 @@ case ClientType::kQuery: // Other query types have longer timeouts, so no need to update if // any of them have clients. - if (!query_with_ui_clients_.empty() || + if (HasQueryWithUiClientForRemoteId(remote_id) || HasPrintDocumentClientForRemoteId(remote_id)) { return absl::nullopt; } @@ -845,8 +870,9 @@ case ClientType::kQueryWithUi: #if BUILDFLAG(IS_LINUX) // No need to update if there were other query with UI clients. - if (!query_with_ui_clients_.empty()) + if (HasQueryWithUiClientForRemoteId(remote_id)) { return absl::nullopt; + } #else // A modal system dialog, of which there should only ever be at most one // of these. If one was dropped, it should now be empty. @@ -864,17 +890,13 @@ : kClientsRegisteredResetOnIdleTimeout; case ClientType::kPrintDocument: - // No need to update if there were other printing clients for same remote - // ID. - if (HasPrintDocumentClientForRemoteId(remote_id)) { + // No need to update if there were other printing clients or query with + // UI clients for same remote ID. + if (HasQueryWithUiClientForRemoteId(remote_id) || + HasPrintDocumentClientForRemoteId(remote_id)) { return absl::nullopt; } - // This is the longest timeout, so no need to update if there is still a - // query with UI. - if (!query_with_ui_clients_.empty()) - return absl::nullopt; - // New timeout depends upon existence of other queries. return query_clients_.empty() ? kNoClientsRegisteredResetOnIdleTimeout : kClientsRegisteredResetOnIdleTimeout; @@ -1275,7 +1297,7 @@ // static void PrintBackendServiceManager::SetClientsForTesting( const ClientsSet& query_clients, - const ClientsSet& query_with_ui_clients, + const QueryWithUiClientsMap& query_with_ui_clients, const PrintClientsMap& print_document_clients) { g_print_backend_service_manager_singleton->query_clients_ = query_clients; g_print_backend_service_manager_singleton->query_with_ui_clients_ =
diff --git a/chrome/browser/printing/print_backend_service_manager.h b/chrome/browser/printing/print_backend_service_manager.h index 7dd0d66..89a1605 100644 --- a/chrome/browser/printing/print_backend_service_manager.h +++ b/chrome/browser/printing/print_backend_service_manager.h
@@ -21,6 +21,7 @@ #include "mojo/public/cpp/bindings/remote_set.h" #include "printing/buildflags/buildflags.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #if BUILDFLAG(ENABLE_OOP_BASIC_PRINT_DIALOG) #include "ui/gfx/native_widget_types.h" @@ -50,6 +51,9 @@ // Contains set of client IDs. using ClientsSet = base::flat_set<ClientId>; + // Mapping of the RemoteId + using QueryWithUiClientsMap = base::flat_map<ClientId, RemoteId>; + // Mapping of clients to each remote ID that is for printing. using PrintClientsMap = base::flat_map<RemoteId, ClientsSet>; @@ -81,6 +85,12 @@ // to a specific printer. ClientId RegisterPrintDocumentClient(const std::string& printer_name); + // Register as a client of PrintBackendServiceManager for printing a document + // to a specific printer. Use the same `RemoteId` for this new printing + // client as has been used by the indicated query with UI client. This method + // will DCHECK if the client ID provided is not for a query with UI client. + ClientId RegisterPrintDocumentClientReusingClientRemote(ClientId id); + // Notify the manager that this client is no longer needing print backend // services. This signal might alter the manager's internal optimizations. void UnregisterClient(ClientId id); @@ -281,9 +291,14 @@ // Determine the remote ID that is used for the specified `printer_name`. RemoteId GetRemoteIdForPrinterName(const std::string& printer_name); - // Common helper for registering clients. - absl::optional<ClientId> RegisterClient(ClientType client_type, - const std::string& printer_name); + // Common helper for registering clients. The `destination` parameter can be + // either a `std::string` for a printer name or a `RemoteId` which was + // generated from a prior registration. This method will DCHECK if the + // `destination` is a `RemoteId` and the registration requires launching + // another service instance. + absl::optional<ClientId> RegisterClient( + ClientType client_type, + absl::variant<std::string, RemoteId> destination); // Get the total number of clients registered. size_t GetClientsRegisteredCount() const; @@ -318,6 +333,9 @@ static constexpr base::TimeDelta GetClientTypeIdleTimeout( ClientType client_type); + // Whether any clients are queries with UI to `remote_id`. + bool HasQueryWithUiClientForRemoteId(const RemoteId& remote_id) const; + // Whether any clients are printing documents to `remote_id`. bool HasPrintDocumentClientForRemoteId(const RemoteId& remote_id) const; @@ -454,7 +472,7 @@ // Test support for client ID management. static void SetClientsForTesting( const ClientsSet& query_clients, - const ClientsSet& query_with_ui_clients, + const QueryWithUiClientsMap& query_with_ui_clients, const PrintClientsMap& print_document_clients); #if BUILDFLAG(IS_WIN) @@ -479,8 +497,9 @@ // Set of IDs for clients actively engaged in a printing query which requires // the use of a UI. Such a UI corresponds to a modal system dialog. For // Linux there can be multiple of these, but for other platforms there can be - // at most one such client. - ClientsSet query_with_ui_clients_; + // at most one such client. Track the `RemoteId` which is associated with + // each such client. + QueryWithUiClientsMap query_with_ui_clients_; // Map of remote ID to the set of clients printing documents to it. PrintClientsMap print_document_clients_;
diff --git a/chrome/browser/printing/print_backend_service_manager_unittest.cc b/chrome/browser/printing/print_backend_service_manager_unittest.cc index 1723343c..ed35d0e 100644 --- a/chrome/browser/printing/print_backend_service_manager_unittest.cc +++ b/chrome/browser/printing/print_backend_service_manager_unittest.cc
@@ -18,6 +18,7 @@ using ClientId = PrintBackendServiceManager::ClientId; using ClientsSet = PrintBackendServiceManager::ClientsSet; using PrintClientsMap = PrintBackendServiceManager::PrintClientsMap; +using QueryWithUiClientsMap = PrintBackendServiceManager::QueryWithUiClientsMap; using RemoteId = PrintBackendServiceManager::RemoteId; namespace { @@ -40,11 +41,13 @@ const ClientsSet kTestQueryWithOneClient{kClientIdQuery1}; const ClientsSet kTestQueryWithTwoClients{kClientIdQuery1, kClientIdQuery2}; -const ClientsSet kTestQueryWithUiNoClients; -const ClientsSet kTestQueryWithUiOneClient{kClientIdQueryWithUi1}; +const QueryWithUiClientsMap kTestQueryWithUiNoClients; +const QueryWithUiClientsMap kTestQueryWithUiOneClient{ + {kClientIdQueryWithUi1, kRemoteIdEmpty}}; #if BUILDFLAG(IS_LINUX) -const ClientsSet kTestQueryWithUiTwoClients{kClientIdQueryWithUi1, - kClientIdQueryWithUi2}; +const QueryWithUiClientsMap kTestQueryWithUiTwoClients{ + {kClientIdQueryWithUi1, kRemoteIdEmpty}, + {kClientIdQueryWithUi2, kRemoteIdEmpty}}; #endif const PrintClientsMap kTestPrintDocumentNoClients; @@ -68,7 +71,7 @@ IsIdleTimeoutUpdateNeededForRegisteredClient) { const struct TestData { ClientsSet query_clients; - ClientsSet query_with_ui_client; + QueryWithUiClientsMap query_with_ui_client; PrintClientsMap print_document_clients; PrintBackendServiceManager::ClientType modified_client_type; absl::optional<base::TimeDelta> new_timeout; @@ -215,7 +218,7 @@ IsIdleTimeoutUpdateNeededForUnregisteredClient) { const struct TestData { ClientsSet query_clients; - ClientsSet query_with_ui_client; + QueryWithUiClientsMap query_with_ui_client; PrintClientsMap print_document_clients; PrintBackendServiceManager::ClientType modified_client_type; absl::optional<base::TimeDelta> new_timeout;
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index bb0a585..e1bd9b8 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -1155,11 +1155,12 @@ void SetUpCommandLine(base::CommandLine* command_line) override { scoped_feature_list_.InitWithFeaturesAndParameters( - {{::features::kBackForwardCache, + {{::features::kBackForwardCache, {{}}}, + {::features::kBackForwardCacheTimeToLiveControl, // Set a very long TTL before expiration (longer than the test // timeout) so tests that are expecting deletion don't pass when // they shouldn't. - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {::features::kBackForwardCacheMemoryControls});
diff --git a/chrome/browser/privacy/BUILD.gn b/chrome/browser/privacy/BUILD.gn index 7c1e5659..aad92a5 100644 --- a/chrome/browser/privacy/BUILD.gn +++ b/chrome/browser/privacy/BUILD.gn
@@ -77,29 +77,51 @@ # Generate Python bindings for traffic_annotation.proto, for use with # auditor.py. This lets us run auditor.py after simply building the chrome # target. - proto_library("chrome_settings_full_runtime") { + proto_library("chrome_settings") { + visibility = [ + ":traffic_annotation_proto", + ":traffic_annotation_proto_gen", + ] + sources = + [ "$root_gen_dir" + "/components/policy/proto/chrome_settings.proto" ] + + # import policy_common_definitions.proto + import_dirs = [ "//components/policy/proto" ] + + # generate chrome_settings.proto + proto_deps = [ "//components/policy:policy_code_generate" ] + proto_out_dir = "chrome/browser/privacy" + generate_cc = false + generate_library = false + } + + proto_library("device_policy_and_policy_common_definitions") { visibility = [ ":traffic_annotation_proto", ":traffic_annotation_proto_gen", ] sources = [ - "$root_gen_dir" + - "/components/policy/proto/cloud_policy_full_runtime.proto", - "$root_gen_dir" + - "/components/policy/proto/chrome_settings_full_runtime.proto", - "$root_gen_dir" + "/components/policy/proto" + - "/policy_common_definitions_full_runtime.proto", + "//components/policy/proto/chrome_device_policy.proto", + "//components/policy/proto/policy_common_definitions.proto", ] - proto_deps = [ "//components/policy:full_runtime_code_generate" ] - proto_out_dir = "/chrome/browser/privacy" + proto_out_dir = "chrome/browser/privacy" generate_cc = false generate_library = false } proto_library("traffic_annotation_proto") { sources = [ "traffic_annotation.proto" ] - proto_deps = [ ":chrome_settings_full_runtime" ] - import_dirs = [ "$root_gen_dir" + "/components/policy/proto" ] + proto_deps = [ + ":chrome_settings", + ":device_policy_and_policy_common_definitions", + ] + import_dirs = [ + # chrome_settings.proto + "$root_gen_dir" + "/components/policy/proto", + + # chrome_device_policy.proto + "//components/policy/proto", + ] generate_cc = false generate_library = false }
diff --git a/chrome/browser/privacy/traffic_annotation.proto b/chrome/browser/privacy/traffic_annotation.proto index 20b2d38..8b747e2 100644 --- a/chrome/browser/privacy/traffic_annotation.proto +++ b/chrome/browser/privacy/traffic_annotation.proto
@@ -5,13 +5,10 @@ syntax = "proto3"; package traffic_annotation; -// chrome_settings_full_runtime.proto is a version of the following proto -// without lite runtime optimization: -// out/Debug/gen/components/policy/proto/chrome_settings.proto -// -// TODO(crbug.com/1119417): Change this to the non-full-runtime version when -// the C++ auditor is removed. -import "chrome_settings_full_runtime.proto"; +option optimize_for = LITE_RUNTIME; + +import "chrome_settings.proto"; +import "chrome_device_policy.proto"; // Describes a specific kind of network traffic based on a fine-grained // semantic classification of all network traffic generated by Chrome. @@ -211,6 +208,7 @@ TrafficSemantics semantics = 3; + // Next tag: 8 message TrafficPolicy { enum CookiesAllowed { // Do not use this value. It's just a placeholder for default value. @@ -244,10 +242,17 @@ string setting = 3; // Policy configuration(s) that disable or limit this network request. - // This would be a text serialized protobuf of any enterprise policy. + // This would be a text serialized protobuf of any non-device enterprise + // policy. // see out/Debug/gen/components/policy/proto/chrome_settings.proto repeated enterprise_management.ChromeSettingsProto chrome_policy = 4; + // Policy configuration(s) that disable or limit this network request. + // This would be a text serialized protobuf of any device enterprise + // policy. See components/policy/proto/chrome_device_policy.proto. + repeated enterprise_management.ChromeDeviceSettingsProto + chrome_device_policy = 7; + // Justification for not having a policy that disables this feature. string policy_exception_justification = 5;
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc index 2944e103..b7554b16 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
@@ -267,7 +267,6 @@ void PrivacySandboxService::PromptActionOccurred( PrivacySandboxService::PromptAction action) { - InformSentimentService(action); RecordPromptActionMetrics(action); if (base::FeatureList::IsEnabled(privacy_sandbox::kPrivacySandboxSettings4)) { @@ -275,6 +274,7 @@ return; } + InformSentimentService(action); if (PromptAction::kNoticeShown == action && PromptType::kNotice == GetRequiredPromptType()) { // The Privacy Sandbox pref can be enabled when the notice has been @@ -293,6 +293,10 @@ void PrivacySandboxService::PromptActionOccurredM1( PrivacySandboxService::PromptAction action) { + DCHECK( + base::FeatureList::IsEnabled(privacy_sandbox::kPrivacySandboxSettings4)); + + InformSentimentServiceM1(action); if (PromptAction::kNoticeAcknowledge == action || PromptAction::kNoticeOpenSettings == action) { if (privacy_sandbox::kPrivacySandboxSettings4ConsentRequired.Get()) { @@ -1428,6 +1432,38 @@ #endif } +void PrivacySandboxService::InformSentimentServiceM1( + PrivacySandboxService::PromptAction action) { +#if !BUILDFLAG(IS_ANDROID) + if (!sentiment_service_) { + return; + } + + TrustSafetySentimentService::FeatureArea area; + switch (action) { + case PromptAction::kNoticeOpenSettings: + area = TrustSafetySentimentService::FeatureArea:: + kPrivacySandbox4NoticeSettings; + break; + case PromptAction::kNoticeAcknowledge: + area = TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk; + break; + case PromptAction::kConsentAccepted: + area = TrustSafetySentimentService::FeatureArea:: + kPrivacySandbox4ConsentAccept; + break; + case PromptAction::kConsentDeclined: + area = TrustSafetySentimentService::FeatureArea:: + kPrivacySandbox4ConsentDecline; + break; + default: + return; + } + + sentiment_service_->InteractedWithPrivacySandbox4(area); +#endif +} + void PrivacySandboxService::RecordPromptActionMetrics( PrivacySandboxService::PromptAction action) { switch (action) {
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h index 4f9e642..3fab1146 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
@@ -550,6 +550,10 @@ // determined by |action|. Only a subset of actions has a corresponding area. void InformSentimentService(PrivacySandboxService::PromptAction action); + // Equivalent of PrivacySandboxService::InformSentimentService, but for + // PrivacySandboxSettings4. + void InformSentimentServiceM1(PrivacySandboxService::PromptAction action); + // Implementation of PrivacySandboxService::PromptActionOccurred, but for // PrivacySandboxSettings4. virtual void PromptActionOccurredM1(PromptAction action);
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc index f3304ee..39ccb03 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
@@ -3610,6 +3610,51 @@ static_cast<int>(PromptSuppressedReason::kRestricted)}}); } +#if !BUILDFLAG(IS_ANDROID) +TEST_F(PrivacySandboxServiceM1PromptTest, PromptActionsSentimentService) { + // Settings both consent and notice to be true so that we can loop through all + // cases interacting with the sentiment service cleanly, without breaking + // DCHECKs. Other tests / code paths check that PromptActionOccurred is + // working correctly based on notice and consent, and assert that only one is + // enabled. + feature_list()->Reset(); + feature_list()->InitAndEnableFeatureWithParameters( + privacy_sandbox::kPrivacySandboxSettings4, + {{"consent-required", "true"}, {"notice-required", "true"}}); + + std::map<PromptAction, TrustSafetySentimentService::FeatureArea> + expected_feature_areas; + expected_feature_areas = { + {PromptAction::kNoticeOpenSettings, + TrustSafetySentimentService::FeatureArea:: + kPrivacySandbox4NoticeSettings}, + {PromptAction::kNoticeAcknowledge, + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk}, + {PromptAction::kConsentAccepted, + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentAccept}, + {PromptAction::kConsentDeclined, + TrustSafetySentimentService::FeatureArea:: + kPrivacySandbox4ConsentDecline}}; + + for (int enum_value = 0; + enum_value <= static_cast<int>(PromptAction::kMaxValue); ++enum_value) { + auto prompt_action = static_cast<PromptAction>(enum_value); + if (expected_feature_areas.count(prompt_action)) { + EXPECT_CALL( + *mock_sentiment_service(), + InteractedWithPrivacySandbox4(expected_feature_areas[prompt_action])) + .Times(1); + } else { + EXPECT_CALL(*mock_sentiment_service(), + InteractedWithPrivacySandbox4(testing::_)) + .Times(0); + } + privacy_sandbox_service()->PromptActionOccurred(prompt_action); + testing::Mock::VerifyAndClearExpectations(mock_sentiment_service()); + } +} +#endif + class PrivacySandboxServiceM1ConsentPromptTest : public PrivacySandboxServiceM1PromptTest {};
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc index 2aac407b..a801fb8 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.cc
@@ -7,7 +7,9 @@ #include "base/feature_list.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "components/prefs/pref_service.h" #include "components/privacy_sandbox/privacy_sandbox_features.h" +#include "components/privacy_sandbox/privacy_sandbox_prefs.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/tribool.h" @@ -49,3 +51,18 @@ bool PrivacySandboxSettingsDelegate::IsIncognitoProfile() const { return profile_->IsIncognitoProfile(); } + +bool PrivacySandboxSettingsDelegate::HasAppropriateTopicsConsent() const { + // If the profile doesn't require a release 4 consent, then it always has + // an appropriate (i.e. not required) Topics consent. + if (!privacy_sandbox::kPrivacySandboxSettings4ConsentRequired.Get()) { + return true; + } + + // Ideally we could consult the PrivacySandboxService, and centralise this + // logic. However, that service depends on PrivacySandboxSettings, which will + // own this delegate, and so including it here would create a circular + // dependency. + return profile_->GetPrefs()->GetBoolean( + prefs::kPrivacySandboxTopicsConsentGiven); +}
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h index 90b99cf..6eea038 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate.h
@@ -19,6 +19,7 @@ // PrivacySandboxSettings::Delegate: bool IsPrivacySandboxRestricted() const override; bool IsIncognitoProfile() const override; + bool HasAppropriateTopicsConsent() const override; private: raw_ptr<Profile> profile_;
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc index b4d36988..210ca69 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_delegate_unittest.cc
@@ -88,3 +88,46 @@ // don't restrict the feature. EXPECT_FALSE(delegate()->IsPrivacySandboxRestricted()); } + +TEST_F(PrivacySandboxSettingsDelegateTest, + AppropriateTopicsConsent_ConsentNotRequired) { + // When the V4 consent required parameter is not present, Topics always has + // an appropriate level of consent. + prefs()->SetBoolean(prefs::kPrivacySandboxTopicsConsentGiven, false); + feature_list()->InitAndEnableFeature( + privacy_sandbox::kPrivacySandboxSettings4); + + EXPECT_TRUE(delegate()->HasAppropriateTopicsConsent()); + + feature_list()->Reset(); + feature_list()->InitAndEnableFeatureWithParameters( + privacy_sandbox::kPrivacySandboxSettings4, + {{privacy_sandbox::kPrivacySandboxSettings4NoticeRequired.name, "true"}}); + + EXPECT_TRUE(delegate()->HasAppropriateTopicsConsent()); + + feature_list()->Reset(); + feature_list()->InitAndEnableFeatureWithParameters( + privacy_sandbox::kPrivacySandboxSettings3, + {{privacy_sandbox::kPrivacySandboxSettings3ConsentRequired.name, + "true"}}); + + EXPECT_TRUE(delegate()->HasAppropriateTopicsConsent()); +} + +TEST_F(PrivacySandboxSettingsDelegateTest, + AppropriateTopicsConsent_ConsentRequired) { + feature_list()->InitAndEnableFeatureWithParameters( + privacy_sandbox::kPrivacySandboxSettings4, + {{privacy_sandbox::kPrivacySandboxSettings4ConsentRequired.name, + "true"}}); + + // Default state should be a not-active consent. + EXPECT_FALSE(delegate()->HasAppropriateTopicsConsent()); + + prefs()->SetBoolean(prefs::kPrivacySandboxTopicsConsentGiven, true); + EXPECT_TRUE(delegate()->HasAppropriateTopicsConsent()); + + prefs()->SetBoolean(prefs::kPrivacySandboxTopicsConsentGiven, false); + EXPECT_FALSE(delegate()->HasAppropriateTopicsConsent()); +}
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 bfb2186..30de27ed 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -421,7 +421,9 @@ LastTabStandingTrackerFactory::GetInstance(); } #if !BUILDFLAG(IS_ANDROID) +#if !BUILDFLAG(IS_CHROMEOS_LACROS) captions::LiveCaptionControllerFactory::GetInstance(); +#endif if (base::FeatureList::IsEnabled(media::kLiveTranslate)) captions::LiveTranslateControllerFactory::GetInstance(); #endif
diff --git a/chrome/browser/profiles/pref_service_builder_utils.cc b/chrome/browser/profiles/pref_service_builder_utils.cc index c0a80d56..895c7a06 100644 --- a/chrome/browser/profiles/pref_service_builder_utils.cc +++ b/chrome/browser/profiles/pref_service_builder_utils.cc
@@ -37,9 +37,9 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) #include "chrome/browser/content_settings/content_settings_supervised_provider.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif namespace {
diff --git a/chrome/browser/profiles/profile_attributes_entry.cc b/chrome/browser/profiles/profile_attributes_entry.cc index a7365fc..22b014dd 100644 --- a/chrome/browser/profiles/profile_attributes_entry.cc +++ b/chrome/browser/profiles/profile_attributes_entry.cc
@@ -37,7 +37,7 @@ #include "ui/native_theme/native_theme.h" #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc index 3921fb2..5a3d8e4d6 100644 --- a/chrome/browser/profiles/profile_attributes_storage.cc +++ b/chrome/browser/profiles/profile_attributes_storage.cc
@@ -32,13 +32,13 @@ #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/account_id/account_id.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/profile_metrics/state.h" #include "components/signin/public/base/persistent_repeating_timer.h" #include "components/signin/public/base/signin_pref_names.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "third_party/icu/source/i18n/unicode/coll.h" @@ -233,8 +233,10 @@ // TODO(crbug.com/1060113): Replace this check by // !entry->GetHostedDomain().has_value() in M84 (once the attributes storage // gets reasonably well populated). - if (policy::BrowserPolicyConnector::IsNonEnterpriseUser( - base::UTF16ToUTF8(entry->GetUserName()))) { + if (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + base::UTF16ToUTF8(entry->GetUserName())) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise) { return profile_metrics::UnconsentedPrimaryAccountType::kConsumer; } // TODO(crbug.com/1060113): Figure out how to distinguish EDU accounts from
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc index 58d4226..44955fe 100644 --- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc +++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -25,13 +25,13 @@ #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/signin_util.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" #include "components/profile_metrics/state.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync_preferences/pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index c786f8a..1340e75 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -238,9 +238,9 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) #include "chrome/browser/content_settings/content_settings_supervised_provider.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/profiles/profile_keyed_service_browsertest.cc b/chrome/browser/profiles/profile_keyed_service_browsertest.cc index a0fd4d7..8f7fbaf 100644 --- a/chrome/browser/profiles/profile_keyed_service_browsertest.cc +++ b/chrome/browser/profiles/profile_keyed_service_browsertest.cc
@@ -210,6 +210,8 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) "CleanupManagerLacros", "DownloadCoreService", +#else + "LiveCaptionController", #endif // BUILDFLAG(IS_CHROMEOS_LACROS) "AlarmManager", "BackgroundContentsService", @@ -227,7 +229,6 @@ "HidDeviceManager", "HostContentSettingsMap", "LastTabStandingTrackerKeyedService", - "LiveCaptionController", "MediaRouterUIService", "NotificationDisplayService", "OptimizationGuideKeyedService",
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 5ad18f99..4f6dd06 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -110,9 +110,9 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) #include "chrome/browser/supervised_user/child_accounts/child_account_service.h" #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc index 4967a08..3aff1e0 100644 --- a/chrome/browser/profiles/profile_manager_browsertest.cc +++ b/chrome/browser/profiles/profile_manager_browsertest.cc
@@ -64,10 +64,10 @@ #endif #if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/lacros/lacros_test_helper.h" #include "chromeos/startup/browser_init_params.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/test/test_launcher.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc index 4f74aab..d7dc16fc 100644 --- a/chrome/browser/profiles/profile_manager_unittest.cc +++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -90,7 +90,7 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif using base::ASCIIToUTF16;
diff --git a/chrome/browser/profiles/profile_test_util.cc b/chrome/browser/profiles/profile_test_util.cc index 052a904..59f6593 100644 --- a/chrome/browser/profiles/profile_test_util.cc +++ b/chrome/browser/profiles/profile_test_util.cc
@@ -15,7 +15,7 @@ #if !BUILDFLAG(IS_ANDROID) #include "chrome/browser/profiles/profile_window.h" -#include "components/policy/core/browser/browser_policy_connector.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "testing/gtest/include/gtest/gtest.h" #endif // BUILDFLAG(IS_ANDROID) @@ -40,12 +40,12 @@ ScopedNonEnterpriseDomainSetterForTesting:: ScopedNonEnterpriseDomainSetterForTesting(const char* domain) { - policy::BrowserPolicyConnector::SetNonEnterpriseDomainForTesting(domain); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting(domain); } ScopedNonEnterpriseDomainSetterForTesting:: ~ScopedNonEnterpriseDomainSetterForTesting() { - policy::BrowserPolicyConnector::SetNonEnterpriseDomainForTesting(nullptr); + signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting(nullptr); } #endif // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index fa8868a..1adc64e6 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -122,10 +122,10 @@ #include "ui/gfx/codec/png_codec.h" #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
diff --git a/chrome/browser/resources/app_home/app_item.html b/chrome/browser/resources/app_home/app_item.html index 54c5cc5..4913e58e 100644 --- a/chrome/browser/resources/app_home/app_item.html +++ b/chrome/browser/resources/app_home/app_item.html
@@ -32,6 +32,6 @@ </style> <div class="icon-container"> - <img src="[[appInfo.iconUrl.url]]" class="icon-image" alt="App's icon"></img> + <img src="[[getIconUrl_(appInfo)]]" class="icon-image" alt="App's icon"></img> </div> <div class="text-container">[[appInfo.name]]</div>
diff --git a/chrome/browser/resources/app_home/app_item.ts b/chrome/browser/resources/app_home/app_item.ts index 81c80b8..0775601 100644 --- a/chrome/browser/resources/app_home/app_item.ts +++ b/chrome/browser/resources/app_home/app_item.ts
@@ -43,6 +43,17 @@ this.dispatchEvent( new CustomEvent(eventName, {bubbles: true, composed: true, detail})); } + + private getIconUrl_() { + const url = new URL(this.appInfo.iconUrl.url); + // For web app, the backend serves grayscale image when the app is not + // locally installed automatically and doesn't recognize this query param, + // but we add a query param here to force browser to refetch the image. + if (!this.appInfo.isLocallyInstalled) { + url.searchParams.append('grayscale', 'true'); + } + return url; + } } declare global {
diff --git a/chrome/browser/resources/app_home/app_list.html b/chrome/browser/resources/app_home/app_list.html index 23b4004..12f38677 100644 --- a/chrome/browser/resources/app_home/app_list.html +++ b/chrome/browser/resources/app_home/app_list.html
@@ -41,7 +41,7 @@ <cr-action-menu id="menu" hidden="{{!selectedActionMenuModel_}}"> <div id="open-in-window" tabindex="0" class="dropdown-item" on-click="onOpenInWindowItemClick_" - hidden="[[isOpenInWindowHidden_(selectedActionMenuModel_)]]"> + hidden="[[!isLocallyInstalled_(selectedActionMenuModel_)]]"> <div class="dropdown-item-label"> $i18n{appWindowOpenLabel} </div> @@ -65,16 +65,23 @@ </cr-checkbox> </div> <button id="create-shortcut" class="dropdown-item" - on-click="onCreateShortcutItemClick_"> + on-click="onCreateShortcutItemClick_" + hidden="[[!isLocallyInstalled_(selectedActionMenuModel_)]]"> $i18n{createShortcutForAppLabel} </button> + <button id="install-locally" class="dropdown-item" + on-click="onInstallLocallyItemClick_" + hidden="[[isLocallyInstalled_(selectedActionMenuModel_)]]"> + $i18n{installLocallyLabel} + </button> <hr> <button id="uninstall" class="dropdown-item" on-click="onUninstallItemClick_"> $i18n{uninstallAppLabel} </button> <button id="app-settings" class="dropdown-item" - on-click="onAppSettingsItemClick_"> + on-click="onAppSettingsItemClick_" + hidden="[[!isLocallyInstalled_(selectedActionMenuModel_)]]"> $i18n{appSettingsLabel} </button> </cr-action-menu>
diff --git a/chrome/browser/resources/app_home/app_list.ts b/chrome/browser/resources/app_home/app_list.ts index 3acfd1d..37f2046 100644 --- a/chrome/browser/resources/app_home/app_list.ts +++ b/chrome/browser/resources/app_home/app_list.ts
@@ -111,10 +111,10 @@ } } - private isOpenInWindowHidden_() { + private isLocallyInstalled_() { return this.selectedActionMenuModel_ ? - !this.selectedActionMenuModel_.appInfo.mayShowOpenInWindow : - true; + this.selectedActionMenuModel_.appInfo.isLocallyInstalled : + false; } private isLaunchOnStartupHidden_() { @@ -173,6 +173,14 @@ this.closeMenu_(); } + private onInstallLocallyItemClick_() { + if (this.selectedActionMenuModel_?.appInfo.id) { + BrowserProxy.getInstance().handler.installAppLocally( + this.selectedActionMenuModel_?.appInfo.id); + } + this.closeMenu_(); + } + private onUninstallItemClick_() { if (this.selectedActionMenuModel_?.appInfo.id) { BrowserProxy.getInstance().handler.uninstallApp(
diff --git a/chrome/browser/resources/bluetooth_internals/BUILD.gn b/chrome/browser/resources/bluetooth_internals/BUILD.gn index a8d85f75..c958fbf 100644 --- a/chrome/browser/resources/bluetooth_internals/BUILD.gn +++ b/chrome/browser/resources/bluetooth_internals/BUILD.gn
@@ -8,32 +8,8 @@ import("//ui/webui/resources/tools/generate_grd.gni") bluetooth_grd_prefix = "bluetooth_internals" -public_mojo_grdp_file = "$target_gen_dir/public_mojo_resources.grdp" -internals_mojo_grdp_file = "$target_gen_dir/internals_mojo_resources.grdp" resources_grd_file = "$target_gen_dir/resources.grd" -generate_grd("build_public_mojo_grdp") { - grd_prefix = bluetooth_grd_prefix - out_grd = public_mojo_grdp_file - input_files = [ - "adapter.mojom-webui.js", - "uuid.mojom-webui.js", - "device.mojom-webui.js", - ] - input_files_base_dir = - rebase_path("$root_gen_dir/mojom-webui/device/bluetooth/public/mojom/", - root_build_dir) -} - -generate_grd("build_internal_mojo_grdp") { - grd_prefix = bluetooth_grd_prefix - out_grd = internals_mojo_grdp_file - input_files = [ "bluetooth_internals.mojom-webui.js" ] - input_files_base_dir = rebase_path( - "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/bluetooth_internals/", - root_build_dir) -} - html_files = [ "characteristic_list_item.html", "descriptor_list_item.html", @@ -85,6 +61,28 @@ "value_control.js", ] +mojom_files = [ + "adapter.mojom-webui.ts", + "bluetooth_internals.mojom-webui.ts", + "device.mojom-webui.ts", + "uuid.mojom-webui.js", +] + +copy("copy_mojom") { + deps = [ + "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_ts__generator", + "//device/bluetooth/public/mojom:deprecated_experimental_interfaces_ts__generator", + "//device/bluetooth/public/mojom:mojom_js__generator", + ] + sources = [ + "$root_gen_dir/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals.mojom-webui.ts", + "$root_gen_dir/device/bluetooth/public/mojom/adapter.mojom-webui.ts", + "$root_gen_dir/device/bluetooth/public/mojom/device.mojom-webui.ts", + "$root_gen_dir/mojom-webui/device/bluetooth/public/mojom/uuid.mojom-webui.js", + ] + outputs = [ "$target_gen_dir/{{source_file_part}}" ] +} + copy("copy_files") { sources = js_files outputs = [ "${target_gen_dir}/{{source_file_part}}" ] @@ -98,10 +96,11 @@ root_dir = target_gen_dir out_dir = "$target_gen_dir/tsc" tsconfig_base = "tsconfig_base.json" - in_files = js_files + html_wrapper_files + in_files = js_files + html_wrapper_files + mojom_files deps = [ "//ui/webui/resources:library" ] extra_deps = [ ":copy_files", + ":copy_mojom", ":html_wrapper_files", ] } @@ -110,12 +109,7 @@ enable_input_discovery_for_gn_analyze = false source = resources_grd_file - deps = [ - ":build_grd", - "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js", - "//device/bluetooth/public/mojom:deprecated_experimental_interfaces_js", - "//device/bluetooth/public/mojom:mojom_js", - ] + deps = [ ":build_grd" ] outputs = [ "grit/bluetooth_internals_resources.h", @@ -129,11 +123,7 @@ generate_grd("build_grd") { grd_prefix = bluetooth_grd_prefix out_grd = resources_grd_file - deps = [ - ":build_internal_mojo_grdp", - ":build_public_mojo_grdp", - ":build_ts", - ] + deps = [ ":build_ts" ] input_files = [ "bluetooth_internals.css", "bluetooth_internals.html", @@ -141,11 +131,6 @@ ] input_files_base_dir = rebase_path(".", "//") - grdp_files = [ - public_mojo_grdp_file, - internals_mojo_grdp_file, - ] - manifest_files = filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ]) }
diff --git a/chrome/browser/resources/bluetooth_internals/adapter_broker.js b/chrome/browser/resources/bluetooth_internals/adapter_broker.js index 1da2ab4a..7a627d2 100644 --- a/chrome/browser/resources/bluetooth_internals/adapter_broker.js +++ b/chrome/browser/resources/bluetooth_internals/adapter_broker.js
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {AdapterInfo, AdapterObserverInterface, AdapterObserverReceiver, AdapterRemote, ConnectResult, DiscoverySessionRemote} from './adapter.mojom-webui.js'; +import {AdapterObserverReceiver, AdapterRemote, ConnectResult, DiscoverySessionRemote} from './adapter.mojom-webui.js'; import {BluetoothInternalsHandler, BluetoothInternalsHandlerRemote} from './bluetooth_internals.mojom-webui.js'; -import {Device, DeviceInfo, DeviceRemote} from './device.mojom-webui.js'; +import {Device, DeviceRemote} from './device.mojom-webui.js'; const SCAN_CLIENT_NAME = 'Bluetooth Internals Page';
diff --git a/chrome/browser/resources/bluetooth_internals/adapter_page.js b/chrome/browser/resources/bluetooth_internals/adapter_page.js index 62986e4..9330835 100644 --- a/chrome/browser/resources/bluetooth_internals/adapter_page.js +++ b/chrome/browser/resources/bluetooth_internals/adapter_page.js
@@ -10,7 +10,6 @@ import {$} from 'chrome://resources/js/util_ts.js'; -import {AdapterInfo} from './adapter.mojom-webui.js'; import {Page} from './page.js'; const PROPERTY_NAMES = {
diff --git a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js index f9e0d3c..fdecd4d 100644 --- a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js +++ b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
@@ -15,7 +15,6 @@ import {AdapterPage} from './adapter_page.js'; import {BluetoothInternalsHandler, BluetoothInternalsHandlerRemote} from './bluetooth_internals.mojom-webui.js'; import {DebugLogPage} from './debug_log_page.js'; -import {DeviceInfo} from './device.mojom-webui.js'; import {DeviceCollection} from './device_collection.js'; import {DeviceDetailsPage} from './device_details_page.js'; import {DevicesPage, ScanStatus} from './devices_page.js'; @@ -24,6 +23,7 @@ import {showSnackbar, SnackbarType} from './snackbar.js'; + // Expose for testing. /** @type {AdapterBroker} */ export let adapterBroker = null;
diff --git a/chrome/browser/resources/bluetooth_internals/characteristic_list_item.js b/chrome/browser/resources/bluetooth_internals/characteristic_list_item.js index 93a08b7..c95ad721 100644 --- a/chrome/browser/resources/bluetooth_internals/characteristic_list_item.js +++ b/chrome/browser/resources/bluetooth_internals/characteristic_list_item.js
@@ -10,7 +10,7 @@ import {CustomElement} from 'chrome://resources/js/custom_element.js'; import {getTemplate} from './characteristic_list_item.html.js'; -import {CharacteristicInfo, Property} from './device.mojom-webui.js'; +import {Property} from './device.mojom-webui.js'; /** Property names for the CharacteristicInfo fieldset */ const INFO_PROPERTY_NAMES = {
diff --git a/chrome/browser/resources/bluetooth_internals/descriptor_list_item.js b/chrome/browser/resources/bluetooth_internals/descriptor_list_item.js index cc08312..b252b18 100644 --- a/chrome/browser/resources/bluetooth_internals/descriptor_list_item.js +++ b/chrome/browser/resources/bluetooth_internals/descriptor_list_item.js
@@ -9,7 +9,6 @@ import {CustomElement} from 'chrome://resources/js/custom_element.js'; import {getTemplate} from './descriptor_list_item.html.js'; -import {DescriptorInfo} from './device.mojom-webui.js'; /** Property names for the DescriptorInfo fieldset */ const INFO_PROPERTY_NAMES = {
diff --git a/chrome/browser/resources/bluetooth_internals/device_collection.js b/chrome/browser/resources/bluetooth_internals/device_collection.js index 346a65d..a6fb9b06 100644 --- a/chrome/browser/resources/bluetooth_internals/device_collection.js +++ b/chrome/browser/resources/bluetooth_internals/device_collection.js
@@ -9,8 +9,6 @@ import {assert} from 'chrome://resources/js/assert_ts.js'; -import {DeviceInfo} from './device.mojom-webui.js'; - /** * Enum of connection status for a device. * @enum {number}
diff --git a/chrome/browser/resources/bluetooth_internals/device_details_page.js b/chrome/browser/resources/bluetooth_internals/device_details_page.js index d12d06fd..bd9f8ba 100644 --- a/chrome/browser/resources/bluetooth_internals/device_details_page.js +++ b/chrome/browser/resources/bluetooth_internals/device_details_page.js
@@ -13,7 +13,7 @@ import {$} from 'chrome://resources/js/util_ts.js'; -import {DeviceInfo, DeviceRemote, ServiceInfo} from './device.mojom-webui.js'; +import {DeviceRemote} from './device.mojom-webui.js'; import {connectToDevice} from './device_broker.js'; import {ConnectionStatus} from './device_collection.js'; import {formatManufacturerDataMap, formatServiceUuids} from './device_utils.js';
diff --git a/chrome/browser/resources/bluetooth_internals/device_table.js b/chrome/browser/resources/bluetooth_internals/device_table.js index 14a92eb4..f423d1a 100644 --- a/chrome/browser/resources/bluetooth_internals/device_table.js +++ b/chrome/browser/resources/bluetooth_internals/device_table.js
@@ -8,7 +8,6 @@ import {assert} from 'chrome://resources/js/assert_ts.js'; import {CustomElement} from 'chrome://resources/js/custom_element.js'; -import {DeviceInfo} from './device.mojom-webui.js'; import {DeviceCollection} from './device_collection.js'; import {getTemplate} from './device_table.html.js'; import {formatManufacturerDataMap, formatServiceUuids} from './device_utils.js';
diff --git a/chrome/browser/resources/bluetooth_internals/devices_page.js b/chrome/browser/resources/bluetooth_internals/devices_page.js index bfe88db..431b3a5 100644 --- a/chrome/browser/resources/bluetooth_internals/devices_page.js +++ b/chrome/browser/resources/bluetooth_internals/devices_page.js
@@ -8,7 +8,6 @@ */ import './device_table.js'; -import {DeviceInfo} from './device.mojom-webui.js'; import {DeviceCollection} from './device_collection.js'; import {Page} from './page.js';
diff --git a/chrome/browser/resources/bluetooth_internals/service_list_item.js b/chrome/browser/resources/bluetooth_internals/service_list_item.js index a6501aa5..2e78c35 100644 --- a/chrome/browser/resources/bluetooth_internals/service_list_item.js +++ b/chrome/browser/resources/bluetooth_internals/service_list_item.js
@@ -8,7 +8,6 @@ import {CustomElement} from 'chrome://resources/js/custom_element.js'; -import {ServiceInfo} from './device.mojom-webui.js'; import {getTemplate} from './service_list_item.html.js'; /**
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js index df7ded4..6a67411 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js
@@ -374,19 +374,20 @@ * @return {!Promise} */ async waitForUIProperties(targetProps) { - // Poll until the updateDictationBubble() API gets called with - // `targetProps`. - return new Promise(resolve => { - const printErrorMessageTimeoutId = setTimeout(() => { - this.printErrorMessage_(targetProps); - }, 3.5 * 1000); - const intervalId = setInterval(() => { + if (this.uiPropertiesMatch_(targetProps)) { + return; + } + + await new Promise(resolve => { + const onUpdateDictationBubble = () => { if (this.uiPropertiesMatch_(targetProps)) { - clearTimeout(printErrorMessageTimeoutId); - clearInterval(intervalId); + this.mockAccessibilityPrivate.removeUpdateDictationBubbleListener(); resolve(); } - }, 100); + }; + + this.mockAccessibilityPrivate.addUpdateDictationBubbleListener( + onUpdateDictationBubble); }); } @@ -427,18 +428,6 @@ } /** - * @param {DictationBubbleProperties} props - * @private - */ - printErrorMessage_(props) { - console.error(`Still waiting for UI properties - visible: ${props.visible} - icon: ${props.icon} - text: ${props.text} - hints: ${props.hints}`); - } - - /** * Always allows Dictation commands, even if the Dictation locale and browser * locale differ. Only used for testing. */
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js index 4291230f..1c34e48 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler.js
@@ -29,9 +29,10 @@ /** @private {?function(): void} */ this.onActiveChangedForTesting_ = null; - /** @private {?function(): void} */ this.onEditableNodeChangedForTesting_ = null; + /** @private {?function(): void} */ + this.onFocusChangedForTesting_ = null; } /** @@ -96,6 +97,10 @@ } this.setEditableNode_(node); + + if (this.onFocusChangedForTesting_) { + this.onFocusChangedForTesting_(); + } } /** @return {?AutomationNode} */
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler_test.js index 8d19db6..1d98645 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/focus_handler_test.js
@@ -29,13 +29,24 @@ * @return {!Promise} */ async waitForFocusHandlerActive(active) { - return new Promise(resolve => { - const intervalId = setInterval(() => { - if (this.getFocusHandler().active_ === active) { - clearInterval(intervalId); + const focusHandler = this.getFocusHandler(); + const activeOk = () => { + return focusHandler.active_ === active; + }; + + if (activeOk()) { + return; + } + + await new Promise(resolve => { + const onActiveChanged = () => { + if (activeOk()) { + focusHandler.onActiveChangedForTesting_ = null; resolve(); } - }, 100); + }; + + focusHandler.onActiveChangedForTesting_ = onActiveChanged; }); } @@ -44,13 +55,24 @@ * @return {!Promise} */ async waitForFocus(target) { - return new Promise(resolve => { - const intervalId = setInterval(() => { - if (this.getFocusHandler().editableNode_ === target) { - clearInterval(intervalId); + const focusHandler = this.getFocusHandler(); + const isTargetFocused = () => { + return focusHandler.editableNode_ === target; + }; + + if (isTargetFocused()) { + return; + } + + await new Promise(resolve => { + const onFocusChanged = () => { + if (isTargetFocused()) { + focusHandler.onFocusChangedForTesting_ = null; resolve(); } - }, 100); + }; + + focusHandler.onFocusChangedForTesting_ = onFocusChanged; }); }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/dictation_pumpkin_parse_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/dictation_pumpkin_parse_test.js index 7e675ca..a37a63d 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/dictation_pumpkin_parse_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/parse/dictation_pumpkin_parse_test.js
@@ -19,6 +19,9 @@ await importModule( 'SpeechParser', '/accessibility_common/dictation/parse/speech_parser.js'); + await importModule( + 'SUPPORTED_LOCALES', + '/accessibility_common/dictation/parse/pumpkin/pumpkin_constants.js'); await super.setUpDeferred(); @@ -29,19 +32,35 @@ /** * @return {!Promise} + * @param {string=} locale An optional locale. If the locale is provided, + * this method will wait for Pumpkin to initialize in that locale. If the + * locale isn't provided, then this method will wait for Pumpkin to + * initialize in any locale. * @private */ - async waitForPumpkinParseStrategy_() { + async waitForPumpkinParseStrategy_(locale) { const strategy = this.getPumpkinParseStrategy(); - // TODO(crbug.com/1258190): Consider adding an observer or callback and - // remove the polling below. - return new Promise(resolve => { - const intervalId = setInterval(() => { - if (strategy.pumpkinTaggerReady_) { - clearInterval(intervalId); + const isReady = () => { + let localeOk = true; + if (locale) { + const pumpkinLocale = SUPPORTED_LOCALES[locale] || null; + localeOk = pumpkinLocale === strategy.locale_; + } + + return localeOk && strategy.pumpkinTaggerReady_; + }; + + if (isReady()) { + return; + } + + await new Promise(resolve => { + strategy.onPumpkinTaggerReadyChangedForTesting_ = () => { + if (isReady()) { + strategy.onPumpkinTaggerReadyChangedForTesting_ = null; resolve(); } - }, 300); + }; }); } }; @@ -199,7 +218,7 @@ ]; for (const {locale, testCase} of testCases) { await this.setPref(Dictation.DICTATION_LOCALE_PREF, locale); - await this.waitForPumpkinParseStrategy_(); + await this.waitForPumpkinParseStrategy_(locale); await this.runPumpkinParseTestCase(testCase); } }); @@ -208,13 +227,15 @@ await this.waitForPumpkinParseStrategy_(); this.alwaysEnableCommands(); await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'ja'); + // Don't pass in a locale below because 'ja' is an unsupported locale (and + // thus Pumpkin will never initialize in that locale). await this.waitForPumpkinParseStrategy_(); await this.runPumpkinParseTestCase( new ParseTestCase('copy selected text', {})); // Would produce an UNDO_TEXT_EDIT macro if Japanese was supported. await this.runPumpkinParseTestCase(new ParseTestCase('もとどおりにする', {})); await this.setPref(Dictation.DICTATION_LOCALE_PREF, 'en-US'); - await this.waitForPumpkinParseStrategy_(); + await this.waitForPumpkinParseStrategy_('en-US'); await this.runPumpkinParseTestCase( new ParseTestCase('copy selected text', {name: 'COPY_SELECTED_TEXT'})); });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js index 2b2971a..f04ee2a 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -737,7 +737,9 @@ target.className === 'PasswordPopupSuggestionView' || target.className === 'AutofillPopupFooterView' || target.className === 'AutofillPopupWarningView' || - target.className === 'AutofillPopupBaseView') { + target.className === 'AutofillPopupBaseView' || + target.className === + 'PasswordGenerationPopupViewViews::GeneratedPasswordBox') { override = true; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js index dc3553a..b37b6ab 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
@@ -194,7 +194,6 @@ 'speakTextUnderMouse': false, 'sticky': false, 'typingEcho': 0, - 'useClassic': false, 'usePitchChanges': true, 'useVerboseMode': true,
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js index 8c2c54e..09f4038 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_accessibility_private.js
@@ -108,6 +108,9 @@ */ this.dictationBubbleProps_ = null; + /** @private {Function} */ + this.onUpdateDictationBubble_ = null; + /** @private {Set<string>} */ this.enabledFeatures_ = new Set(); @@ -381,9 +384,21 @@ return this.dictationActivated_; } + /** @param {!Function} listener */ + addUpdateDictationBubbleListener(listener) { + this.onUpdateDictationBubble_ = listener; + } + + removeUpdateDictationBubbleListener() { + this.onUpdateDictationBubble_ = null; + } + /** @param {!chrome.accessibilityPrivate.DictationBubbleProperties} props */ updateDictationBubble(props) { this.dictationBubbleProps_ = props; + if (this.onUpdateDictationBubble_) { + this.onUpdateDictationBubble_(); + } } /** @return {!chrome.accessibilityPrivate.DictationBubbleProperties|null} */
diff --git a/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn index 891f6fd..798de1b 100644 --- a/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/login/BUILD.gn
@@ -50,6 +50,7 @@ "../../components/behaviors:oobe_dialog_host_behavior", "../../components/behaviors:oobe_i18n_behavior", "../../components/dialogs:oobe_adaptive_dialog", + "../../components/dialogs:oobe_loading_dialog", ] extra_deps = [ ":web_components" ] }
diff --git a/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.html b/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.html index 421d2c6d..4794c743 100644 --- a/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.html +++ b/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.html
@@ -8,8 +8,21 @@ #description-body { margin: 8px 0 8px 0; } + div.warning { + border-bottom: var(--cr-separator-line); + padding-bottom: 11px; + padding-top: 22px; + } + .warning-message { + margin-inline-start: 20px; + } </style> +<oobe-loading-dialog id="loading-dialog" for-step="loading" role="dialog" + title-key="loadingDialogTitle"> + <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> +</oobe-loading-dialog> + <oobe-adaptive-dialog id="welcome-dialog" for-step="welcome" role="dialog"> <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> <h1 slot="title">[[i18nDynamic(locale, 'welcomeScreenTitle')]]</h1> @@ -20,6 +33,15 @@ <div id="description-body"> [[i18nDynamic(locale, 'welcomeScreenDescriptionBody')]] </div> + <div class="message-container"> + <div class="warning" hidden="[[hasEnoughFreeDiskSpace]]"> + <iron-icon slot="icon" icon="oobe-32:warning"></iron-icon> + <span class="warning-message"> + [[i18nDynamic(locale, 'notEnoughFreeDiskSpaceMessage', + requiredFreeDiskSpaceInString)]] + </span> + </div> + </div> </div> <div slot="bottom-buttons"> <oobe-text-button id="skip-button" @@ -27,6 +49,7 @@ text-key="skipButtonLabel"> </oobe-text-button> <oobe-text-button inverse id="update-button" + disabled="[[!hasEnoughFreeDiskSpace]]" on-click="onUpdateButtonClicked_" text-key="updateButtonLabel"> </oobe-text-button>
diff --git a/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.js b/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.js index d8e5fcd0..b035d53 100644 --- a/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.js +++ b/chrome/browser/resources/chromeos/login/screens/login/arc_vm_data_migration.js
@@ -10,6 +10,7 @@ import '//resources/polymer/v3_0/paper-styles/color.js'; import '../../components/common_styles/oobe_dialog_host_styles.css.js'; import '../../components/dialogs/oobe_adaptive_dialog.js'; +import '../../components/dialogs/oobe_loading_dialog.js'; import '../../components/oobe_icons.html.js'; import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -22,6 +23,7 @@ // Keep in sync with ArcVmDataMigrationScreenView::UIState. var ArcVmDataMigrationUIState = { + LOADING: 'loading', WELCOME: 'welcome', }; @@ -57,15 +59,20 @@ } static get properties() { - return {}; + return { + hasEnoughFreeDiskSpace: Boolean, + requiredFreeDiskSpaceInString: String, + }; } constructor() { super(); + this.hasEnoughFreeDiskSpace = true; + this.requiredFreeDiskSpaceInString = ''; } defaultUIStep() { - return ArcVmDataMigrationUIState.WELCOME; + return ArcVmDataMigrationUIState.LOADING; } get UI_STEPS() { @@ -75,6 +82,7 @@ get EXTERNAL_API() { return [ 'setUIState', + 'setRequiredFreeDiskSpace', ]; } @@ -91,6 +99,11 @@ this.setUIStep(Object.values(ArcVmDataMigrationUIState)[state]); } + setRequiredFreeDiskSpace(requiredFreeDiskSpaceInString) { + this.hasEnoughFreeDiskSpace = false; + this.requiredFreeDiskSpaceInString = requiredFreeDiskSpaceInString; + } + onSkipButtonClicked_() { this.userActed(ArcVmDataMigrationUserAction.SKIP); }
diff --git a/chrome/browser/resources/nearby_share/shared/nearby_share_settings_behavior.js b/chrome/browser/resources/nearby_share/shared/nearby_share_settings_behavior.js index 67f7114..e571ff6 100644 --- a/chrome/browser/resources/nearby_share/shared/nearby_share_settings_behavior.js +++ b/chrome/browser/resources/nearby_share/shared/nearby_share_settings_behavior.js
@@ -189,4 +189,6 @@ /** @type {!NearbySettings} */ this.settings; } + + onSettingsRetrieved() {} }
diff --git a/chrome/browser/resources/password_manager/checkup_details_section.html b/chrome/browser/resources/password_manager/checkup_details_section.html index 56c956c..08a40d2 100644 --- a/chrome/browser/resources/password_manager/checkup_details_section.html +++ b/chrome/browser/resources/password_manager/checkup_details_section.html
@@ -43,6 +43,10 @@ #insecureCredentials { margin-top: 24px; } + + iron-icon.policy-disabled { + margin-inline-start: var(--cr-controlled-by-spacing); + } </style> <div id="header"> <cr-icon-button class="icon-arrow-back" id="backButton" @@ -63,7 +67,9 @@ <template id="insecureCredentials" is="dom-repeat" items="[[shownInsecureCredentials_]]" initial-count="50"> <checkup-list-item item="[[item]]" first="[[!index]]" - show-details="[[isCompromisedSection(insecurityType_)]]"> + show-details="[[isCompromisedSection(insecurityType_)]]" + on-more-actions-click="onMoreActionsClick_" + group="[[getCurrentGroup_(item.id, groups_)]]"> </checkup-list-item> </template> <template is="dom-if" if="[[mutedCompromisedCredentials_.length]]"> @@ -76,10 +82,38 @@ opened="[[mutedLeakedCredentialsExpanded_]]"> <template is="dom-repeat" items="[[mutedCompromisedCredentials_]]"> <checkup-list-item item="[[item]]" first="[[!index]]" - show-details="[[isCompromisedSection(insecurityType_)]]"> + show-details="[[isCompromisedSection(insecurityType_)]]" + on-more-actions-click="onMoreActionsClick_" + group="[[getCurrentGroup_(item.id, groups_)]]"> </checkup-list-item> </template> </iron-collapse> </template> </template> <!-- TODO(crbug.com/1401001): Display reused credentials --> +<cr-action-menu id="moreActionsMenu" role-description="$i18n{menu}" + accessibility-label="$i18n{moreActions}"> + <button id="menuShowPassword" class="dropdown-item" + on-click="onMenuShowPasswordClick_"> + [[getShowHideTitle_(activeListItem_)]] + </button> + <button id="menuEditPassword" class="dropdown-item" + on-click="onEditPasswordClick_"> + $i18n{editPassword} + </button> + <button id="menuRemovePassword" class="dropdown-item" + on-click="onMenuRemovePasswordClick_"> + $i18n{deletePassword} + </button> + <template is="dom-if" if="[[isCompromisedSection(insecurityType_)]]"> + <button id="menuMuteUnmuteButton" class="dropdown-item" + on-click="onMenuMuteUnmuteClick_" + disabled="[[isMutingDisabledByPrefs_(pref)]]"> + [[getMuteUnmuteLabel_(activeListItem_)]] + <template is="dom-if" if="[[isMutingDisabledByPrefs_(pref)]]" restamp> + <iron-icon icon="cr20:domain" class="policy-disabled"> + </iron-icon> + </template> + </button> + </template> +</cr-action-menu>
diff --git a/chrome/browser/resources/password_manager/checkup_details_section.ts b/chrome/browser/resources/password_manager/checkup_details_section.ts index b63384d..9d7946f 100644 --- a/chrome/browser/resources/password_manager/checkup_details_section.ts +++ b/chrome/browser/resources/password_manager/checkup_details_section.ts
@@ -1,30 +1,38 @@ // 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. +import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js'; import './shared_style.css.js'; import './checkup_list_item.js'; +import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './checkup_details_section.html.js'; -import {CredentialsChangedListener, PasswordManagerImpl} from './password_manager_proxy.js'; +import {CheckupListItemElement} from './checkup_list_item.js'; +import {CredentialsChangedListener, PasswordCheckInteraction, PasswordManagerImpl} from './password_manager_proxy.js'; +import {PrefMixin} from './prefs/pref_mixin.js'; import {CheckupSubpage, Page, Route, RouteObserverMixin, Router} from './router.js'; export interface CheckupDetailsSectionElement { $: { - subtitle: HTMLElement, description: HTMLElement, + moreActionsMenu: CrActionMenuElement, + menuShowPassword: HTMLButtonElement, + menuEditPassword: HTMLButtonElement, + menuRemovePassword: HTMLButtonElement, + subtitle: HTMLElement, }; } const CheckupDetailsSectionElementBase = - I18nMixin(RouteObserverMixin(PolymerElement)); + PrefMixin(I18nMixin(RouteObserverMixin(PolymerElement))); export class CheckupDetailsSectionElement extends CheckupDetailsSectionElementBase { @@ -59,20 +67,34 @@ private pageTitle_: string; private insecurityType_: CheckupSubpage|undefined; + private groups_: chrome.passwordsPrivate.CredentialGroup[] = []; private allInsecureCredentials_: chrome.passwordsPrivate.PasswordUiEntry[]; private shownInsecureCredentials_: chrome.passwordsPrivate.PasswordUiEntry[]; private mutedCompromisedCredentials_: chrome.passwordsPrivate.PasswordUiEntry[]; + private activeListItem_: CheckupListItemElement|null; private insecureCredentialsChangedListener_: CredentialsChangedListener|null = null; + constructor() { + super(); + this.prefKey = 'profile.password_dismiss_compromised_alert'; + } + override connectedCallback() { super.connectedCallback(); - this.insecureCredentialsChangedListener_ = insecureCredentials => { - this.allInsecureCredentials_ = insecureCredentials; + const updateGroups = () => { + PasswordManagerImpl.getInstance().getCredentialGroups().then( + groups => this.groups_ = groups); }; + this.insecureCredentialsChangedListener_ = insecureCredentials => { + this.allInsecureCredentials_ = insecureCredentials; + updateGroups(); + }; + + updateGroups(); PasswordManagerImpl.getInstance().getInsecureCredentials().then( this.insecureCredentialsChangedListener_); PasswordManagerImpl.getInstance().addInsecureCredentialsListener( @@ -150,6 +172,57 @@ private isReusedSection(): boolean { return this.insecurityType_ === CheckupSubpage.REUSED; } + + private onMoreActionsClick_(event: CustomEvent) { + const target = event.detail.target; + this.$.moreActionsMenu.showAt(target); + this.activeListItem_ = + event.detail.listItem as unknown as CheckupListItemElement; + } + + private onMenuShowPasswordClick_() { + this.activeListItem_?.showHidePassword(); + this.$.moreActionsMenu.close(); + this.activeListItem_ = null; + PasswordManagerImpl.getInstance().recordPasswordCheckInteraction( + PasswordCheckInteraction.SHOW_PASSWORD); + } + + private getShowHideTitle_(): string { + return this.activeListItem_?.getShowHideButtonLabel() || ''; + } + + private isMutingDisabledByPrefs_(): boolean { + return !!this.pref && this.pref.value === false; + } + + private getMuteUnmuteLabel_(): string { + return this.activeListItem_?.item.compromisedInfo?.isMuted === true ? + this.i18n('unmuteCompromisedPassword') : + this.i18n('muteCompromisedPassword'); + } + + private onMenuMuteUnmuteClick_() { + assert(this.activeListItem_); + if (this.activeListItem_.item.compromisedInfo?.isMuted === true) { + PasswordManagerImpl.getInstance().recordPasswordCheckInteraction( + PasswordCheckInteraction.UNMUTE_PASSWORD); + PasswordManagerImpl.getInstance().unmuteInsecureCredential( + this.activeListItem_.item); + } else { + PasswordManagerImpl.getInstance().recordPasswordCheckInteraction( + PasswordCheckInteraction.MUTE_PASSWORD); + PasswordManagerImpl.getInstance().muteInsecureCredential( + this.activeListItem_.item); + } + this.$.moreActionsMenu.close(); + } + + private getCurrentGroup_(id: number): chrome.passwordsPrivate.CredentialGroup + |undefined { + return this.groups_.find( + group => group.entries.some(entry => entry.id === id)); + } } declare global {
diff --git a/chrome/browser/resources/password_manager/checkup_list_item.html b/chrome/browser/resources/password_manager/checkup_list_item.html index ea8234c6..3ae40eb 100644 --- a/chrome/browser/resources/password_manager/checkup_list_item.html +++ b/chrome/browser/resources/password_manager/checkup_list_item.html
@@ -44,12 +44,11 @@ </style> <div id="separator" class="hr" hidden="[[first]]"></div> <div id="list-item" focus-row-container> - <!-- TODO(crbug.com/): Consider using group icon. --> - <site-favicon domain="[[item.changePasswordUrl]]"></site-favicon> + <site-favicon url="[[group.iconUrl]]" domain="[[group.name]]"></site-favicon> <div id="credentialInfo"> <div id="infoColumn"> <div id="shownUrl" class="label"> - [[getShownDomain_(item)]] + [[group.name]] </div> <div class="cr-secondary-text label"> <span id="username">[[item.username]]</span> @@ -78,7 +77,7 @@ </iron-icon> </cr-button> </div> - <!-- TODO(crbug.com/): Implement more actions. --> - <cr-icon-button class="icon-more-vert" id="more" title="$i18n{moreActions}"> + <cr-icon-button class="icon-more-vert" id="more" title="$i18n{moreActions}" + on-click="onMoreClick_"> </cr-icon-button> </div>
diff --git a/chrome/browser/resources/password_manager/checkup_list_item.ts b/chrome/browser/resources/password_manager/checkup_list_item.ts index f1a53b2..58862d62 100644 --- a/chrome/browser/resources/password_manager/checkup_list_item.ts +++ b/chrome/browser/resources/password_manager/checkup_list_item.ts
@@ -8,18 +8,21 @@ import './site_favicon.js'; import './shared_style.css.js'; +import {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './checkup_list_item.html.js'; -import {ShowPasswordMixin} from './show_password_mixin.js'; +import {PasswordManagerImpl} from './password_manager_proxy.js'; +import {ShowPasswordMixin, ShowPasswordMixinInterface} from './show_password_mixin.js'; -export interface CheckupListItemElement { +export interface CheckupListItemElement extends ShowPasswordMixinInterface { $: { shownUrl: HTMLElement, username: HTMLElement, insecurePassword: HTMLInputElement, + more: CrIconButtonElement, }; } @@ -38,6 +41,8 @@ return { item: Object, + group: Object, + first: Boolean, showDetails: Boolean, @@ -45,14 +50,10 @@ } item: chrome.passwordsPrivate.PasswordUiEntry; + group: chrome.passwordsPrivate.CredentialGroup; first: boolean; showDetails: boolean; - private getShownDomain_(): string { - // TODO(crbug.com/1401001): Use group name here. - return this.item.urls.shown; - } - private getPasswordValue_(): string|undefined { return this.isPasswordVisible ? this.item.password : ' '.repeat(10); } @@ -76,6 +77,37 @@ assertNotReached( 'Can\'t find a string for type: ' + this.item.compromisedInfo); } + + private onMoreClick_(event: Event) { + this.dispatchEvent(new CustomEvent('more-actions-click', { + bubbles: true, + composed: true, + detail: { + listItem: this, + target: event.target, + }, + })); + } + + public showHidePassword() { + if (this.isPasswordVisible === true) { + this.onShowHidePasswordButtonClick(); + this.item.password = undefined; + this.item.note = undefined; + return; + } + + PasswordManagerImpl.getInstance() + .requestCredentialsDetails([this.item.id]) + .then(entries => { + const entry = entries[0]; + assert(!!entry); + this.item.password = entry.password; + this.item.note = entry.note; + this.onShowHidePasswordButtonClick(); + }) + .catch(() => {}); + } } declare global {
diff --git a/chrome/browser/resources/password_manager/password_manager_proxy.ts b/chrome/browser/resources/password_manager/password_manager_proxy.ts index 5d210bc..2a872cd9 100644 --- a/chrome/browser/resources/password_manager/password_manager_proxy.ts +++ b/chrome/browser/resources/password_manager/password_manager_proxy.ts
@@ -159,6 +159,18 @@ removeBlockedSite(id: number): void; /** + * Dismisses / mutes the |insecureCredential| in the passwords store. + */ + muteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry): void; + + /** + * Restores / unmutes the |insecureCredential| in the passwords store. + */ + unmuteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry): void; + + /** * Queries the status of any ongoing export. */ requestExportProgressStatus(): @@ -278,6 +290,16 @@ chrome.passwordsPrivate.removePasswordException(id); } + muteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry) { + chrome.passwordsPrivate.muteInsecureCredential(insecureCredential); + } + + unmuteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry) { + chrome.passwordsPrivate.unmuteInsecureCredential(insecureCredential); + } + requestExportProgressStatus() { return chrome.passwordsPrivate.requestExportProgressStatus(); }
diff --git a/chrome/browser/resources/pdf/elements/viewer-toolbar.html b/chrome/browser/resources/pdf/elements/viewer-toolbar.html index 990e133..ffed0b9d 100644 --- a/chrome/browser/resources/pdf/elements/viewer-toolbar.html +++ b/chrome/browser/resources/pdf/elements/viewer-toolbar.html
@@ -276,7 +276,7 @@ <if expr="enable_ink"> disabled="[[annotationMode]]" </if> - aria-checked="[[getTwoPageViewAriaChecked_(twoUpViewEnabled)]]"> + aria-checked="[[getAriaChecked_(twoUpViewEnabled)]]"> <span class="check-container"> <iron-icon icon="pdf:check" hidden="[[!twoUpViewEnabled]]"></iron-icon> </span> @@ -286,7 +286,7 @@ <button id="show-annotations-button" class="dropdown-item" on-click="toggleDisplayAnnotations_" role="checkbox" - aria-checked="[[getShowAnnotationsAriaChecked_(displayAnnotations_)]]"> + aria-checked="[[getAriaChecked_(displayAnnotations_)]]"> <span class="check-container"> <iron-icon icon="pdf:check" hidden="[[!displayAnnotations_]]"></iron-icon> </span>
diff --git a/chrome/browser/resources/pdf/elements/viewer-toolbar.ts b/chrome/browser/resources/pdf/elements/viewer-toolbar.ts index 912a005..40a0beb4 100644 --- a/chrome/browser/resources/pdf/elements/viewer-toolbar.ts +++ b/chrome/browser/resources/pdf/elements/viewer-toolbar.ts
@@ -217,15 +217,7 @@ this.dispatchEvent(new CustomEvent('properties-click')); } - private getSinglePageAriaChecked_(checked: boolean): string { - return checked ? 'false' : 'true'; - } - - private getTwoPageViewAriaChecked_(checked: boolean): string { - return checked ? 'true' : 'false'; - } - - private getShowAnnotationsAriaChecked_(checked: boolean): string { + private getAriaChecked_(checked: boolean): string { return checked ? 'true' : 'false'; }
diff --git a/chrome/browser/resources/print_preview/data/state.ts b/chrome/browser/resources/print_preview/data/state.ts index 519dc978..e283e716 100644 --- a/chrome/browser/resources/print_preview/data/state.ts +++ b/chrome/browser/resources/print_preview/data/state.ts
@@ -16,6 +16,11 @@ CLOSING = 7, } +/** + * These values are persisted to logs. New entries should replace MAX_BUCKET but + * existing entries should not be renumbered and numeric values should never be + * reused. + */ export enum Error { NONE = 0, INVALID_TICKET = 1, @@ -23,6 +28,7 @@ NO_DESTINATIONS = 3, PREVIEW_FAILED = 4, PRINT_FAILED = 5, + MAX_BUCKET = 6, }
diff --git a/chrome/browser/resources/print_preview/native_layer.ts b/chrome/browser/resources/print_preview/native_layer.ts index 83a8c2f4..d040bdd 100644 --- a/chrome/browser/resources/print_preview/native_layer.ts +++ b/chrome/browser/resources/print_preview/native_layer.ts
@@ -197,6 +197,13 @@ * @param maxBucket The maximum bucket value in the histogram. */ recordInHistogram(histogram: string, bucket: number, maxBucket: number): void; + + /** + * Notifies the metrics handler to record a boolean histogram value. + * @param histogram The name of the histogram to record. + * @param value The boolean value to record. + */ + recordBooleanHistogram(histogram: string, value: boolean): void; } export class NativeLayerImpl implements NativeLayer { @@ -254,6 +261,10 @@ 'metricsHandler:recordInHistogram', [histogram, bucket, maxBucket]); } + recordBooleanHistogram(histogram: string, value: boolean) { + chrome.send('metricsHandler:recordBooleanHistogram', [histogram, value]); + } + static getInstance(): NativeLayer { return instance || (instance = new NativeLayerImpl()); }
diff --git a/chrome/browser/resources/print_preview/ui/app.ts b/chrome/browser/resources/print_preview/ui/app.ts index 3743eb1..1952d12 100644 --- a/chrome/browser/resources/print_preview/ui/app.ts +++ b/chrome/browser/resources/print_preview/ui/app.ts
@@ -81,7 +81,10 @@ documentSettings_: Object, - error_: Number, + error_: { + type: Number, + observer: 'onErrorChange_', + }, margins_: Object, @@ -332,6 +335,13 @@ this.$.model.applyDestinationSpecificPolicies(); this.startPreviewWhenReady_ = true; + + if (this.state === State.NOT_READY && + this.destination_.type !== PrinterType.PDF_PRINTER) { + this.nativeLayer_!.recordBooleanHistogram( + 'PrintPreview.TransitionedToReadyState', true); + } + this.$.state.transitTo(State.READY); break; case DestinationState.ERROR: @@ -341,6 +351,13 @@ newState = State.FATAL_ERROR; } // </if> + + if (this.state === State.NOT_READY && + this.destination_.type !== PrinterType.PDF_PRINTER) { + this.nativeLayer_!.recordBooleanHistogram( + 'PrintPreview.TransitionedToReadyState', false); + } + this.$.state.transitTo(newState); break; default: @@ -395,6 +412,13 @@ } } + private onErrorChange_() { + if (this.error_ !== Error.NONE) { + this.nativeLayer_!.recordInHistogram( + 'PrintPreview.StateError', this.error_, Error.MAX_BUCKET); + } + } + private onPrintRequested_() { if (this.state === State.NOT_READY) { this.printRequested_ = true;
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 312040f..13d5e0813a 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -268,7 +268,6 @@ group("closure_compile_module") { deps = [ ":closure_compile_local_module", - "multidevice_page:closure_compile_module", "os_people_page:closure_compile_module", "os_privacy_page:closure_compile_module", ] @@ -291,7 +290,6 @@ ":os_settings_routes", ":prefs_behavior", ":route_observer_behavior", - ":route_origin_behavior", ":router", ] } @@ -376,12 +374,5 @@ ] } -js_library("route_origin_behavior") { - deps = [ - ":os_route", - "//ash/webui/common/resources:cr.m", - ] -} - js_library("icon") { }
diff --git a/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_data.ts b/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_data.ts new file mode 100644 index 0000000..e1fa09e --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_data.ts
@@ -0,0 +1,33 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {Keyboard, MetaKey, Mouse, PointingStick, Touchpad} from './input_device_settings_types.js'; + +export const fakeKeyboards: Keyboard[] = [{ + id: 0, + name: 'fake-keyboard', + isExternal: false, + metaKey: MetaKey.COMMAND, + modifierKeys: [], + settings: {}, +}]; + +export const fakeTouchpads: Touchpad[] = [{ + id: 1, + name: 'fake-touchpad', + isExternal: false, + isHaptic: false, +}]; + +export const fakeMice: Mouse[] = [{ + id: 2, + name: 'fake-mouse', + isExternal: false, +}]; + +export const fakePointingSticks: PointingStick[] = [{ + id: 3, + name: 'fake-pointing-stick', + isExternal: false, +}];
diff --git a/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_settings_provider.ts b/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_settings_provider.ts index c950e5021..36616bf 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_settings_provider.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/fake_input_device_settings_provider.ts
@@ -79,7 +79,7 @@ this.methods.setResult('fakeKeyboards', keyboards); } - getFakeKeyboards(): Promise<Keyboard[]> { + getConnectedKeyboardSettings(): Promise<Keyboard[]> { return this.methods.resolveMethod('fakeKeyboards'); } @@ -87,7 +87,7 @@ this.methods.setResult('fakeTouchpads', touchpads); } - getFakeTouchpads(): Promise<Touchpad[]> { + getConnectedTouchpadSettings(): Promise<Touchpad[]> { return this.methods.resolveMethod('fakeTouchpads'); } @@ -95,7 +95,7 @@ this.methods.setResult('fakeMice', mice); } - getFakeMice(): Promise<Mouse[]> { + getConnectedMouseSettings(): Promise<Mouse[]> { return this.methods.resolveMethod('fakeMice'); } @@ -103,7 +103,7 @@ this.methods.setResult('fakePointingSticks', pointingSticks); } - getFakePointingSticks(): Promise<PointingStick[]> { + getConnectedPointingStickSettings(): Promise<PointingStick[]> { return this.methods.resolveMethod('fakePointingSticks'); }
diff --git a/chrome/browser/resources/settings/chromeos/device_page/input_device_mojo_interface_provider.ts b/chrome/browser/resources/settings/chromeos/device_page/input_device_mojo_interface_provider.ts new file mode 100644 index 0000000..3d972d7 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/device_page/input_device_mojo_interface_provider.ts
@@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert_ts.js'; + +import {fakeKeyboards, fakeMice, fakePointingSticks, fakeTouchpads} from './fake_input_device_data.js'; +import {FakeInputDeviceSettingsProvider} from './fake_input_device_settings_provider.js'; + +/** + * @fileoverview + * Provides singleton access to mojo interfaces with the ability + * to override them with test/fake implementations. + */ + +let inputDeviceSettingsProvider: FakeInputDeviceSettingsProvider|null; + +/** + * Create a FakeInputDeviceSettingsProvider with reasonable fake data. + */ +export function setupFakeInputDeviceSettingsProvider(): void { + inputDeviceSettingsProvider = new FakeInputDeviceSettingsProvider(); + inputDeviceSettingsProvider.setFakeKeyboards(fakeKeyboards); + inputDeviceSettingsProvider.setFakeTouchpads(fakeTouchpads); + inputDeviceSettingsProvider.setFakeMice(fakeMice); + inputDeviceSettingsProvider.setFakePointingSticks(fakePointingSticks); +} + +export function getInputDeviceSettingsProvider(): + FakeInputDeviceSettingsProvider { + // TODO(yyhyyh@): After mojo bindings implemented, update situations for + // getting the provider from remote and create a fake provider for testing. + if (!inputDeviceSettingsProvider) { + setupFakeInputDeviceSettingsProvider(); + } + + assert(!!inputDeviceSettingsProvider); + return inputDeviceSettingsProvider; +}
diff --git a/chrome/browser/resources/settings/chromeos/device_page/input_device_settings_types.ts b/chrome/browser/resources/settings/chromeos/device_page/input_device_settings_types.ts index 8509650..059e139 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/input_device_settings_types.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/input_device_settings_types.ts
@@ -100,7 +100,11 @@ export interface InputDeviceSettingsProviderInterface { observeKeyboardSettings(observer: KeyboardObserverInterface): void; + getConnectedKeyboardSettings(): Promise<Keyboard[]>; observeTouchpadSettings(observer: TouchpadObserverInterface): void; + getConnectedTouchpadSettings(): Promise<Touchpad[]>; observeMouseSettings(observer: MouseObserverInterface): void; + getConnectedMouseSettings(): Promise<Mouse[]>; observePointingStickSettings(observer: PointingStickObserverInterface): void; + getConnectedPointingStickSettings(): Promise<PointingStick[]>; }
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn deleted file mode 100644 index 59183b5..0000000 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn +++ /dev/null
@@ -1,118 +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("//third_party/closure_compiler/compile_js.gni") -import("../os_settings.gni") - -js_type_check("closure_compile_module") { - closure_flags = os_settings_closure_flags + mojom_js_args + [ - # For typechecking nearby share Mojo WebUI bindings: - # - Add the Mojo WebUI binding gen directory to the module root - # - Replace import path prefix so the bindings can be resolved - "js_module_root=" + rebase_path( - "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/nearby_share/", - root_build_dir), - "browser_resolver_prefix_replacements=\"/mojo/=./\"", - ] - is_polymer3 = true - deps = [ - ":multidevice_browser_proxy", - ":multidevice_constants", - ":multidevice_feature_behavior", - ":multidevice_metrics_logger", - ":multidevice_notification_access_setup_dialog", - ":multidevice_page", - ":multidevice_permissions_setup_dialog", - ":multidevice_screen_lock_subpage", - ":multidevice_subpage", - ] -} - -js_library("multidevice_browser_proxy") { - deps = [ - ":multidevice_constants", - "//ash/webui/common/resources:cr.m", - ] -} - -js_library("multidevice_constants") { - deps = [] -} - -js_library("multidevice_feature_behavior") { - deps = [ - ":multidevice_constants", - "//ash/webui/common/resources:i18n_behavior", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("multidevice_page") { - deps = [ - ":multidevice_browser_proxy", - ":multidevice_constants", - ":multidevice_feature_behavior", - ":multidevice_notification_access_setup_dialog", - ":multidevice_permissions_setup_dialog", - "..:deep_linking_behavior", - "..:metrics_recorder", - "..:os_route", - "..:prefs_behavior", - "..:route_observer_behavior", - "..:router", - "//ash/webui/common/resources:assert", - "//ash/webui/common/resources:web_ui_listener_behavior", - "//chrome/browser/resources/nearby_share/shared:nearby_share_settings_behavior", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("multidevice_notification_access_setup_dialog") { - deps = [ - ":multidevice_constants", - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources:load_time_data.m", - "//ash/webui/common/resources:web_ui_listener_behavior", - ] -} - -js_library("multidevice_permissions_setup_dialog") { - deps = [ - ":multidevice_constants", - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources:web_ui_listener_behavior", - ] -} - -js_library("multidevice_subpage") { - deps = [ - ":multidevice_browser_proxy", - ":multidevice_constants", - "..:deep_linking_behavior", - "..:os_route", - "..:os_settings_routes", - "..:route_observer_behavior", - "..:router", - "//ash/webui/common/resources/network:network_listener_behavior", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("multidevice_screen_lock_subpage") { - deps = [ - "../os_people_page:lock_screen_password_prompt_dialog", - "../os_people_page:lock_state_behavior", - "//ash/webui/common/resources:assert", - "//ash/webui/common/resources:focus_without_ink_js", - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources:load_time_data.m", - "//ash/webui/common/resources/quick_unlock:lock_screen_constants", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - externs_list = [ "$externs_path/chrome_extensions.js" ] -} - -js_library("multidevice_metrics_logger") { - deps = [ "//ash/webui/common/resources:assert" ] -}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.js deleted file mode 100644 index 1f984e8..0000000 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.js +++ /dev/null
@@ -1,272 +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 {sendWithPromise} from 'chrome://resources/ash/common/cr.m.js'; - -import {MultiDeviceFeature, MultiDevicePageContentData, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFeatureCombination, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js'; - -/** - * An object containing messages for web permissisions origin - * and the messages multidevice feature state. - * - * @typedef {{origin: string, - * enabled: boolean}} - */ -export let AndroidSmsInfo; - -/** @interface */ -export class MultiDeviceBrowserProxy { - showMultiDeviceSetupDialog() {} - - /** @return {!Promise<!MultiDevicePageContentData>} */ - getPageContentData() {} - - /** - * @param {!MultiDeviceFeature} feature The feature whose state - * should be set. - * @param {boolean} enabled Whether the feature should be turned off or on. - * @param {string=} opt_authToken Proof that the user is authenticated. - * Needed to enable Smart Lock, and Better Together Suite if the Smart - * Lock user pref is enabled. - * @return {!Promise<boolean>} Whether the operation was successful. - */ - setFeatureEnabledState(feature, enabled, opt_authToken) {} - - removeHostDevice() {} - - retryPendingHostSetup() {} - - /** - * Called when the "Set Up" button is clicked to open the Android Messages - * PWA. - */ - setUpAndroidSms() {} - - /** - * Returns the value of the preference controlling whether Smart Lock may be - * used to sign-in the user (as opposed to unlocking the screen). - * @return {!Promise<boolean>} - */ - getSmartLockSignInEnabled() {} - - /** - * Sets the value of the preference controlling whether Smart Lock may be - * used to sign-in the user (as opposed to unlocking the screen). - * @param {boolean} enabled - * @param {string=} opt_authToken Authentication token used to restrict - * edit access to the Smart Lock sign-in pref. - */ - setSmartLockSignInEnabled(enabled, opt_authToken) {} - - /** - * Returns the value of the preference controlling whether Smart Lock - * sign-in is allowed. - * @return {!Promise<boolean>} - */ - getSmartLockSignInAllowed() {} - - /** - * Returns android messages info with messages feature state - * and messages for web permissions origin. - * @return {!Promise<!AndroidSmsInfo>} Android SMS Info - */ - getAndroidSmsInfo() {} - - /** - * Attempts the phone hub notification access setup flow. - */ - attemptNotificationSetup() {} - - /** - * Cancels the phone hub notification access setup flow. - */ - cancelNotificationSetup() {} - - /** - * Attempts the phone hub apps access setup flow. - */ - attemptAppsSetup() {} - - /** - * Cancels the phone hub apps access setup flow. - */ - cancelAppsSetup() {} - - /** - * Attempts the phone hub combined feature access setup flow. - */ - attemptCombinedFeatureSetup(cameraRoll, notifications) {} - - /** - * Cancels the phone hub combined feature access setup flow. - */ - cancelCombinedFeatureSetup() {} - - /** - * Attempts to connect to the phone before setup. - */ - attemptFeatureSetupConnection() {} - - /** - * Cancel the connection flow. - */ - cancelFeatureSetupConnection() {} - - /** - * Log [Cancel] button click event in phone hub combined feature access setup - * flow. - * @param {!PhoneHubPermissionsSetupFlowScreens} screen - * @param {!PhoneHubPermissionsSetupAction} action - */ - logPhoneHubPermissionSetUpScreenAction(screen, action) {} - - /** - * Log phone hub combined feature access [Set Up] button click event. - * @param {!PhoneHubPermissionsSetupFeatureCombination} setup_mode - */ - logPhoneHubPermissionSetUpButtonClicked(setup_mode) {} - - /** - * Log setup mode when multidevice permissions set up intro screen is - * displayed. - * @param {!PhoneHubPermissionsSetupFeatureCombination} setup_mode - */ - logPhoneHubPermissionOnboardingSetupMode(setup_mode) {} - - /** - * Log setup mode when multidevice permissions set up finished screen is - * displayed. - * @param {!PhoneHubPermissionsSetupFeatureCombination} completed_mode - */ - logPhoneHubPermissionOnboardingSetupResult(completed_mode) {} -} - -/** @type {?MultiDeviceBrowserProxy} */ -let instance = null; - -/** - * @implements {MultiDeviceBrowserProxy} - */ -export class MultiDeviceBrowserProxyImpl { - /** @return {!MultiDeviceBrowserProxy} */ - static getInstance() { - return instance || (instance = new MultiDeviceBrowserProxyImpl()); - } - - /** @param {!MultiDeviceBrowserProxy} obj */ - static setInstanceForTesting(obj) { - instance = obj; - } - - /** @override */ - showMultiDeviceSetupDialog() { - chrome.send('showMultiDeviceSetupDialog'); - } - - /** @override */ - getPageContentData() { - return sendWithPromise('getPageContentData'); - } - - /** @override */ - setFeatureEnabledState(feature, enabled, opt_authToken) { - return sendWithPromise( - 'setFeatureEnabledState', feature, enabled, opt_authToken); - } - - /** @override */ - removeHostDevice() { - chrome.send('removeHostDevice'); - } - - /** @override */ - retryPendingHostSetup() { - chrome.send('retryPendingHostSetup'); - } - - /** @override */ - setUpAndroidSms() { - chrome.send('setUpAndroidSms'); - } - - /** @override */ - getSmartLockSignInEnabled() { - return sendWithPromise('getSmartLockSignInEnabled'); - } - - /** @override */ - setSmartLockSignInEnabled(enabled, opt_authToken) { - chrome.send('setSmartLockSignInEnabled', [enabled, opt_authToken]); - } - - /** @override */ - getSmartLockSignInAllowed() { - return sendWithPromise('getSmartLockSignInAllowed'); - } - - /** @override */ - getAndroidSmsInfo() { - return sendWithPromise('getAndroidSmsInfo'); - } - - /** @override */ - attemptNotificationSetup() { - chrome.send('attemptNotificationSetup'); - } - - /** @override */ - cancelNotificationSetup() { - chrome.send('cancelNotificationSetup'); - } - - /** @override */ - attemptAppsSetup() { - chrome.send('attemptAppsSetup'); - } - - /** @override */ - cancelAppsSetup() { - chrome.send('cancelAppsSetup'); - } - - /** @override */ - attemptCombinedFeatureSetup(cameraRoll, notifications) { - chrome.send('attemptCombinedFeatureSetup', [cameraRoll, notifications]); - } - - /** @override */ - cancelCombinedFeatureSetup() { - chrome.send('cancelCombinedFeatureSetup'); - } - - /** @override */ - attemptFeatureSetupConnection() { - chrome.send('attemptFeatureSetupConnection'); - } - - /** @override */ - cancelFeatureSetupConnection() { - chrome.send('cancelFeatureSetupConnection'); - } - - /** @override */ - logPhoneHubPermissionSetUpScreenAction(screen, action) { - chrome.send('logPhoneHubPermissionSetUpScreenAction', [screen, action]); - } - - /** @override */ - logPhoneHubPermissionSetUpButtonClicked(setup_mode) { - chrome.send('logPhoneHubPermissionSetUpButtonClicked', [setup_mode]); - } - - /** @override */ - logPhoneHubPermissionOnboardingSetupMode(setup_mode) { - chrome.send('logPhoneHubPermissionOnboardingSetupMode', [setup_mode]); - } - - /** @override */ - logPhoneHubPermissionOnboardingSetupResult(completed_mode) { - chrome.send('logPhoneHubPermissionOnboardingSetupResult', [completed_mode]); - } -}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.ts new file mode 100644 index 0000000..a2cc3c4 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.ts
@@ -0,0 +1,246 @@ +// 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 {sendWithPromise} from 'chrome://resources/ash/common/cr.m.js'; + +import {MultiDeviceFeature, MultiDevicePageContentData, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFeatureCombination, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js'; + +/** + * An object containing messages for web permissisions origin + * and the messages multidevice feature state. + */ +export interface AndroidSmsInfo { + origin: string; + enabled: boolean; +} + +export interface MultiDeviceBrowserProxy { + showMultiDeviceSetupDialog(): void; + + getPageContentData(): Promise<MultiDevicePageContentData>; + + /** + * @param feature The feature whose state should be set. + * @param enabled Whether the feature should be turned off or on. + * @param authToken Proof that the user is authenticated. + * Needed to enable Smart Lock, and Better Together Suite if the Smart + * Lock user pref is enabled. + * @return Whether the operation was successful. + */ + setFeatureEnabledState( + feature: MultiDeviceFeature, enabled: boolean, + authToken?: string): Promise<boolean>; + + removeHostDevice(): void; + + retryPendingHostSetup(): void; + + setUpAndroidSms(): void; + + /** + * Returns the value of the preference controlling whether Smart Lock may be + * used to sign-in the user (as opposed to unlocking the screen). + */ + getSmartLockSignInEnabled(): Promise<boolean>; + + /** + * Sets the value of the preference controlling whether Smart Lock may be + * used to sign-in the user (as opposed to unlocking the screen). + * @param enabled + * @param authToken Authentication token used to restrict + * edit access to the Smart Lock sign-in pref. + */ + setSmartLockSignInEnabled(enabled: boolean, authToken?: string): void; + + /** + * Returns the value of the preference controlling whether Smart Lock + * sign-in is allowed. + */ + getSmartLockSignInAllowed(): Promise<boolean>; + + /** + * Returns android messages info with messages feature state + * and messages for web permissions origin. + */ + getAndroidSmsInfo(): Promise<AndroidSmsInfo>; + + /** + * Attempts the phone hub notification access setup flow. + */ + attemptNotificationSetup(): void; + + /** + * Cancels the phone hub notification access setup flow. + */ + cancelNotificationSetup(): void; + + /** + * Attempts the phone hub apps access setup flow. + */ + attemptAppsSetup(): void; + + /** + * Cancels the phone hub apps access setup flow. + */ + cancelAppsSetup(): void; + + /** + * Attempts the phone hub combined feature access setup flow. + */ + attemptCombinedFeatureSetup( + showCameraRoll: boolean, showNotifications: boolean): void; + + /** + * Cancels the phone hub combined feature access setup flow. + */ + cancelCombinedFeatureSetup(): void; + + /** + * Attempts to connect to the phone before setup. + */ + attemptFeatureSetupConnection(): void; + + /** + * Cancel the connection flow. + */ + cancelFeatureSetupConnection(): void; + + /** + * Log [Cancel] button click event in phone hub combined feature access setup + * flow. + */ + logPhoneHubPermissionSetUpScreenAction( + screen: PhoneHubPermissionsSetupFlowScreens, + action: PhoneHubPermissionsSetupAction): void; + + /** + * Log phone hub combined feature access [Set Up] button click event. + */ + logPhoneHubPermissionSetUpButtonClicked( + setupMode: PhoneHubPermissionsSetupFeatureCombination): void; + + /** + * Log setup mode when multidevice permissions set up intro screen is + * displayed. + */ + logPhoneHubPermissionOnboardingSetupMode( + setupMode: PhoneHubPermissionsSetupFeatureCombination): void; + + /** + * Log setup mode when multidevice permissions set up finished screen is + * displayed. + */ + logPhoneHubPermissionOnboardingSetupResult( + completedMode: PhoneHubPermissionsSetupFeatureCombination): void; +} + +let instance: MultiDeviceBrowserProxy|null = null; + +export class MultiDeviceBrowserProxyImpl implements MultiDeviceBrowserProxy { + static getInstance(): MultiDeviceBrowserProxy { + return instance || (instance = new MultiDeviceBrowserProxyImpl()); + } + + static setInstanceForTesting(obj: MultiDeviceBrowserProxy): void { + instance = obj; + } + + showMultiDeviceSetupDialog(): void { + chrome.send('showMultiDeviceSetupDialog'); + } + + getPageContentData(): Promise<MultiDevicePageContentData> { + return sendWithPromise('getPageContentData'); + } + + setFeatureEnabledState( + feature: MultiDeviceFeature, enabled: boolean, + authToken?: string): Promise<boolean> { + return sendWithPromise( + 'setFeatureEnabledState', feature, enabled, authToken); + } + + removeHostDevice(): void { + chrome.send('removeHostDevice'); + } + + retryPendingHostSetup(): void { + chrome.send('retryPendingHostSetup'); + } + + setUpAndroidSms(): void { + chrome.send('setUpAndroidSms'); + } + + getSmartLockSignInEnabled(): Promise<boolean> { + return sendWithPromise('getSmartLockSignInEnabled'); + } + + setSmartLockSignInEnabled(enabled: boolean, authToken?: string): void { + chrome.send('setSmartLockSignInEnabled', [enabled, authToken]); + } + + getSmartLockSignInAllowed(): Promise<boolean> { + return sendWithPromise('getSmartLockSignInAllowed'); + } + + getAndroidSmsInfo(): Promise<AndroidSmsInfo> { + return sendWithPromise('getAndroidSmsInfo'); + } + + attemptNotificationSetup(): void { + chrome.send('attemptNotificationSetup'); + } + + cancelNotificationSetup(): void { + chrome.send('cancelNotificationSetup'); + } + + attemptAppsSetup(): void { + chrome.send('attemptAppsSetup'); + } + + cancelAppsSetup(): void { + chrome.send('cancelAppsSetup'); + } + + attemptCombinedFeatureSetup( + showCameraRoll: boolean, showNotifications: boolean): void { + chrome.send( + 'attemptCombinedFeatureSetup', [showCameraRoll, showNotifications]); + } + + cancelCombinedFeatureSetup(): void { + chrome.send('cancelCombinedFeatureSetup'); + } + + attemptFeatureSetupConnection(): void { + chrome.send('attemptFeatureSetupConnection'); + } + + cancelFeatureSetupConnection(): void { + chrome.send('cancelFeatureSetupConnection'); + } + + logPhoneHubPermissionSetUpScreenAction( + screen: PhoneHubPermissionsSetupFlowScreens, + action: PhoneHubPermissionsSetupAction): void { + chrome.send('logPhoneHubPermissionSetUpScreenAction', [screen, action]); + } + + logPhoneHubPermissionSetUpButtonClicked( + setupMode: PhoneHubPermissionsSetupFeatureCombination): void { + chrome.send('logPhoneHubPermissionSetUpButtonClicked', [setupMode]); + } + + logPhoneHubPermissionOnboardingSetupMode( + setupMode: PhoneHubPermissionsSetupFeatureCombination): void { + chrome.send('logPhoneHubPermissionOnboardingSetupMode', [setupMode]); + } + + logPhoneHubPermissionOnboardingSetupResult( + completedMode: PhoneHubPermissionsSetupFeatureCombination): void { + chrome.send('logPhoneHubPermissionOnboardingSetupResult', [completedMode]); + } +}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.ts index a6d5341..d942b45d 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_combined_setup_item.ts
@@ -11,20 +11,15 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import './multidevice_feature_item.js'; -import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {Constructor} from '../common/types'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; import {getTemplate} from './multidevice_combined_setup_item.html.js'; import {PhoneHubPermissionsSetupFeatureCombination} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; const SettingsMultideviceCombinedSetupItemElementBase = - mixinBehaviors([MultiDeviceFeatureBehavior], I18nMixin(PolymerElement)) as - Constructor<PolymerElement&I18nMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(PolymerElement); class SettingsMultideviceCombinedSetupItemElement extends SettingsMultideviceCombinedSetupItemElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.js deleted file mode 100644 index 97d0ce8..0000000 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.js +++ /dev/null
@@ -1,198 +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. - -/** - * The state of the preference controlling Smart Lock's ability to sign-in the - * user. - * @enum {string} - */ -export const SmartLockSignInEnabledState = { - ENABLED: 'enabled', - DISABLED: 'disabled', -}; - -/** - * The possible statuses of hosts on the logged in account that determine the - * page content. Note that this is based on (and must include an analog of - * all values in) the HostStatus enum in - * services/multidevice_setup/public/mojom/multidevice_setup.mojom. - * @enum {number} - */ -export const MultiDeviceSettingsMode = { - NO_ELIGIBLE_HOSTS: 0, - NO_HOST_SET: 1, - HOST_SET_WAITING_FOR_SERVER: 2, - HOST_SET_WAITING_FOR_VERIFICATION: 3, - HOST_SET_VERIFIED: 4, -}; - -/** - * Enum of MultiDevice features. Note that this is copied from (and must - * include an analog of all values in) the Feature enum in - * //chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom. - * @enum {number} - */ -export const MultiDeviceFeature = { - BETTER_TOGETHER_SUITE: 0, - INSTANT_TETHERING: 1, - MESSAGES: 2, - SMART_LOCK: 3, - PHONE_HUB: 4, - PHONE_HUB_NOTIFICATIONS: 5, - PHONE_HUB_TASK_CONTINUATION: 6, - WIFI_SYNC: 7, - ECHE: 8, - PHONE_HUB_CAMERA_ROLL: 9, -}; - -/** - * Possible states of MultiDevice features. Note that this is copied from (and - * must include an analog of all values in) the FeatureState enum in - * //chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom. - * @enum {number} - */ -export const MultiDeviceFeatureState = { - PROHIBITED_BY_POLICY: 0, - DISABLED_BY_USER: 1, - ENABLED_BY_USER: 2, - NOT_SUPPORTED_BY_CHROMEBOOK: 3, - NOT_SUPPORTED_BY_PHONE: 4, - UNAVAILABLE_NO_VERIFIED_HOST: 5, - UNAVAILABLE_INSUFFICIENT_SECURITY: 6, - UNAVAILABLE_SUITE_DISABLED: 7, - FURTHER_SETUP_REQUIRED: 8, - UNAVAILABLE_TOP_LEVEL_FEATURE_DISABLED: 9, - UNAVAILABLE_NO_VERIFIED_HOST_CLIENT_NOT_READY: 10, - UNAVAILABLE_NO_VERIFIED_HOST_NO_ELIGIBLE_HOST: 11, -}; - -/** - * Possible states of Phone Hub's feature access. Access can be - * prohibited if the user is using a work profile on their phone on Android - * version <N, or if the policy managing the phone disables access. - * @enum {number} - */ -export const PhoneHubFeatureAccessStatus = { - PROHIBITED: 0, - AVAILABLE_BUT_NOT_GRANTED: 1, - ACCESS_GRANTED: 2, -}; - -/** - * Possible reasons for Phone Hub's feature access being prohibited. - * Users should ensure feature access is actually prohibited before - * comparing against these reasons. - * @enum {number} - */ -export const PhoneHubFeatureAccessProhibitedReason = { - UNKNOWN: 0, - WORK_PROFILE: 1, - DISABLED_BY_PHONE_POLICY: 2, -}; - -/** - * Possible of Phone Hub's permissions setup mode.The value will be assigned - * when the user clicks on the settings UI. Basically, INIT_MODE will be - * default value, which means it has not been set yet. - * ALL_PERMISSIONS_SETUP_MODE means that we will process notifications and - * apps streaming onboarding flow in order. - * - * @enum {number} - */ -export const PhoneHubPermissionsSetupMode = { - INIT_MODE: 0, - NOTIFICATION_SETUP_MODE: 1, - APPS_SETUP_MODE: 2, - CAMERA_ROLL_SETUP_MODE: 3, - ALL_PERMISSIONS_SETUP_MODE: 4, -}; - -/** - * Numerical values the screens for combined set up dialog only. - * Update of this enum should be propagate to PermissionsOnboardingStep - * in chromeos/ash/components/phonehub/util/histogram_util.h. - * @enum {number} - */ -export const PhoneHubPermissionsSetupFlowScreens = { - NOT_APPLICABLE: 0, - INTRO: 1, - FINISH_SET_UP_ON_PHONE: 2, - CONNECTING: 3, - CONNECTION_ERROR: 4, - CONNECTION_TIME_OUT: 5, - CONNECTED: 6, - SET_A_PIN_OR_PASSWORD: 7, -}; - -/** - * Numerical values the screens for actions in combined set up dialog only. - * Update of this enum should be propagate to PermissionsOnboardingScreenEvent - * in chromeos/ash/components/phonehub/util/histogram_util.h. - * @enum {number} - */ -export const PhoneHubPermissionsSetupAction = { - UNKNOWN: 0, - SHOWN: 1, - LEARN_MORE: 2, - CANCEL: 3, - DONE: 4, - NEXT_OR_TRY_AGAIN: 5, -}; - -/** - * Numerical values the set up mode in combined set up dialog only. - * Update of this enum should be propagate to PermissionsOnboardingSetUpMode in - * chromeos/ash/components/phonehub/util/histogram_util.h. - * @enum {number} - */ -export const PhoneHubPermissionsSetupFeatureCombination = { - NONE: 0, - NOTIFICATION: 1, - MESSAGING_APP: 2, - CAMERA_ROLL: 3, - NOTIFICATION_AND_MESSAGING_APP: 4, - NOTIFICATION_AND_CAMERA_ROLL: 5, - MESSAGING_APP_AND_CAMERA_ROLL: 6, - ALL_PERMISSONS: 7, -}; - -/** - * Container for the initial data that the page requires in order to display - * the correct content. It is also used for receiving status updates during - * use. Note that the host device may be verified (enabled or disabled), - * awaiting verification, or it may have failed setup because it was not able - * to connect to the server. - * - * For each MultiDevice feature (including the "suite" feature, which acts as - * a gatekeeper for the others), the corresponding *State property is an enum - * containing the data necessary to display it. Note that hostDeviceName - * should be undefined if and only if no host has been set up, regardless of - * whether there are potential hosts on the account. - * - * @typedef {{ - * mode: !MultiDeviceSettingsMode, - * hostDeviceName: (string|undefined), - * betterTogetherState: !MultiDeviceFeatureState, - * instantTetheringState: !MultiDeviceFeatureState, - * messagesState: !MultiDeviceFeatureState, - * smartLockState: !MultiDeviceFeatureState, - * phoneHubState: !MultiDeviceFeatureState, - * phoneHubCameraRollState: !MultiDeviceFeatureState, - * phoneHubNotificationsState: !MultiDeviceFeatureState, - * phoneHubTaskContinuationState: !MultiDeviceFeatureState, - * phoneHubAppsState: !MultiDeviceFeatureState, - * wifiSyncState: !MultiDeviceFeatureState, - * isAndroidSmsPairingComplete: boolean, - * cameraRollAccessStatus: !PhoneHubFeatureAccessStatus, - * notificationAccessStatus: !PhoneHubFeatureAccessStatus, - * appsAccessStatus: !PhoneHubFeatureAccessStatus, - * notificationAccessProhibitedReason: - * !PhoneHubFeatureAccessProhibitedReason, - * isNearbyShareDisallowedByPolicy: boolean, - * isPhoneHubPermissionsDialogSupported: boolean, - * isCameraRollFilePermissionGranted: boolean, - * isPhoneHubFeatureCombinedSetupSupported: boolean - * }} - */ -export let MultiDevicePageContentData;
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.ts new file mode 100644 index 0000000..4200122 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_constants.ts
@@ -0,0 +1,184 @@ +// 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. + +/** + * The state of the preference controlling Smart Lock's ability to sign-in the + * user. + */ +export enum SmartLockSignInEnabledState { + ENABLED = 'enabled', + DISABLED = 'disabled', +} + +/** + * The possible statuses of hosts on the logged in account that determine the + * page content. Note that this is based on (and must include an analog of + * all values in) the HostStatus enum in + * services/multidevice_setup/public/mojom/multidevice_setup.mojom. + */ +export enum MultiDeviceSettingsMode { + NO_ELIGIBLE_HOSTS = 0, + NO_HOST_SET = 1, + HOST_SET_WAITING_FOR_SERVER = 2, + HOST_SET_WAITING_FOR_VERIFICATION = 3, + HOST_SET_VERIFIED = 4, +} + +/** + * Enum of MultiDevice features. Note that this is copied from (and must + * include an analog of all values in) the Feature enum in + * //chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom. + */ +export enum MultiDeviceFeature { + BETTER_TOGETHER_SUITE = 0, + INSTANT_TETHERING = 1, + MESSAGES = 2, + SMART_LOCK = 3, + PHONE_HUB = 4, + PHONE_HUB_NOTIFICATIONS = 5, + PHONE_HUB_TASK_CONTINUATION = 6, + WIFI_SYNC = 7, + ECHE = 8, + PHONE_HUB_CAMERA_ROLL = 9, +} + +/** + * Possible states of MultiDevice features. Note that this is copied from (and + * must include an analog of all values in) the FeatureState enum in + * //chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom. + */ +export enum MultiDeviceFeatureState { + PROHIBITED_BY_POLICY = 0, + DISABLED_BY_USER = 1, + ENABLED_BY_USER = 2, + NOT_SUPPORTED_BY_CHROMEBOOK = 3, + NOT_SUPPORTED_BY_PHONE = 4, + UNAVAILABLE_NO_VERIFIED_HOST = 5, + UNAVAILABLE_INSUFFICIENT_SECURITY = 6, + UNAVAILABLE_SUITE_DISABLED = 7, + FURTHER_SETUP_REQUIRED = 8, + UNAVAILABLE_TOP_LEVEL_FEATURE_DISABLED = 9, + UNAVAILABLE_NO_VERIFIED_HOST_CLIENT_NOT_READY = 10, + UNAVAILABLE_NO_VERIFIED_HOST_NO_ELIGIBLE_HOST = 11, +} + +/** + * Possible states of Phone Hub's feature access. Access can be + * prohibited if the user is using a work profile on their phone on Android + * version <N, or if the policy managing the phone disables access. + */ +export enum PhoneHubFeatureAccessStatus { + PROHIBITED = 0, + AVAILABLE_BUT_NOT_GRANTED = 1, + ACCESS_GRANTED = 2, +} + +/** + * Possible reasons for Phone Hub's feature access being prohibited. + * Users should ensure feature access is actually prohibited before + * comparing against these reasons. + */ +export enum PhoneHubFeatureAccessProhibitedReason { + UNKNOWN = 0, + WORK_PROFILE = 1, + DISABLED_BY_PHONE_POLICY = 2, +} + +/** + * Possible of Phone Hub's permissions setup mode.The value will be assigned + * when the user clicks on the settings UI. Basically, INIT_MODE will be + * default value, which means it has not been set yet. + * ALL_PERMISSIONS_SETUP_MODE means that we will process notifications and + * apps streaming onboarding flow in order. + */ +export enum PhoneHubPermissionsSetupMode { + INIT_MODE = 0, + NOTIFICATION_SETUP_MODE = 1, + APPS_SETUP_MODE = 2, + CAMERA_ROLL_SETUP_MODE = 3, + ALL_PERMISSIONS_SETUP_MODE = 4, +} + +/** + * Numerical values the screens for combined set up dialog only. + * Update of this enum should be propagate to PermissionsOnboardingStep + * in chromeos/ash/components/phonehub/util/histogram_util.h. + */ +export enum PhoneHubPermissionsSetupFlowScreens { + NOT_APPLICABLE = 0, + INTRO = 1, + FINISH_SET_UP_ON_PHONE = 2, + CONNECTING = 3, + CONNECTION_ERROR = 4, + CONNECTION_TIME_OUT = 5, + CONNECTED = 6, + SET_A_PIN_OR_PASSWORD = 7, +} + +/** + * Numerical values the screens for actions in combined set up dialog only. + * Update of this enum should be propagate to PermissionsOnboardingScreenEvent + * in chromeos/ash/components/phonehub/util/histogram_util.h. + */ +export enum PhoneHubPermissionsSetupAction { + UNKNOWN = 0, + SHOWN = 1, + LEARN_MORE = 2, + CANCEL = 3, + DONE = 4, + NEXT_OR_TRY_AGAIN = 5, +} + +/** + * Numerical values the set up mode in combined set up dialog only. + * Update of this enum should be propagate to PermissionsOnboardingSetUpMode in + * chromeos/ash/components/phonehub/util/histogram_util.h. + */ +export enum PhoneHubPermissionsSetupFeatureCombination { + NONE = 0, + NOTIFICATION = 1, + MESSAGING_APP = 2, + CAMERA_ROLL = 3, + NOTIFICATION_AND_MESSAGING_APP = 4, + NOTIFICATION_AND_CAMERA_ROLL = 5, + MESSAGING_APP_AND_CAMERA_ROLL = 6, + ALL_PERMISSONS = 7, +} + +/** + * Container for the initial data that the page requires in order to display + * the correct content. It is also used for receiving status updates during + * use. Note that the host device may be verified (enabled or disabled), + * awaiting verification, or it may have failed setup because it was not able + * to connect to the server. + * + * For each MultiDevice feature (including the "suite" feature, which acts as + * a gatekeeper for the others), the corresponding *State property is an enum + * containing the data necessary to display it. Note that hostDeviceName + * should be undefined if and only if no host has been set up, regardless of + * whether there are potential hosts on the account. + */ +export interface MultiDevicePageContentData { + mode: MultiDeviceSettingsMode; + hostDeviceName: string|undefined; + betterTogetherState: MultiDeviceFeatureState; + instantTetheringState: MultiDeviceFeatureState; + messagesState: MultiDeviceFeatureState; + smartLockState: MultiDeviceFeatureState; + phoneHubState: MultiDeviceFeatureState; + phoneHubCameraRollState: MultiDeviceFeatureState; + phoneHubNotificationsState: MultiDeviceFeatureState; + phoneHubTaskContinuationState: MultiDeviceFeatureState; + phoneHubAppsState: MultiDeviceFeatureState; + wifiSyncState: MultiDeviceFeatureState; + isAndroidSmsPairingComplete: boolean; + cameraRollAccessStatus: PhoneHubFeatureAccessStatus; + notificationAccessStatus: PhoneHubFeatureAccessStatus; + appsAccessStatus: PhoneHubFeatureAccessStatus; + notificationAccessProhibitedReason: PhoneHubFeatureAccessProhibitedReason; + isNearbyShareDisallowedByPolicy: boolean; + isPhoneHubPermissionsDialogSupported: boolean; + isCameraRollFilePermissionGranted: boolean; + isPhoneHubFeatureCombinedSetupSupported: boolean; +}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_behavior.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_behavior.js deleted file mode 100644 index 4a1e5d0..0000000 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_behavior.js +++ /dev/null
@@ -1,440 +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. - -/** - * @fileoverview Polymer behavior for dealing with MultiDevice features. It is - * intended to facilitate passing data between elements in the MultiDevice page - * cleanly and concisely. It includes some constants and utility methods. - */ - -import {I18nBehavior} from 'chrome://resources/ash/common/i18n_behavior.js'; - -import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus} from './multidevice_constants.js'; - -/** @polymerBehavior */ -const MultiDeviceFeatureBehaviorImpl = { - properties: { - /** @type {!MultiDevicePageContentData} */ - pageContentData: Object, - - /** - * Enum defined in multidevice_constants.js. - * @type {Object<string, number>} - */ - MultiDeviceFeature: { - type: Object, - value: MultiDeviceFeature, - }, - }, - - /** - * Whether the gatekeeper pref for the whole Better Together feature suite is - * on. - * @return {boolean} - */ - isSuiteOn() { - return !!this.pageContentData && - this.pageContentData.betterTogetherState === - MultiDeviceFeatureState.ENABLED_BY_USER; - }, - - /** - * Whether the gatekeeper pref for the whole Better Together feature suite is - * allowed by policy. - * @return {boolean} - */ - isSuiteAllowedByPolicy() { - return !!this.pageContentData && - this.pageContentData.betterTogetherState !== - MultiDeviceFeatureState.PROHIBITED_BY_POLICY; - }, - - /** - * Whether an individual feature is allowed by policy. - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureAllowedByPolicy(feature) { - return this.getFeatureState(feature) !== - MultiDeviceFeatureState.PROHIBITED_BY_POLICY; - }, - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureSupported(feature) { - return ![MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK, - MultiDeviceFeatureState.NOT_SUPPORTED_BY_PHONE, - ].includes(this.getFeatureState(feature)); - }, - - /** - * Whether the top-level Phone Hub feature is enabled. - * @return {boolean} - */ - isPhoneHubOn() { - return this.getFeatureState(MultiDeviceFeature.PHONE_HUB) === - MultiDeviceFeatureState.ENABLED_BY_USER; - }, - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isPhoneHubSubFeature(feature) { - return [ - MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL, - MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS, - MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION, - MultiDeviceFeature.ECHE, - ].includes(feature); - }, - - /** - * @return {boolean} Whether or not Phone Hub notification access is - * prohibited (i.e., due to the user having a work profile). - */ - isPhoneHubNotificationAccessProhibited() { - return this.pageContentData && - this.pageContentData.notificationAccessStatus === - PhoneHubFeatureAccessStatus.PROHIBITED; - }, - - /** - * @return {boolean} Whether or not Phone Hub apps access is - * prohibited (i.e., due to the apps streaming policy of the phone is - * disabled). - */ - isPhoneHubAppsAccessProhibited() { - return this.pageContentData && - this.pageContentData.appsAccessStatus === - PhoneHubFeatureAccessStatus.PROHIBITED; - }, - - /** - * Whether Camera Roll requires user action to finish set up. - * @return {boolean} - */ - isPhoneHubCameraRollSetupRequired() { - return this.isFeatureSupported(MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL) && - this.pageContentData.cameraRollAccessStatus === - PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && - this.isFeatureAllowedByPolicy(MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL); - }, - - /** - * Whether Apps requires user action to finish set up. - * @return {boolean} - */ - isPhoneHubAppsSetupRequired() { - return this.isFeatureSupported(MultiDeviceFeature.ECHE) && - this.pageContentData.isPhoneHubPermissionsDialogSupported && - this.pageContentData.appsAccessStatus === - PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && - this.isFeatureAllowedByPolicy(MultiDeviceFeature.ECHE); - }, - - /** - * Whether Notifications requires user action to finish set up. - * @return {boolean} - */ - isPhoneHubNotificationsSetupRequired() { - return this.pageContentData.notificationAccessStatus === - PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && - this.isFeatureAllowedByPolicy( - MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS); - }, - - /** - * Whether the user is prevented from attempted to change a given feature. In - * the UI this corresponds to a disabled toggle. - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureStateEditable(feature) { - // The suite is off and the toggle corresponds to an individual feature - // (as opposed to the full suite). - if (feature !== MultiDeviceFeature.BETTER_TOGETHER_SUITE && - !this.isSuiteOn()) { - return false; - } - - // Cannot edit Phone Hub sub-feature toggles if the top-level Phone Hub - // feature is not enabled. - if (this.isPhoneHubSubFeature(feature) && !this.isPhoneHubOn()) { - return false; - } - - // Cannot edit the Phone Hub notification toggle if notification access is - // prohibited. - if (feature === MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS && - this.isPhoneHubNotificationAccessProhibited()) { - return false; - } - - // Cannot edit the Phone Hub apps toggle if apps access is - // prohibited. - if (feature === MultiDeviceFeature.ECHE && - this.isPhoneHubAppsAccessProhibited()) { - return false; - } - - return [ - MultiDeviceFeatureState.DISABLED_BY_USER, - MultiDeviceFeatureState.ENABLED_BY_USER, - ].includes(this.getFeatureState(feature)); - }, - - /** - * The localized string representing the name of the feature. - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getFeatureName(feature) { - switch (feature) { - case MultiDeviceFeature.BETTER_TOGETHER_SUITE: - return this.i18n('multideviceSetupItemHeading'); - case MultiDeviceFeature.INSTANT_TETHERING: - return this.i18n('multideviceInstantTetheringItemTitle'); - case MultiDeviceFeature.MESSAGES: - return this.i18n('multideviceAndroidMessagesItemTitle'); - case MultiDeviceFeature.SMART_LOCK: - return this.i18n('multideviceSmartLockItemTitle'); - case MultiDeviceFeature.PHONE_HUB: - return this.i18n('multidevicePhoneHubItemTitle'); - case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: - return this.i18n('multidevicePhoneHubCameraRollItemTitle'); - case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: - return this.i18n('multidevicePhoneHubNotificationsItemTitle'); - case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: - return this.i18n('multidevicePhoneHubTaskContinuationItemTitle'); - case MultiDeviceFeature.WIFI_SYNC: - return this.i18n('multideviceWifiSyncItemTitle'); - case MultiDeviceFeature.ECHE: - return this.i18n('multidevicePhoneHubAppsItemTitle'); - default: - return ''; - } - }, - - /** - * The full icon name used provided by the containing iron-iconset-svg - * (i.e. [iron-iconset-svg name]:[SVG <g> tag id]) for a given feature. - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getIconName(feature) { - switch (feature) { - case MultiDeviceFeature.BETTER_TOGETHER_SUITE: - return 'os-settings:multidevice-better-together-suite'; - case MultiDeviceFeature.MESSAGES: - return 'os-settings:multidevice-messages'; - case MultiDeviceFeature.SMART_LOCK: - return 'os-settings:multidevice-smart-lock'; - case MultiDeviceFeature.PHONE_HUB: - case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: - case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: - case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: - case MultiDeviceFeature.ECHE: - return 'os-settings:multidevice-better-together-suite'; - case MultiDeviceFeature.WIFI_SYNC: - return 'os-settings:multidevice-wifi-sync'; - default: - return ''; - } - }, - - /** - * The localized string providing a description or useful status information - * concerning a given feature. - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getFeatureSummaryHtml(feature) { - switch (feature) { - case MultiDeviceFeature.SMART_LOCK: - return this.i18nAdvanced('multideviceSmartLockItemSummary'); - case MultiDeviceFeature.INSTANT_TETHERING: - return this.i18nAdvanced('multideviceInstantTetheringItemSummary'); - case MultiDeviceFeature.MESSAGES: - return this.i18nAdvanced('multideviceAndroidMessagesItemSummary'); - case MultiDeviceFeature.PHONE_HUB: - return this.i18nAdvanced('multidevicePhoneHubItemSummary'); - case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: - return this.i18nAdvanced('multidevicePhoneHubCameraRollItemSummary'); - case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: - return this.i18nAdvanced('multidevicePhoneHubNotificationsItemSummary'); - case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: - return this.i18nAdvanced( - 'multidevicePhoneHubTaskContinuationItemSummary'); - case MultiDeviceFeature.WIFI_SYNC: - return this.i18nAdvanced('multideviceWifiSyncItemSummary'); - case MultiDeviceFeature.ECHE: - return this.i18nAdvanced('multidevicePhoneHubAppsItemSummary'); - default: - return ''; - } - }, - - /** - * Extracts the MultiDeviceFeatureState enum value describing the given - * feature from this.pageContentData. Returns null if the feature is not - * an accepted value (e.g. testing fake). - * @param {!MultiDeviceFeature} feature - * @return {?MultiDeviceFeatureState} - */ - getFeatureState(feature) { - if (!this.pageContentData) { - return null; - } - - switch (feature) { - case MultiDeviceFeature.BETTER_TOGETHER_SUITE: - return this.pageContentData.betterTogetherState; - case MultiDeviceFeature.INSTANT_TETHERING: - return this.pageContentData.instantTetheringState; - case MultiDeviceFeature.MESSAGES: - return this.pageContentData.messagesState; - case MultiDeviceFeature.SMART_LOCK: - return this.pageContentData.smartLockState; - case MultiDeviceFeature.PHONE_HUB: - return this.pageContentData.phoneHubState; - case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: - return this.pageContentData.phoneHubCameraRollState; - case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: - return this.pageContentData.phoneHubNotificationsState; - case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: - return this.pageContentData.phoneHubTaskContinuationState; - case MultiDeviceFeature.WIFI_SYNC: - return this.pageContentData.wifiSyncState; - case MultiDeviceFeature.ECHE: - return this.pageContentData.phoneHubAppsState; - default: - return null; - } - }, - - /** - * Whether a host phone has been set by the user (not necessarily verified). - * @return {boolean} - */ - isHostSet() { - return [ - MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, - MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, - MultiDeviceSettingsMode.HOST_SET_VERIFIED, - ].includes(this.pageContentData.mode); - }, -}; - -/** @interface */ -export class MultiDeviceFeatureBehaviorInterface { - constructor() { - /** @type {!MultiDevicePageContentData} */ - this.pageContentData; - - /** @type {Object<string, number>} */ - this.MultiDeviceFeature; - } - - /** - * @return {boolean} - */ - isSuiteOn() {} - - /** - * @return {boolean} - */ - isSuiteAllowedByPolicy() {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureAllowedByPolicy(feature) {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureSupported(feature) {} - - /** - * @return {boolean} - */ - isPhoneHubOn() {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isPhoneHubSubFeature(feature) {} - - /** - * @return {boolean} - */ - isPhoneHubNotificationAccessProhibited() {} - - /** - * @return {boolean} - */ - isPhoneHubAppsAccessProhibited() {} - - /** - * @return {boolean} - */ - isPhoneHubCameraRollSetupRequired() {} - - /** - * @return {boolean} - */ - isPhoneHubAppsSetupRequired() {} - - /** - * @return {boolean} - */ - isPhoneHubNotificationsSetupRequired() {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {boolean} - */ - isFeatureStateEditable(feature) {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getFeatureName(feature) {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getIconName(feature) {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {string} - */ - getFeatureSummaryHtml(feature) {} - - /** - * @param {!MultiDeviceFeature} feature - * @return {?MultiDeviceFeatureState} - */ - getFeatureState(feature) {} - - /** - * @return {boolean} - */ - isHostSet() {} -} - -/** @polymerBehavior */ -export const MultiDeviceFeatureBehavior = [ - I18nBehavior, - MultiDeviceFeatureBehaviorImpl, -];
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.ts index 2863a354..9a06ebe 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_item.ts
@@ -19,24 +19,20 @@ import './multidevice_feature_toggle.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {castExists} from '../assert_extras.js'; -import {Constructor} from '../common/types'; import {routes} from '../os_route.js'; -import {RouteOriginMixin, RouteOriginMixinInterface} from '../route_origin_mixin.js'; +import {RouteOriginMixin} from '../route_origin_mixin.js'; import {Route, Router} from '../router.js'; import {MultiDeviceFeature} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; import {getTemplate} from './multidevice_feature_item.html.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {recordSmartLockToggleMetric, SmartLockToggleLocation} from './multidevice_metrics_logger.js'; const SettingsMultideviceFeatureItemElementBase = - mixinBehaviors( - [MultiDeviceFeatureBehavior], RouteOriginMixin(PolymerElement)) as - Constructor<PolymerElement&RouteOriginMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(RouteOriginMixin(PolymerElement)); export class SettingsMultideviceFeatureItemElement extends SettingsMultideviceFeatureItemElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_mixin.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_mixin.ts new file mode 100644 index 0000000..7c71a16 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_mixin.ts
@@ -0,0 +1,347 @@ +// 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. + +/** + * @fileoverview Polymer behavior for dealing with MultiDevice features. It is + * intended to facilitate passing data between elements in the MultiDevice page + * cleanly and concisely. It includes some constants and utility methods. + */ + +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {dedupingMixin, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {Constructor} from '../common/types.js'; + +import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus} from './multidevice_constants.js'; + +export interface MultiDeviceFeatureMixinInterface extends I18nMixinInterface { + pageContentData: MultiDevicePageContentData; + MultiDeviceFeature: MultiDeviceFeature; + getFeatureName(feature: MultiDeviceFeature): string; + getFeatureState(feature: MultiDeviceFeature): MultiDeviceFeatureState|null; + getFeatureSummaryHtml(feature: MultiDeviceFeature): TrustedHTML|string; + getIconName(feature: MultiDeviceFeature): string; + isFeatureAllowedByPolicy(feature: MultiDeviceFeature): boolean; + isFeatureStateEditable(feature: MultiDeviceFeature): boolean; + isFeatureSupported(feature: MultiDeviceFeature): boolean; + isHostSet(): boolean; + isPhoneHubAppsAccessProhibited(): boolean; + isPhoneHubAppsSetupRequired(): boolean; + isPhoneHubCameraRollSetupRequired(): boolean; + isPhoneHubNotificationAccessProhibited(): boolean; + isPhoneHubNotificationsSetupRequired(): boolean; + isPhoneHubOn(): boolean; + isPhoneHubSubFeature(feature: MultiDeviceFeature): boolean; + isSuiteAllowedByPolicy(): boolean; + isSuiteOn(): boolean; +} + +export const MultiDeviceFeatureMixin = dedupingMixin( + <T extends Constructor<PolymerElement>>(superClass: T): T& + Constructor<MultiDeviceFeatureMixinInterface> => { + const superClassBase = I18nMixin(superClass); + + class MultiDeviceFeatureMixinInternal extends superClassBase implements + MultiDeviceFeatureMixinInterface { + static get properties() { + return { + pageContentData: Object, + + /** + * Enum defined in multidevice_constants.js. Defined as a property + * to be used in Polymer HTML bindings and mirror the enum. + */ + MultiDeviceFeature: { + type: Object, + value: MultiDeviceFeature, + }, + }; + } + + // eslint-disable-next-line @typescript-eslint/naming-convention + MultiDeviceFeature: MultiDeviceFeature; + pageContentData: MultiDevicePageContentData; + + /** + * Whether the gatekeeper pref for the whole Better Together feature + * suite is on. + */ + isSuiteOn(): boolean { + return !!this.pageContentData && + this.pageContentData.betterTogetherState === + MultiDeviceFeatureState.ENABLED_BY_USER; + } + + /** + * Whether the gatekeeper pref for the whole Better Together feature + * suite is allowed by policy. + */ + isSuiteAllowedByPolicy(): boolean { + return !!this.pageContentData && + this.pageContentData.betterTogetherState !== + MultiDeviceFeatureState.PROHIBITED_BY_POLICY; + } + + /** + * Whether an individual feature is allowed by policy. + */ + isFeatureAllowedByPolicy(feature: MultiDeviceFeature): boolean { + return this.getFeatureState(feature) !== + MultiDeviceFeatureState.PROHIBITED_BY_POLICY; + } + + isFeatureSupported(feature: MultiDeviceFeature): boolean { + return ![MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK, + MultiDeviceFeatureState.NOT_SUPPORTED_BY_PHONE, + ].includes(this.getFeatureState(feature)!); + } + + /** + * Whether the top-level Phone Hub feature is enabled. + */ + isPhoneHubOn(): boolean { + return this.getFeatureState(MultiDeviceFeature.PHONE_HUB) === + MultiDeviceFeatureState.ENABLED_BY_USER; + } + + isPhoneHubSubFeature(feature: MultiDeviceFeature): boolean { + return [ + MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL, + MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS, + MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION, + MultiDeviceFeature.ECHE, + ].includes(feature); + } + + /** + * @return Whether or not Phone Hub notification access is + * prohibited (i.e., due to the user having a work profile). + */ + isPhoneHubNotificationAccessProhibited(): boolean { + return this.pageContentData && + this.pageContentData.notificationAccessStatus === + PhoneHubFeatureAccessStatus.PROHIBITED; + } + + /** + * @return Whether or not Phone Hub apps access is prohibited + * (i.e., due to the apps streaming policy of the phone is disabled). + */ + isPhoneHubAppsAccessProhibited(): boolean { + return this.pageContentData && + this.pageContentData.appsAccessStatus === + PhoneHubFeatureAccessStatus.PROHIBITED; + } + + /** + * Whether Camera Roll requires user action to finish set up. + */ + isPhoneHubCameraRollSetupRequired(): boolean { + return this.isFeatureSupported( + MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL) && + this.pageContentData.cameraRollAccessStatus === + PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && + this.isFeatureAllowedByPolicy( + MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL); + } + + /** + * Whether Apps requires user action to finish set up. + */ + isPhoneHubAppsSetupRequired(): boolean { + return this.isFeatureSupported(MultiDeviceFeature.ECHE) && + this.pageContentData.isPhoneHubPermissionsDialogSupported && + this.pageContentData.appsAccessStatus === + PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && + this.isFeatureAllowedByPolicy(MultiDeviceFeature.ECHE); + } + + /** + * Whether Notifications requires user action to finish set up. + */ + isPhoneHubNotificationsSetupRequired(): boolean { + return this.pageContentData.notificationAccessStatus === + PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED && + this.isFeatureAllowedByPolicy( + MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS); + } + + /** + * Whether the user is prevented from attempted to change a given + * feature. In the UI this corresponds to a disabled toggle. + */ + isFeatureStateEditable(feature: MultiDeviceFeature): boolean { + // The suite is off and the toggle corresponds to an individual + // feature (as opposed to the full suite). + if (feature !== MultiDeviceFeature.BETTER_TOGETHER_SUITE && + !this.isSuiteOn()) { + return false; + } + + // Cannot edit Phone Hub sub-feature toggles if the top-level Phone + // Hub feature is not enabled. + if (this.isPhoneHubSubFeature(feature) && !this.isPhoneHubOn()) { + return false; + } + + // Cannot edit the Phone Hub notification toggle if notification + // access is prohibited. + if (feature === MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS && + this.isPhoneHubNotificationAccessProhibited()) { + return false; + } + + // Cannot edit the Phone Hub apps toggle if apps access is + // prohibited. + if (feature === MultiDeviceFeature.ECHE && + this.isPhoneHubAppsAccessProhibited()) { + return false; + } + + return [ + MultiDeviceFeatureState.DISABLED_BY_USER, + MultiDeviceFeatureState.ENABLED_BY_USER, + ].includes(this.getFeatureState(feature)!); + } + + /** + * The localized string representing the name of the feature. + */ + getFeatureName(feature: MultiDeviceFeature): string { + switch (feature) { + case MultiDeviceFeature.BETTER_TOGETHER_SUITE: + return this.i18n('multideviceSetupItemHeading'); + case MultiDeviceFeature.INSTANT_TETHERING: + return this.i18n('multideviceInstantTetheringItemTitle'); + case MultiDeviceFeature.MESSAGES: + return this.i18n('multideviceAndroidMessagesItemTitle'); + case MultiDeviceFeature.SMART_LOCK: + return this.i18n('multideviceSmartLockItemTitle'); + case MultiDeviceFeature.PHONE_HUB: + return this.i18n('multidevicePhoneHubItemTitle'); + case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: + return this.i18n('multidevicePhoneHubCameraRollItemTitle'); + case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: + return this.i18n('multidevicePhoneHubNotificationsItemTitle'); + case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: + return this.i18n('multidevicePhoneHubTaskContinuationItemTitle'); + case MultiDeviceFeature.WIFI_SYNC: + return this.i18n('multideviceWifiSyncItemTitle'); + case MultiDeviceFeature.ECHE: + return this.i18n('multidevicePhoneHubAppsItemTitle'); + default: + return ''; + } + } + + /** + * The full icon name used provided by the containing iron-iconset-svg + * (i.e. [iron-iconset-svg name]:[SVG <g> tag id]) for a given feature. + */ + getIconName(feature: MultiDeviceFeature): string { + switch (feature) { + case MultiDeviceFeature.BETTER_TOGETHER_SUITE: + return 'os-settings:multidevice-better-together-suite'; + case MultiDeviceFeature.MESSAGES: + return 'os-settings:multidevice-messages'; + case MultiDeviceFeature.SMART_LOCK: + return 'os-settings:multidevice-smart-lock'; + case MultiDeviceFeature.PHONE_HUB: + case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: + case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: + case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: + case MultiDeviceFeature.ECHE: + return 'os-settings:multidevice-better-together-suite'; + case MultiDeviceFeature.WIFI_SYNC: + return 'os-settings:multidevice-wifi-sync'; + default: + return ''; + } + } + + /** + * The localized string providing a description or useful status + * information concerning a given feature. + */ + getFeatureSummaryHtml(feature: MultiDeviceFeature): TrustedHTML|string { + switch (feature) { + case MultiDeviceFeature.SMART_LOCK: + return this.i18nAdvanced('multideviceSmartLockItemSummary'); + case MultiDeviceFeature.INSTANT_TETHERING: + return this.i18nAdvanced( + 'multideviceInstantTetheringItemSummary'); + case MultiDeviceFeature.MESSAGES: + return this.i18nAdvanced('multideviceAndroidMessagesItemSummary'); + case MultiDeviceFeature.PHONE_HUB: + return this.i18nAdvanced('multidevicePhoneHubItemSummary'); + case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: + return this.i18nAdvanced( + 'multidevicePhoneHubCameraRollItemSummary'); + case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: + return this.i18nAdvanced( + 'multidevicePhoneHubNotificationsItemSummary'); + case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: + return this.i18nAdvanced( + 'multidevicePhoneHubTaskContinuationItemSummary'); + case MultiDeviceFeature.WIFI_SYNC: + return this.i18nAdvanced('multideviceWifiSyncItemSummary'); + case MultiDeviceFeature.ECHE: + return this.i18nAdvanced('multidevicePhoneHubAppsItemSummary'); + default: + return ''; + } + } + + /** + * Extracts the MultiDeviceFeatureState enum value describing the given + * feature from this.pageContentData. Returns null if the feature is not + * an accepted value (e.g. testing fake). + */ + getFeatureState(feature: MultiDeviceFeature): MultiDeviceFeatureState + |null { + if (!this.pageContentData) { + return null; + } + + switch (feature) { + case MultiDeviceFeature.BETTER_TOGETHER_SUITE: + return this.pageContentData.betterTogetherState; + case MultiDeviceFeature.INSTANT_TETHERING: + return this.pageContentData.instantTetheringState; + case MultiDeviceFeature.MESSAGES: + return this.pageContentData.messagesState; + case MultiDeviceFeature.SMART_LOCK: + return this.pageContentData.smartLockState; + case MultiDeviceFeature.PHONE_HUB: + return this.pageContentData.phoneHubState; + case MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL: + return this.pageContentData.phoneHubCameraRollState; + case MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS: + return this.pageContentData.phoneHubNotificationsState; + case MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION: + return this.pageContentData.phoneHubTaskContinuationState; + case MultiDeviceFeature.WIFI_SYNC: + return this.pageContentData.wifiSyncState; + case MultiDeviceFeature.ECHE: + return this.pageContentData.phoneHubAppsState; + default: + return null; + } + } + + /** + * Whether a host phone has been set by the user (not necessarily + * verified). + */ + isHostSet(): boolean { + return [ + MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, + MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, + MultiDeviceSettingsMode.HOST_SET_VERIFIED, + ].includes(this.pageContentData.mode); + } + } + + return MultiDeviceFeatureMixinInternal; + });
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.ts index 2e541c2..49fb4389 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_feature_toggle.ts
@@ -14,12 +14,10 @@ import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {Constructor} from '../common/types.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MultiDeviceFeature, MultiDeviceFeatureState} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_feature_toggle.html.js'; export interface SettingsMultideviceFeatureToggleElement { @@ -29,8 +27,7 @@ } const SettingsMultideviceFeatureToggleElementBase = - mixinBehaviors([MultiDeviceFeatureBehavior], PolymerElement) as - Constructor<PolymerElement&MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(PolymerElement); export class SettingsMultideviceFeatureToggleElement extends SettingsMultideviceFeatureToggleElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.js deleted file mode 100644 index 3172c52..0000000 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.js +++ /dev/null
@@ -1,69 +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. - -import {assertNotReached} from 'chrome://resources/ash/common/assert.js'; - -/** - * Location where Smart Lock was toggled on/off. - * @enum {number} - */ -export const SmartLockToggleLocation = { - MULTIDEVICE_PAGE: 0, - LOCK_SCREEN_SETTINGS: 1, -}; - -/** - * This enum is tied directly to a UMA enum defined in - * //tools/metrics/histograms/enums.xml, and should always reflect it (do not - * change one without changing the other). - * These values are persisted to logs. Entries should not be renumbered and - * numeric values should never be reused. - * @enum {number} - */ -const SmartLockToggle = { - ENABLED_ON_MULTIDEVICE_PAGE: 0, - DISABLED_ON_MULTIDEVICE_PAGE: 1, - ENABLED_ON_LOCK_SCREEN_SETTINGS: 2, - DISABLED_ON_LOCK_SCREEN_SETTINGS: 3, - MAX: 4, -}; - -const SmartLockToggleHistogramName = 'SmartLock.Toggle'; - -/** - * Records a metric for when Smart Lock is enabled/disabled in Settings - * indicating which toggle was used and whether Smart Lock was enabled or - * disabled. - * @param {SmartLockToggleLocation} smartLockToggleLocation - * @param {boolean} enabled - */ -export function recordSmartLockToggleMetric(smartLockToggleLocation, enabled) { - chrome.send('metricsHandler:recordInHistogram', [ - SmartLockToggleHistogramName, - getSmartLockToggleValue_(smartLockToggleLocation, enabled), - SmartLockToggle.MAX, - ]); -} - -/** - * Look up the correct SmartLock.Toggle historgram value to emit when Smart - * Lock is enabled/disabled in the given location in Settings. - * @param {SmartLockToggleLocation} smartLockToggleLocation - * @param {boolean} enabled - * @return {SmartLockToggle} - * @private - */ -function getSmartLockToggleValue_(smartLockToggleLocation, enabled) { - switch (smartLockToggleLocation) { - case SmartLockToggleLocation.MULTIDEVICE_PAGE: - return enabled ? SmartLockToggle.ENABLED_ON_MULTIDEVICE_PAGE : - SmartLockToggle.DISABLED_ON_MULTIDEVICE_PAGE; - case SmartLockToggleLocation.LOCK_SCREEN_SETTINGS: - return enabled ? SmartLockToggle.ENABLED_ON_LOCK_SCREEN_SETTINGS : - SmartLockToggle.DISABLED_ON_LOCK_SCREEN_SETTINGS; - } - - assertNotReached('Invalid smartLockToggleLocation'); - return SmartLockToggle.DISABLED_ON_MULTIDEVICE_PAGE; -}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.ts new file mode 100644 index 0000000..67c00e3d --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_metrics_logger.ts
@@ -0,0 +1,63 @@ +// 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. + +import {assertNotReached} from 'chrome://resources/js/assert_ts.js'; + +/** + * Location where Smart Lock was toggled on/off. + */ +export enum SmartLockToggleLocation { + MULTIDEVICE_PAGE = 0, + LOCK_SCREEN_SETTINGS = 1, +} + +/** + * This enum is tied directly to a UMA enum defined in + * //tools/metrics/histograms/enums.xml, and should always reflect it (do not + * change one without changing the other). + * These values are persisted to logs. Entries should not be renumbered and + * numeric values should never be reused. + */ +enum SmartLockToggle { + ENABLED_ON_MULTIDEVICE_PAGE = 0, + DISABLED_ON_MULTIDEVICE_PAGE = 1, + ENABLED_ON_LOCK_SCREEN_SETTINGS = 2, + DISABLED_ON_LOCK_SCREEN_SETTINGS = 3, + MAX = 4, +} + +const SMART_LOCK_TOGGLE_HISTOGRAM_NAME = 'SmartLock.Toggle'; + +/** + * Records a metric for when Smart Lock is enabled/disabled in Settings + * indicating which toggle was used and whether Smart Lock was enabled or + * disabled. + */ +export function recordSmartLockToggleMetric( + smartLockToggleLocation: SmartLockToggleLocation, enabled: boolean): void { + chrome.send('metricsHandler:recordInHistogram', [ + SMART_LOCK_TOGGLE_HISTOGRAM_NAME, + getSmartLockToggleValue(smartLockToggleLocation, enabled), + SmartLockToggle.MAX, + ]); +} + +/** + * Look up the correct SmartLock.Toggle historgram value to emit when Smart + * Lock is enabled/disabled in the given location in Settings. + */ +export function getSmartLockToggleValue( + smartLockToggleLocation: SmartLockToggleLocation, + enabled: boolean): SmartLockToggle { + switch (smartLockToggleLocation) { + case SmartLockToggleLocation.MULTIDEVICE_PAGE: + return enabled ? SmartLockToggle.ENABLED_ON_MULTIDEVICE_PAGE : + SmartLockToggle.DISABLED_ON_MULTIDEVICE_PAGE; + case SmartLockToggleLocation.LOCK_SCREEN_SETTINGS: + return enabled ? SmartLockToggle.ENABLED_ON_LOCK_SCREEN_SETTINGS : + SmartLockToggle.DISABLED_ON_LOCK_SCREEN_SETTINGS; + default: + assertNotReached('Invalid smartLockToggleLocation'); + } +}
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.ts similarity index 76% rename from chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js rename to chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.ts index 716e115..8a3bc30 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_notification_access_setup_dialog.ts
@@ -17,9 +17,10 @@ import '../os_settings_icons.html.js'; import '../../settings_shared.css.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; import {MultiDeviceFeature} from './multidevice_constants.js'; @@ -29,32 +30,30 @@ * Numerical values should not be changed because they must stay in sync with * notification_access_setup_operation.h, with the exception of * CONNECTION_REQUESTED. - * @enum {number} */ -export const NotificationAccessSetupOperationStatus = { - CONNECTION_REQUESTED: 0, - CONNECTING: 1, - TIMED_OUT_CONNECTING: 2, - CONNECTION_DISCONNECTED: 3, - SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE: 4, - COMPLETED_SUCCESSFULLY: 5, - NOTIFICATION_ACCESS_PROHIBITED: 6, -}; +export enum NotificationAccessSetupOperationStatus { + CONNECTION_REQUESTED = 0, + CONNECTING = 1, + TIMED_OUT_CONNECTING = 2, + CONNECTION_DISCONNECTED = 3, + SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE = 4, + COMPLETED_SUCCESSFULLY = 5, + NOTIFICATION_ACCESS_PROHIBITED = 6, +} -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {WebUIListenerBehaviorInterface} - */ +interface SettingsMultideviceNotificationAccessSetupDialogElement { + $: { + dialog: CrDialogElement, + }; +} + const SettingsMultideviceNotificationAccessSetupDialogElementBase = - mixinBehaviors([I18nBehavior, WebUIListenerBehavior], PolymerElement); + WebUiListenerMixin(I18nMixin(PolymerElement)); -/** @polymer */ class SettingsMultideviceNotificationAccessSetupDialogElement extends SettingsMultideviceNotificationAccessSetupDialogElementBase { static get is() { - return 'settings-multidevice-notification-access-setup-dialog'; + return 'settings-multidevice-notification-access-setup-dialog' as const; } static get template() { @@ -65,60 +64,51 @@ return { /** * A null |setupState_| indicates that the operation has not yet started. - * @private {?NotificationAccessSetupOperationStatus} */ setupState_: { type: Number, value: null, }, - /** @private */ title_: { type: String, computed: 'getTitle_(setupState_)', }, - /** @private */ description_: { type: String, computed: 'getDescription_(setupState_)', }, - /** @private */ hasNotStartedSetupAttempt_: { type: Boolean, computed: 'computeHasNotStartedSetupAttempt_(setupState_)', reflectToAttribute: true, }, - /** @private */ isSetupAttemptInProgress_: { type: Boolean, computed: 'computeIsSetupAttemptInProgress_(setupState_)', reflectToAttribute: true, }, - /** @private */ didSetupAttemptFail_: { type: Boolean, computed: 'computeDidSetupAttemptFail_(setupState_)', reflectToAttribute: true, }, - /** @private */ hasCompletedSetupSuccessfully_: { type: Boolean, computed: 'computeHasCompletedSetupSuccessfully_(setupState_)', reflectToAttribute: true, }, - /** @private */ isNotificationAccessProhibited_: { type: Boolean, computed: 'computeIsNotificationAccessProhibited_(setupState_)', }, - /** @private */ shouldShowSetupInstructionsSeparately_: { type: Boolean, computed: 'computeShouldShowSetupInstructionsSeparately_(' + @@ -128,28 +118,34 @@ }; } + private browserProxy_: MultiDeviceBrowserProxy; + private description_: string; + private didSetupAttemptFail_: boolean; + private hasCompletedSetupSuccessfully_: boolean; + private hasNotStartedSetupAttempt_: boolean; + private isNotificationAccessProhibited_: boolean; + private isSetupAttemptInProgress_: boolean; + private setupState_: NotificationAccessSetupOperationStatus|null; + private shouldShowSetupInstructionsSeparately_: boolean; + private title_: string; + constructor() { super(); - /** @private {!MultiDeviceBrowserProxy} */ this.browserProxy_ = MultiDeviceBrowserProxyImpl.getInstance(); } - /** @override */ - connectedCallback() { + override connectedCallback(): void { super.connectedCallback(); - this.addWebUIListener( + this.addWebUiListener( 'settings.onNotificationAccessSetupStatusChanged', this.onSetupStateChanged_.bind(this)); this.$.dialog.showModal(); } - /** - * @param {!NotificationAccessSetupOperationStatus} setupState - * @private - */ - onSetupStateChanged_(setupState) { + private onSetupStateChanged_( + setupState: NotificationAccessSetupOperationStatus): void { this.setupState_ = setupState; if (this.setupState_ === NotificationAccessSetupOperationStatus.COMPLETED_SUCCESSFULLY) { @@ -158,19 +154,11 @@ } } - /** - * @return {boolean} - * @private - */ - computeHasNotStartedSetupAttempt_() { + private computeHasNotStartedSetupAttempt_(): boolean { return this.setupState_ === null; } - /** - * @return {boolean} - * @private - */ - computeIsSetupAttemptInProgress_() { + private computeIsSetupAttemptInProgress_(): boolean { return this.setupState_ === NotificationAccessSetupOperationStatus .SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE || @@ -180,29 +168,17 @@ NotificationAccessSetupOperationStatus.CONNECTION_REQUESTED; } - /** - * @return {boolean} - * @private - */ - computeHasCompletedSetupSuccessfully_() { + private computeHasCompletedSetupSuccessfully_(): boolean { return this.setupState_ === NotificationAccessSetupOperationStatus.COMPLETED_SUCCESSFULLY; } - /** - * @return {boolean} - * @private - */ - computeIsNotificationAccessProhibited_() { + private computeIsNotificationAccessProhibited_(): boolean { return this.setupState_ === NotificationAccessSetupOperationStatus.NOTIFICATION_ACCESS_PROHIBITED; } - /** - * @return {boolean} - * @private - * */ - computeDidSetupAttemptFail_() { + private computeDidSetupAttemptFail_(): boolean { return this.setupState_ === NotificationAccessSetupOperationStatus.TIMED_OUT_CONNECTING || this.setupState_ === @@ -212,10 +188,9 @@ } /** - * @return {boolean} Whether to show setup instructions in its own section. - * @private + * @return Whether to show setup instructions in its own section. */ - computeShouldShowSetupInstructionsSeparately_() { + private computeShouldShowSetupInstructionsSeparately_(): boolean { return this.setupState_ === null || this.setupState_ === NotificationAccessSetupOperationStatus.CONNECTION_REQUESTED || @@ -225,29 +200,22 @@ this.setupState_ === NotificationAccessSetupOperationStatus.CONNECTING; } - /** @private */ - attemptNotificationSetup_() { + private attemptNotificationSetup_(): void { this.browserProxy_.attemptNotificationSetup(); this.setupState_ = NotificationAccessSetupOperationStatus.CONNECTION_REQUESTED; } - /** @private */ - onCancelClicked_() { + private onCancelClicked_(): void { this.browserProxy_.cancelNotificationSetup(); this.$.dialog.close(); } - /** @private */ - onDoneOrCloseButtonClicked_() { + private onDoneOrCloseButtonClicked_(): void { this.$.dialog.close(); } - /** - * @return {string} The title of the dialog. - * @private - */ - getTitle_() { + private getTitle_(): string { if (this.setupState_ === null) { return this.i18n('multideviceNotificationAccessSetupAckTitle'); } @@ -277,10 +245,9 @@ } /** - * @return {string} A description about the connection attempt state. - * @private + * @return A description about the connection attempt state. */ - getDescription_() { + private getDescription_(): TrustedHTML|string { if (this.setupState_ === null) { return this.i18n('multideviceNotificationAccessSetupAckSummary'); } @@ -310,22 +277,14 @@ } } - /** - * @return {boolean} - * @private - */ - shouldShowCancelButton_() { + private shouldShowCancelButton_(): boolean { return this.setupState_ !== NotificationAccessSetupOperationStatus.COMPLETED_SUCCESSFULLY && this.setupState_ !== NotificationAccessSetupOperationStatus.NOTIFICATION_ACCESS_PROHIBITED; } - /** - * @return {boolean} - * @private - */ - shouldShowTryAgainButton_() { + private shouldShowTryAgainButton_(): boolean { return this.setupState_ === NotificationAccessSetupOperationStatus.TIMED_OUT_CONNECTING || this.setupState_ === @@ -333,6 +292,13 @@ } } +declare global { + interface HTMLElementTagNameMap { + [SettingsMultideviceNotificationAccessSetupDialogElement.is]: + SettingsMultideviceNotificationAccessSetupDialogElement; + } +} + customElements.define( SettingsMultideviceNotificationAccessSetupDialogElement.is, SettingsMultideviceNotificationAccessSetupDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.ts similarity index 73% rename from chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js rename to chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.ts index 5a5f329f..6587596 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.ts
@@ -17,54 +17,44 @@ import './multidevice_permissions_setup_dialog.js'; import './multidevice_subpage.js'; -import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; +import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {beforeNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; +import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js'; import {NearbyShareSettingsBehavior, NearbyShareSettingsBehaviorInterface} from '../../shared/nearby_share_settings_behavior.js'; -import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; +import {Constructor} from '../common/types.js'; +import {DeepLinkingMixin, DeepLinkingMixinInterface} from '../deep_linking_mixin.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; -import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {RouteObserverMixin, RouteObserverMixinInterface} from '../route_observer_mixin.js'; import {Route, Router} from '../router.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; -import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus} from './multidevice_constants.js'; +import {MultiDeviceFeatureMixin, MultiDeviceFeatureMixinInterface} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_page.html.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {DeepLinkingBehaviorInterface} - * @implements {RouteObserverBehaviorInterface} - * @implements {MultiDeviceFeatureBehaviorInterface} - * @implements {WebUIListenerBehaviorInterface} - * @implements {PrefsBehaviorInterface} - * @implements {NearbyShareSettingsBehaviorInterface} - * @implements {I18nBehaviorInterface} - */ -const SettingsMultidevicePageElementBase = mixinBehaviors( - [ - DeepLinkingBehavior, - RouteObserverBehavior, - MultiDeviceFeatureBehavior, - WebUIListenerBehavior, - PrefsBehavior, - NearbyShareSettingsBehavior, - I18nBehavior, - ], - PolymerElement); +import TokenInfo = chrome.quickUnlockPrivate.TokenInfo; -/** @polymer */ +const SettingsMultidevicePageElementBase = + mixinBehaviors( + [ + NearbyShareSettingsBehavior, + ], + MultiDeviceFeatureMixin(RouteObserverMixin(DeepLinkingMixin( + PrefsMixin(WebUiListenerMixin(PolymerElement)))))) as + Constructor<PolymerElement&WebUiListenerMixinInterface&PrefsMixinInterface& + DeepLinkingMixinInterface&RouteObserverMixinInterface& + MultiDeviceFeatureMixinInterface& + NearbyShareSettingsBehaviorInterface>; + class SettingsMultidevicePageElement extends SettingsMultidevicePageElementBase { static get is() { - return 'settings-multidevice-page'; + return 'settings-multidevice-page' as const; } static get template() { @@ -73,19 +63,15 @@ static get properties() { return { - /** Preferences state. */ - prefs: {type: Object}, - /** * A Map specifying which element should be focused when exiting a * subpage. The key of the map holds a Route path, and the value holds a * query selector that identifies the desired element. - * @private {!Map<string, string>} */ focusConfig_: { type: Object, value() { - const map = new Map(); + const map = new Map<string, string>(); if (routes.MULTIDEVICE_FEATURES) { map.set( routes.MULTIDEVICE_FEATURES.path, @@ -97,7 +83,6 @@ /** * Authentication token provided by password-prompt-dialog. - * @private {!chrome.quickUnlockPrivate.TokenInfo|undefined} */ authToken_: { type: Object, @@ -109,20 +94,17 @@ * is required. This value is initialized to null, is set when the * password dialog is opened, and is reset to null again once the password * dialog is closed. - * @private {?MultiDeviceFeature} */ featureToBeEnabledOnceAuthenticated_: { type: Number, value: null, }, - /** @private {boolean} */ showPasswordPromptDialog_: { type: Boolean, value: false, }, - /** @private */ showPhonePermissionSetupDialog_: { type: Boolean, value: false, @@ -131,7 +113,6 @@ /** * Whether or not Nearby Share is supported which controls if the Nearby * Share settings and subpage are accessible. - * @private {boolean} */ isNearbyShareSupported_: { type: Boolean, @@ -140,14 +121,12 @@ }, }, - /** @private */ shouldEnableNearbyShareBackgroundScanningRevamp_: { type: Boolean, computed: `computeShouldEnableNearbyShareBackgroundScanningRevamp_( settings.isFastInitiationHardwareSupported)`, }, - /** @private */ isSettingsRetreived: { type: Boolean, value: false, @@ -155,11 +134,10 @@ /** * Used by DeepLinkingBehavior to focus this page's deep links. - * @type {!Set<!Setting>} */ supportedSettingIds: { type: Object, - value: () => new Set([ + value: () => new Set<Setting>([ Setting.kSetUpMultiDevice, Setting.kVerifyMultiDeviceSetup, Setting.kMultiDeviceOnOff, @@ -169,7 +147,6 @@ /** * Reflects the password sub-dialog property. - * @private */ isPasswordDialogShowing_: { type: Boolean, @@ -178,14 +155,12 @@ /** * Reflects the pin number sub-dialog property. - * @private */ isPinNumberDialogShowing_: { type: Boolean, value: false, }, - /** @private */ isChromeosScreenLockEnabled_: { type: Boolean, value: function() { @@ -193,7 +168,6 @@ }, }, - /** @private */ isPhoneScreenLockEnabled_: { type: Boolean, value: function() { @@ -203,38 +177,44 @@ }; } + isSettingsRetreived: boolean; + private authToken_: TokenInfo|undefined; + private browserProxy_: MultiDeviceBrowserProxy; + private featureToBeEnabledOnceAuthenticated_: MultiDeviceFeature|null; + private isChromeosScreenLockEnabled_: boolean; + private isNearbyShareSupported_: boolean; + private isPasswordDialogShowing_: boolean; + private isPhoneScreenLockEnabled_: boolean; + private isPinNumberDialogShowing_: boolean; + private shouldEnableNearbyShareBackgroundScanningRevamp_: boolean; + private showPasswordPromptDialog_: boolean; + private showPhonePermissionSetupDialog_: boolean; + constructor() { super(); - /** @private {?MultiDeviceBrowserProxy} */ this.browserProxy_ = MultiDeviceBrowserProxyImpl.getInstance(); } - /** @override */ - ready() { + override ready(): void { super.ready(); this.addEventListener('close', this.onDialogClose_); this.addEventListener('feature-toggle-clicked', (event) => { - this.onFeatureToggleClicked_( - /** - * @type {!CustomEvent<!{feature: !MultiDeviceFeature, enabled: - * boolean}>} - */ - (event)); + this.onFeatureToggleClicked_(event); }); this.addEventListener( 'forget-device-requested', this.onForgetDeviceRequested_); this.addEventListener( 'permission-setup-requested', this.onPermissionSetupRequested_); - this.addWebUIListener( + this.addWebUiListener( 'settings.updateMultidevicePageContentData', - (data) => this.onPageContentDataChanged_(data)); - this.addWebUIListener( + this.onPageContentDataChanged_.bind(this)); + this.addWebUiListener( 'settings.OnEnableScreenLockChanged', this.onEnableScreenLockChanged_.bind(this)); - this.addWebUIListener( + this.addWebUiListener( 'settings.OnScreenLockStatusChanged', this.onScreenLockStatusChanged_.bind(this)); @@ -245,17 +225,14 @@ /** * Overridden from NearbyShareSettingsBehavior. */ - onSettingsRetrieved() { + override onSettingsRetrieved(): void { this.isSettingsRetreived = true; } /** * Overridden from RouteObserverBehavior. - * @param {!Route} route - * @param {!Route=} oldRoute - * @protected */ - currentRouteChanged(route, oldRoute) { + override currentRouteChanged(route: Route): void { this.leaveNestedPageIfNoHostIsSet_(); // Does not apply to this page. @@ -266,20 +243,12 @@ this.attemptDeepLink(); } - /** - * @return {string} Translated item label. - * @private - */ - getLabelText_() { + private getLabelText_(): string { return this.pageContentData.hostDeviceName || this.i18n('multideviceSetupItemHeading'); } - /** - * @return {string} Translated sublabel with a "learn more" link. - * @private - */ - getSubLabelInnerHtml_() { + private getSubLabelInnerHtml_(): TrustedHTML|string { if (!this.isSuiteAllowedByPolicy()) { return this.i18nAdvanced('multideviceSetupSummary'); } @@ -298,11 +267,7 @@ } } - /** - * @return {string} Translated button text. - * @private - */ - getButtonText_() { + private getButtonText_(): string { switch (this.pageContentData.mode) { case MultiDeviceSettingsMode.NO_HOST_SET: return this.i18n('multideviceSetupButton'); @@ -315,11 +280,7 @@ } } - /** - * @return {string} Translated button a11y label. - * @private - */ - getButtonA11yLabel_() { + private getButtonA11yLabel_(): string { switch (this.pageContentData.mode) { case MultiDeviceSettingsMode.NO_HOST_SET: return this.i18n('multideviceSetupButtonA11yLabel'); @@ -332,12 +293,7 @@ } } - /** - * @return {string} "true" or "false" indicating whether the text box - * should be aria-hidden or not. - * @private - */ - getTextAriaHidden_() { + private getTextAriaHidden_(): string { // When host is set and verified, we only show subpage arrow button and // toggle. In this case, we avoid the navigation stops on the text to make // navigating easier. The arrow button is labeled and described by the text, @@ -347,11 +303,7 @@ MultiDeviceSettingsMode.HOST_SET_VERIFIED); } - /** - * @return {boolean} - * @private - */ - shouldShowButton_() { + private shouldShowButton_(): boolean { return [ MultiDeviceSettingsMode.NO_HOST_SET, MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, @@ -359,11 +311,7 @@ ].includes(this.pageContentData.mode); } - /** - * @return {boolean} - * @private - */ - shouldShowToggle_() { + private shouldShowToggle_(): boolean { return this.pageContentData.mode === MultiDeviceSettingsMode.HOST_SET_VERIFIED; } @@ -371,26 +319,19 @@ /** * Whether to show the separator bar and, if the state calls for a chevron * (a.k.a. subpage arrow) routing to the subpage, the chevron. - * @return {boolean} - * @private */ - shouldShowSeparatorAndSubpageArrow_() { + private shouldShowSeparatorAndSubpageArrow_(): boolean { return this.pageContentData.mode !== MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS; } - /** - * @return {boolean} - * @private - */ - doesClickOpenSubpage_() { + private doesClickOpenSubpage_(): boolean { return this.isHostSet(); } - /** @private */ - handleItemClick_(event) { + private handleItemClick_(event: Event): void { // We do not open the subpage if the click was on a link. - if (event.composedPath()[0].tagName === 'A') { + if ((event.composedPath()[0] as HTMLElement).tagName === 'A') { event.stopPropagation(); return; } @@ -402,8 +343,7 @@ Router.getInstance().navigateTo(routes.MULTIDEVICE_FEATURES); } - /** @private */ - handleButtonClick_(event) { + private handleButtonClick_(event: Event): void { event.stopPropagation(); switch (this.pageContentData.mode) { case MultiDeviceSettingsMode.NO_HOST_SET: @@ -418,21 +358,20 @@ } } - /** @private */ - openPasswordPromptDialog_() { + private openPasswordPromptDialog_(): void { this.showPasswordPromptDialog_ = true; } - onDialogClose_(event) { + private onDialogClose_(event: Event): void { event.stopPropagation(); if (event.composedPath().some( - element => element.id === 'multidevicePasswordPrompt')) { + element => + (element as HTMLElement).id === 'multidevicePasswordPrompt')) { this.onPasswordPromptDialogClose_(); } } - /** @private */ - onPasswordPromptDialogClose_() { + private onPasswordPromptDialogClose_(): void { // The password prompt should only be shown when there is a feature waiting // to be enabled. assert(this.featureToBeEnabledOnceAuthenticated_ !== null); @@ -465,14 +404,10 @@ * Attempt to enable the provided feature. If not authenticated (i.e., * |authToken_| is invalid), display the password prompt to begin the * authentication process. - * - * @param {!CustomEvent<!{ - * feature: !MultiDeviceFeature, - * enabled: boolean - * }>} event - * @private */ - onFeatureToggleClicked_(event) { + private onFeatureToggleClicked_( + event: CustomEvent<{feature: MultiDeviceFeature, enabled: boolean}>): + void { const feature = event.detail.feature; const enabled = event.detail.enabled; @@ -491,7 +426,6 @@ switch (this.pageContentData.notificationAccessStatus) { case PhoneHubFeatureAccessStatus.PROHIBITED: assertNotReached('Cannot enable notification access; prohibited'); - return; case PhoneHubFeatureAccessStatus.AVAILABLE_BUT_NOT_GRANTED: this.showPhonePermissionSetupDialog_ = true; return; @@ -507,12 +441,8 @@ recordSettingChange(); } - /** - * @param {!MultiDeviceFeature} feature The feature to enable. - * @return {boolean} Whether authentication is required to enable the feature. - * @private - */ - isAuthenticationRequiredToEnable_(feature) { + private isAuthenticationRequiredToEnable_(feature: MultiDeviceFeature): + boolean { // Enabling SmartLock always requires authentication. if (feature === MultiDeviceFeature.SMART_LOCK) { return true; @@ -537,24 +467,21 @@ MultiDeviceFeatureState.UNAVAILABLE_INSUFFICIENT_SECURITY; } - /** @private */ - onForgetDeviceRequested_() { + private onForgetDeviceRequested_(): void { this.browserProxy_.removeHostDevice(); recordSettingChange(); Router.getInstance().navigateTo(routes.MULTIDEVICE); } - /** @private */ - onPermissionSetupRequested_() { + private onPermissionSetupRequested_(): void { this.showPhonePermissionSetupDialog_ = true; } /** * Checks if the user is in a nested page without a host set and, if so, * navigates them back to the main page. - * @private */ - leaveNestedPageIfNoHostIsSet_() { + private leaveNestedPageIfNoHostIsSet_(): void { // Wait for data to arrive. if (!this.pageContentData) { return; @@ -579,11 +506,8 @@ } } - /** - * @param {!MultiDevicePageContentData} newData - * @private - */ - onInitialPageContentDataFetched_(newData) { + private onInitialPageContentDataFetched_(newData: MultiDevicePageContentData): + void { this.onPageContentDataChanged_(newData); // Show the notification access dialog if the url contains the correct @@ -596,28 +520,16 @@ } } - /** - * @param {!MultiDevicePageContentData} newData - * @private - */ - onPageContentDataChanged_(newData) { + private onPageContentDataChanged_(newData: MultiDevicePageContentData): void { this.pageContentData = newData; this.leaveNestedPageIfNoHostIsSet_(); } - /** - * @param {!CustomEvent<!chrome.quickUnlockPrivate.TokenInfo>} e - * @private - */ - onTokenObtained_(e) { + private onTokenObtained_(e: CustomEvent<TokenInfo>): void { this.authToken_ = e.detail; } - /** - * @return {boolean} Whether Nearby Share is disallowed by enterprise policy. - * @private - */ - isNearbyShareDisallowedByPolicy_() { + private isNearbyShareDisallowedByPolicy_(): boolean { if (!this.pageContentData) { return false; } @@ -625,58 +537,28 @@ return this.pageContentData.isNearbyShareDisallowedByPolicy; } - /** - * @param {boolean} state boolean state that determines which string to show - * @param {string} onstr string to show when state is true - * @param {string} offstr string to show when state is false - * @return {string} localized string - * @private - */ - getOnOffString_(state, onstr, offstr) { + private getOnOffString_(state: boolean, onstr: string, offstr: string): + string { return state ? onstr : offstr; } - /** - * @param {boolean} isOnboardingComplete - * @return {boolean} - * @private - */ - showNearbyShareToggle_(isOnboardingComplete) { + private showNearbyShareToggle_(isOnboardingComplete: boolean): boolean { return isOnboardingComplete || this.isNearbyShareDisallowedByPolicy_(); } - /** - * @param {boolean} isOnboardingComplete - * @return {boolean} - * @private - */ - showNearbyShareSetupButton_(isOnboardingComplete) { + private showNearbyShareSetupButton_(isOnboardingComplete: boolean): boolean { return !isOnboardingComplete && !this.isNearbyShareDisallowedByPolicy_(); } - /** - * @param {boolean} isOnboardingComplete - * @return {boolean} - * @private - */ - showNearbyShareOnOffString_(isOnboardingComplete) { + private showNearbyShareOnOffString_(isOnboardingComplete: boolean): boolean { return isOnboardingComplete && !this.isNearbyShareDisallowedByPolicy_(); } - /** - * @param {boolean} isOnboardingComplete - * @return {boolean} - * @private - */ - showNearbyShareDescription_(isOnboardingComplete) { + private showNearbyShareDescription_(isOnboardingComplete: boolean): boolean { return !isOnboardingComplete || this.isNearbyShareDisallowedByPolicy_(); } - /** - * @param {!Event} event - * @private - */ - nearbyShareClick_(event) { + private nearbyShareClick_(): void { if (this.isNearbyShareDisallowedByPolicy_()) { return; } @@ -712,31 +594,21 @@ Router.getInstance().navigateTo(routes.NEARBY_SHARE, params); } - - /** - * @return {boolean} - * @private - */ - showPermissionsSetupDialog_() { + private showPermissionsSetupDialog_(): boolean { if (!this.showPhonePermissionSetupDialog_) { return false; } return !this.pageContentData.isPhoneHubPermissionsDialogSupported; } - /** - * @return {boolean} - * @private - */ - showNewPermissionsSetupDialog_() { + private showNewPermissionsSetupDialog_(): boolean { if (!this.showPhonePermissionSetupDialog_) { return false; } return this.pageContentData.isPhoneHubPermissionsDialogSupported; } - /** @private */ - onHidePhonePermissionsSetupDialog_() { + private onHidePhonePermissionsSetupDialog_(): void { // Don't close the main dialog if the pin number sub-dialog is open. if (this.isPinNumberDialogShowing_) { this.isPinNumberDialogShowing_ = false; @@ -750,14 +622,13 @@ this.showPhonePermissionSetupDialog_ = false; } - /** @private */ - onPinNumberSelected_(e) { + private onPinNumberSelected_(e: CustomEvent<{isPinNumberSelected: boolean}>): + void { assert(typeof e.detail.isPinNumberSelected === 'boolean'); this.isPinNumberDialogShowing_ = e.detail.isPinNumberSelected; } - /** @private */ - handleNearbySetUpClick_() { + private handleNearbySetUpClick_(): void { const params = new URLSearchParams(); params.set('onboarding', ''); // Set by metrics to determine entrypoint for onboarding @@ -765,14 +636,9 @@ Router.getInstance().navigateTo(routes.NEARBY_SHARE, params); } - /** - * @param {boolean} isNearbySharingEnabled - * @param {boolean} shouldEnableNearbyShareBackgroundScanningRevamp - * @return {boolean} - * @private - */ - shouldShowNearbyShareSubpageArrow_( - isNearbySharingEnabled, shouldEnableNearbyShareBackgroundScanningRevamp) { + private shouldShowNearbyShareSubpageArrow_( + isNearbySharingEnabled: boolean, + shouldEnableNearbyShareBackgroundScanningRevamp: boolean): boolean { // If the background scanning feature is enabled but Nearby Sharing is // disabled the subpage should be accessible. The subpage is also accessible // pre-onboarding. @@ -781,23 +647,16 @@ !this.isNearbyShareDisallowedByPolicy_(); } - /** - * @param {boolean} is_hardware_supported - * @return {boolean} - * @private - */ - computeShouldEnableNearbyShareBackgroundScanningRevamp_( - is_hardware_supported) { - return is_hardware_supported; + private computeShouldEnableNearbyShareBackgroundScanningRevamp_( + isHardwareSupported: boolean): boolean { + return isHardwareSupported; } /** * Whether the combined setup for Notifications and Camera Roll is supported * on the connected phone. - * @return {boolean} - * @private */ - isCombinedSetupSupported_() { + private isCombinedSetupSupported_(): boolean { return this.pageContentData.isPhoneHubFeatureCombinedSetupSupported; } @@ -805,10 +664,8 @@ * Due to loadTimeData is not guaranteed to be consistent between page * refreshes, use FireWebUIListener() to update dynamic value of screen lock * setting. - * @param {boolean} enabled - * @private */ - onEnableScreenLockChanged_(enabled) { + private onEnableScreenLockChanged_(enabled: boolean): void { this.isChromeosScreenLockEnabled_ = enabled; } @@ -816,13 +673,17 @@ * Due to loadTimeData is not guaranteed to be consistent between page * refreshes, use FireWebUIListener() to update dynamic value of screen lock * status of phone. - * @param {boolean} enabled - * @private */ - onScreenLockStatusChanged_(enabled) { + private onScreenLockStatusChanged_(enabled: boolean): void { this.isPhoneScreenLockEnabled_ = enabled; } } +declare global { + interface HTMLElementTagNameMap { + [SettingsMultidevicePageElement.is]: SettingsMultidevicePageElement; + } +} + customElements.define( SettingsMultidevicePageElement.is, SettingsMultidevicePageElement);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.ts similarity index 81% rename from chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js rename to chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.ts index 7d00f40..a78d65e 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_permissions_setup_dialog.ts
@@ -19,12 +19,14 @@ import '../os_settings_icons.html.js'; import '../../settings_shared.css.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {Constructor} from '../common/types.js'; import {LockStateBehavior, LockStateBehaviorInterface} from '../os_people_page/lock_state_behavior.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; @@ -38,36 +40,34 @@ * FAILED_OR_CANCELLED, we will abort all setup processes. If * PermissionsSetupStatus is COMPLETED_USER_REJECTED, we will proceed to the * next setup process. - * @enum {number} */ -export const PermissionsSetupStatus = { - CONNECTION_REQUESTED: 0, - CONNECTING: 1, - TIMED_OUT_CONNECTING: 2, - CONNECTION_DISCONNECTED: 3, - SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE: 4, - COMPLETED_SUCCESSFULLY: 5, - NOTIFICATION_ACCESS_PROHIBITED: 6, - COMPLETED_USER_REJECTED: 7, - FAILED_OR_CANCELLED: 8, - CAMERA_ROLL_GRANTED_NOTIFICATION_REJECTED: 9, - CAMERA_ROLL_REJECTED_NOTIFICATION_GRANTED: 10, - CONNECTION_ESTABLISHED: 11, -}; +export enum PermissionsSetupStatus { + CONNECTION_REQUESTED = 0, + CONNECTING = 1, + TIMED_OUT_CONNECTING = 2, + CONNECTION_DISCONNECTED = 3, + SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE = 4, + COMPLETED_SUCCESSFULLY = 5, + NOTIFICATION_ACCESS_PROHIBITED = 6, + COMPLETED_USER_REJECTED = 7, + FAILED_OR_CANCELLED = 8, + CAMERA_ROLL_GRANTED_NOTIFICATION_REJECTED = 9, + CAMERA_ROLL_REJECTED_NOTIFICATION_GRANTED = 10, + CONNECTION_ESTABLISHED = 11, +} /** * Numerical values the flow of dialog set up progress. - * @enum {number} */ -export const SetupFlowStatus = { - INTRO: 0, - SET_LOCKSCREEN: 1, - WAIT_FOR_PHONE_NOTIFICATION: 2, - WAIT_FOR_PHONE_APPS: 3, - WAIT_FOR_PHONE_COMBINED: 4, - WAIT_FOR_CONNECTION: 5, - FINISHED: 6, -}; +export enum SetupFlowStatus { + INTRO = 0, + SET_LOCKSCREEN = 1, + WAIT_FOR_PHONE_NOTIFICATION = 2, + WAIT_FOR_PHONE_APPS = 3, + WAIT_FOR_PHONE_COMBINED = 4, + WAIT_FOR_CONNECTION = 5, + FINISHED = 6, +} /** * Indicates that the onboarding flow includes Phone Hub Notification feature. @@ -84,26 +84,25 @@ */ export const APPS_FEATURE = 1 << 2; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {WebUIListenerBehaviorInterface} - * @implements {LockStateBehaviorInterface} - */ -const SettingsMultidevicePermissionsSetupDialogElementBase = mixinBehaviors( - [ - I18nBehavior, - WebUIListenerBehavior, - LockStateBehavior, - ], - PolymerElement); +interface SettingsMultidevicePermissionsSetupDialogElement { + $: { + dialog: CrDialogElement, + }; +} -/** @polymer */ +const SettingsMultidevicePermissionsSetupDialogElementBase = + mixinBehaviors( + [ + LockStateBehavior, + ], + WebUiListenerMixin(I18nMixin(PolymerElement))) as + Constructor<PolymerElement&I18nMixinInterface&WebUiListenerMixinInterface& + LockStateBehaviorInterface>; + class SettingsMultidevicePermissionsSetupDialogElement extends SettingsMultidevicePermissionsSetupDialogElementBase { static get is() { - return 'settings-multidevice-permissions-setup-dialog'; + return 'settings-multidevice-permissions-setup-dialog' as const; } static get template() { @@ -112,7 +111,6 @@ static get properties() { return { - /** @private {!PhoneHubPermissionsSetupFlowScreens} */ setupScreen_: { type: Number, computed: 'getCurrentScreen_(setupState_, flowState_)', @@ -120,75 +118,62 @@ /** * A null |setupState_| indicates that the operation has not yet started. - * @private {?PermissionsSetupStatus} */ setupState_: { type: Number, value: null, }, - /** @private */ title_: { type: String, computed: 'getTitle_(setupState_, flowState_)', }, - /** @private */ description_: { type: String, computed: 'getDescription_(setupState_, flowState_)', }, - /** @private */ hasStartedSetupAttempt_: { type: Boolean, computed: 'computeHasStartedSetupAttempt_(flowState_)', reflectToAttribute: true, }, - /** @private */ isSetupAttemptInProgress_: { type: Boolean, computed: 'computeIsSetupAttemptInProgress_(setupState_)', reflectToAttribute: true, }, - /** @private */ isSetupScreenLockInProgress_: { type: Boolean, computed: 'computeIsSetupScreenLockInProgress_(flowState_)', reflectToAttribute: true, }, - /** @private */ didSetupAttemptFail_: { type: Boolean, computed: 'computeDidSetupAttemptFail_(setupState_)', reflectToAttribute: true, }, - /** @private */ hasCompletedSetup_: { type: Boolean, computed: 'computeHasCompletedSetup_(setupState_)', reflectToAttribute: true, }, - /** @private */ isNotificationAccessProhibited_: { type: Boolean, computed: 'computeIsNotificationAccessProhibited_(setupState_)', }, - /** - * @private {?SetupFlowStatus} - */ flowState_: { type: Number, value: SetupFlowStatus.INTRO, }, - /** @private */ isScreenLockEnabled_: { type: Boolean, value: false, @@ -222,22 +207,30 @@ }, /** Whether this dialog should show Camera Roll info */ - showCameraRoll: - {type: Boolean, value: false, observer: 'onAccessStateChanged_'}, + showCameraRoll: { + type: Boolean, + value: false, + observer: 'onAccessStateChanged_', + }, /** Whether this dialog should show Notifications info */ - showNotifications: - {type: Boolean, value: false, observer: 'onAccessStateChanged_'}, + showNotifications: { + type: Boolean, + value: false, + observer: 'onAccessStateChanged_', + }, /** Whether this dialog should show App Streaming info */ - showAppStreaming: - {type: Boolean, value: false, observer: 'onAccessStateChanged_'}, + showAppStreaming: { + type: Boolean, + value: false, + observer: 'onAccessStateChanged_', + }, /** * Indicates that the features we want to handle during setup flow. * It is constructed using the bitwise _FEATURE values (ex: * NOTIFICATION_FEATURE) declared at the top. - * @private */ setupMode_: { type: Number, @@ -248,40 +241,34 @@ * Indicates that the features we have completed after setup flow. * It is constructed using the bitwise _FEATURE values (ex: * NOTIFICATION_FEATURE) declared at the top. - * @private */ completedMode_: { type: Number, value: 0, }, - /** @private */ shouldShowLearnMoreButton_: { type: Boolean, computed: 'computeShouldShowLearnMoreButton_(setupState_, flowState_)', reflectToAttribute: true, }, - /** @private */ shouldShowDisabledDoneButton_: { type: Boolean, computed: 'computeShouldShowDisabledDoneButton_(setupState_)', reflectToAttribute: true, }, - /** @private */ isPinNumberSelected_: { type: Boolean, value: false, }, - /** @private */ isPinSet_: { type: Boolean, value: false, }, - /** @private */ showSetupPinDialog_: { type: Boolean, value: false, @@ -296,7 +283,6 @@ value: false, }, - /** @private */ learnMoreButtonAriaLabel_: { type: String, computed: 'getLearnMoreButtonAriaLabel_()', @@ -304,34 +290,60 @@ }; } + combinedSetupSupported: boolean; + isChromeosScreenLockEnabled: boolean; + isPasswordDialogShowing: boolean; + isPhoneScreenLockEnabled: boolean; + showAppStreaming: boolean; + showCameraRoll: boolean; + showNotifications: boolean; + private browserProxy_: MultiDeviceBrowserProxy; + private completedMode_: number; + private description_: string; + private didSetupAttemptFail_: boolean; + private flowState_: SetupFlowStatus; + private hasCompletedSetup_: boolean; + private hasStartedSetupAttempt_: boolean; + private isNotificationAccessProhibited_: boolean; + private isPinNumberSelected_: boolean; + private isPinSet_: boolean; + private isScreenLockEnabled_: boolean; + private isSetupAttemptInProgress_: boolean; + private isSetupScreenLockInProgress_: boolean; + private learnMoreButtonAriaLabel_: string; + private setupMode_: number; + private setupScreen_: PhoneHubPermissionsSetupFlowScreens; + private setupState_: PermissionsSetupStatus|null; + private shouldShowDisabledDoneButton_: boolean; + private shouldShowLearnMoreButton_: boolean; + private showSetupPinDialog_: boolean; + private title_: string; + constructor() { super(); - /** @private {!MultiDeviceBrowserProxy} */ this.browserProxy_ = MultiDeviceBrowserProxyImpl.getInstance(); } - /** @override */ - ready() { + override ready(): void { super.ready(); this.addEventListener('set-pin-done', this.onSetPinDone_); } - /** @override */ - connectedCallback() { + override connectedCallback(): void { super.connectedCallback(); - this.addWebUIListener( + this.addWebUiListener( 'settings.onNotificationAccessSetupStatusChanged', this.onNotificationSetupStateChanged_.bind(this)); - this.addWebUIListener( + this.addWebUiListener( 'settings.onAppsAccessSetupStatusChanged', this.onAppsSetupStateChanged_.bind(this)); - this.addWebUIListener( + this.addWebUiListener( 'settings.onCombinedAccessSetupStatusChanged', this.onCombinedSetupStateChanged_.bind(this)); - this.addWebUIListener( + this.addWebUiListener( 'settings.onFeatureSetupConnectionStatusChanged', this.onFeatureSetupConnectionStatusChanged_.bind(this)); this.$.dialog.showModal(); @@ -340,11 +352,8 @@ PhoneHubPermissionsSetupAction.SHOWN); } - /** - * @param {!PermissionsSetupStatus} notificationSetupState - * @private - */ - onNotificationSetupStateChanged_(notificationSetupState) { + private onNotificationSetupStateChanged_(notificationSetupState: + PermissionsSetupStatus): void { if (this.flowState_ !== SetupFlowStatus.WAIT_FOR_PHONE_NOTIFICATION) { return; } @@ -359,6 +368,7 @@ case PermissionsSetupStatus.CONNECTION_DISCONNECTED: case PermissionsSetupStatus.NOTIFICATION_ACCESS_PROHIBITED: this.flowState_ = SetupFlowStatus.FINISHED; + break; case PermissionsSetupStatus.CONNECTION_REQUESTED: case PermissionsSetupStatus.CONNECTING: case PermissionsSetupStatus @@ -397,11 +407,8 @@ } } - /** - * @param {!PermissionsSetupStatus} appsSetupResult - * @private - */ - onAppsSetupStateChanged_(appsSetupResult) { + private onAppsSetupStateChanged_(appsSetupResult: PermissionsSetupStatus): + void { if (this.flowState_ !== SetupFlowStatus.WAIT_FOR_PHONE_APPS) { return; } @@ -430,11 +437,8 @@ } } - /** - * @param {!PermissionsSetupStatus} combinedSetupResult - * @private - */ - onCombinedSetupStateChanged_(combinedSetupResult) { + private onCombinedSetupStateChanged_(combinedSetupResult: + PermissionsSetupStatus): void { if (this.flowState_ !== SetupFlowStatus.WAIT_FOR_PHONE_COMBINED) { return; } @@ -449,10 +453,14 @@ case PermissionsSetupStatus.CAMERA_ROLL_GRANTED_NOTIFICATION_REJECTED: case PermissionsSetupStatus.CAMERA_ROLL_REJECTED_NOTIFICATION_GRANTED: break; + // TODO(b/266455078) Avoid Fallthrough case in switch + // @ts-expect-error Fallthrough case in switch case PermissionsSetupStatus.FAILED_OR_CANCELLED: this.updateCamearRollSetupResultIfNeeded_(); case PermissionsSetupStatus.TIMED_OUT_CONNECTING: case PermissionsSetupStatus.CONNECTION_DISCONNECTED: + // TODO(b/266455078) Avoid Fallthrough case in switch + // @ts-expect-error Fallthrough case in switch case PermissionsSetupStatus.NOTIFICATION_ACCESS_PROHIBITED: this.flowState_ = SetupFlowStatus.FINISHED; case PermissionsSetupStatus.CONNECTION_REQUESTED: @@ -497,10 +505,7 @@ } } - /** - * @private - */ - logSetupModeMetrics_() { + private logSetupModeMetrics_(): void { if (this.showCameraRoll) { this.setupMode_ |= CAMERA_ROLL_FEATURE; } @@ -514,27 +519,23 @@ this.computePhoneHubPermissionsSetupMode_(this.setupMode_)); } - /** - * @private - */ - logCompletedSetupModeMetrics_() { + private logCompletedSetupModeMetrics_(): void { this.browserProxy_.logPhoneHubPermissionSetUpScreenAction( this.setupScreen_, PhoneHubPermissionsSetupAction.SHOWN); this.browserProxy_.logPhoneHubPermissionOnboardingSetupResult( this.computePhoneHubPermissionsSetupMode_(this.completedMode_)); } - /** - * @param {!PermissionsSetupStatus} connectionResult - * @private - */ - onFeatureSetupConnectionStatusChanged_(connectionResult) { + private onFeatureSetupConnectionStatusChanged_( + connectionResult: PermissionsSetupStatus): void { if (this.flowState_ !== SetupFlowStatus.WAIT_FOR_CONNECTION) { return; } switch (connectionResult) { case PermissionsSetupStatus.TIMED_OUT_CONNECTING: + // TODO(b/266455078) Avoid Fallthrough case in switch + // @ts-expect-error Fallthrough case in switch case PermissionsSetupStatus.CONNECTION_DISCONNECTED: this.setupState_ = connectionResult; case PermissionsSetupStatus.COMPLETED_SUCCESSFULLY: @@ -547,15 +548,13 @@ return; } this.startSetupProcess_(); + return; default: return; } } - /** - * @private - */ - updateCamearRollSetupResultIfNeeded_() { + private updateCamearRollSetupResultIfNeeded_(): void { if (this.setupMode_ & CAMERA_ROLL_FEATURE && !this.showCameraRoll) { this.completedMode_ |= CAMERA_ROLL_FEATURE; this.browserProxy_.setFeatureEnabledState( @@ -563,10 +562,7 @@ } } - /** - * @private - */ - updateNotificationsSetupResultIfNeeded_() { + private updateNotificationsSetupResultIfNeeded_(): void { if (this.setupMode_ & NOTIFICATION_FEATURE && !this.showNotifications) { this.completedMode_ |= NOTIFICATION_FEATURE; this.browserProxy_.setFeatureEnabledState( @@ -574,38 +570,22 @@ } } - /** - * @return {boolean} - * @private - */ - computeHasStartedSetupAttempt_() { + private computeHasStartedSetupAttempt_(): boolean { return this.flowState_ !== SetupFlowStatus.INTRO; } - /** - * @return {boolean} - * @private - */ - computeIsSetupAttemptInProgress_() { + private computeIsSetupAttemptInProgress_(): boolean { return this.setupState_ === PermissionsSetupStatus.SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE || this.setupState_ === PermissionsSetupStatus.CONNECTING || this.setupState_ === PermissionsSetupStatus.CONNECTION_REQUESTED; } - /** - * @return {boolean} - * @private - */ - computeIsSetupScreenLockInProgress_() { + private computeIsSetupScreenLockInProgress_(): boolean { return this.flowState_ === SetupFlowStatus.SET_LOCKSCREEN; } - /** - * @return {boolean} - * @private - */ - computeHasCompletedSetup_() { + private computeHasCompletedSetup_(): boolean { return this.setupState_ === PermissionsSetupStatus.COMPLETED_SUCCESSFULLY || this.someFeaturesHaveBeenSetupWhenCompleted_() || this.setupState_ === @@ -614,20 +594,12 @@ PermissionsSetupStatus.CAMERA_ROLL_REJECTED_NOTIFICATION_GRANTED; } - /** - * @return {boolean} - * @private - */ - computeIsNotificationAccessProhibited_() { + private computeIsNotificationAccessProhibited_(): boolean { return this.setupState_ === PermissionsSetupStatus.NOTIFICATION_ACCESS_PROHIBITED; } - /** - * @return {boolean} - * @private - * */ - computeDidSetupAttemptFail_() { + private computeDidSetupAttemptFail_(): boolean { return this.setupState_ === PermissionsSetupStatus.TIMED_OUT_CONNECTING || this.setupState_ === PermissionsSetupStatus.CONNECTION_DISCONNECTED || this.setupState_ === @@ -635,38 +607,31 @@ this.noFeatureHasBeenSetupWhenCompleted_(); } - /** - * @return {boolean} - * @private - */ - - someFeaturesHaveBeenSetupWhenCompleted_() { + private someFeaturesHaveBeenSetupWhenCompleted_(): boolean { return (this.setupState_ === PermissionsSetupStatus.COMPLETED_USER_REJECTED || this.setupState_ === PermissionsSetupStatus.FAILED_OR_CANCELLED) && this.completedMode_ !== 0; } - /** - * @return {boolean} - * @private - */ - noFeatureHasBeenSetupWhenCompleted_() { + private noFeatureHasBeenSetupWhenCompleted_(): boolean { return (this.setupState_ === PermissionsSetupStatus.COMPLETED_USER_REJECTED || this.setupState_ === PermissionsSetupStatus.FAILED_OR_CANCELLED) && this.completedMode_ === 0; } - - /** @private */ - nextPage_() { + private nextPage_(): void { this.browserProxy_.logPhoneHubPermissionSetUpScreenAction( this.getCurrentScreen_(), PhoneHubPermissionsSetupAction.NEXT_OR_TRY_AGAIN); switch (this.flowState_) { + // TODO(b/266455078) Avoid Fallthrough case in switch + // @ts-expect-error Fallthrough case in switch case SetupFlowStatus.INTRO: this.logSetupModeMetrics_(); + // TODO(b/266455078) Avoid Fallthrough case in switch + // @ts-expect-error Fallthrough case in switch case SetupFlowStatus.FINISHED: this.flowState_ = SetupFlowStatus.WAIT_FOR_CONNECTION; case SetupFlowStatus.WAIT_FOR_CONNECTION: @@ -692,8 +657,7 @@ this.startSetupProcess_(); } - /** @private */ - startSetupProcess_() { + private startSetupProcess_(): void { if ((this.showCameraRoll || this.showNotifications) && this.combinedSetupSupported) { this.browserProxy_.attemptCombinedFeatureSetup( @@ -711,8 +675,7 @@ } } - /** @private */ - onCancelClicked_() { + private onCancelClicked_(): void { if (this.flowState_ === SetupFlowStatus.WAIT_FOR_PHONE_NOTIFICATION) { this.browserProxy_.cancelNotificationSetup(); } else if (this.flowState_ === SetupFlowStatus.WAIT_FOR_PHONE_APPS) { @@ -730,37 +693,33 @@ this.$.dialog.close(); } - /** @private */ - onDoneOrCloseButtonClicked_() { + private onDoneOrCloseButtonClicked_(): void { this.browserProxy_.logPhoneHubPermissionSetUpScreenAction( this.setupScreen_, PhoneHubPermissionsSetupAction.DONE); this.$.dialog.close(); } - /** @private */ - onLearnMoreClicked_() { + private onLearnMoreClicked_(): void { this.browserProxy_.logPhoneHubPermissionSetUpScreenAction( this.setupScreen_, PhoneHubPermissionsSetupAction.LEARN_MORE); window.open(this.i18n('multidevicePhoneHubPermissionsLearnMoreURL')); } - /** @private */ - onPinNumberSelected_(e) { + private onPinNumberSelected_(e: CustomEvent<{isPinNumberSelected: boolean}>): + void { e.stopPropagation(); assert(typeof e.detail.isPinNumberSelected === 'boolean'); this.isPinNumberSelected_ = e.detail.isPinNumberSelected; } - /** @private */ - onSetPinDone_() { + private onSetPinDone_(): void { // Once users confirm pin number, take them to the 'finish setup on the // phone' step directly. this.isPinSet_ = true; this.nextPage_(); } - /** @private */ - propagatePinNumberSelected_(selected) { + private propagatePinNumberSelected_(selected: boolean): void { const pinNumberEvent = new CustomEvent('pin-number-selected', { bubbles: true, composed: true, @@ -769,8 +728,7 @@ this.dispatchEvent(pinNumberEvent); } - /** @private */ - getCurrentScreen_() { + private getCurrentScreen_(): PhoneHubPermissionsSetupFlowScreens { if (this.flowState_ === SetupFlowStatus.INTRO) { return PhoneHubPermissionsSetupFlowScreens.INTRO; } @@ -801,11 +759,7 @@ } } - /** - * @return {string} The title of the dialog. - * @private - */ - getTitle_() { + private getTitle_(): string { if (this.flowState_ === SetupFlowStatus.INTRO) { return this.i18n('multidevicePermissionsSetupAckTitle'); } @@ -841,10 +795,9 @@ } /** - * @return {string} A description about the connection attempt state. - * @private + * @return A description about the connection attempt state. */ - getDescription_() { + private getDescription_(): TrustedHTML|string { if (this.flowState_ === SetupFlowStatus.INTRO) { return ''; } @@ -885,22 +838,14 @@ } } - /** - * @return {boolean} - * @private - */ - computeShouldShowLearnMoreButton_() { + private computeShouldShowLearnMoreButton_(): boolean { return this.flowState_ === SetupFlowStatus.INTRO || this.flowState_ === SetupFlowStatus.SET_LOCKSCREEN || this.setupState_ === PermissionsSetupStatus.SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE; } - /** - * @return {boolean} - * @private - */ - shouldShowCancelButton_() { + private shouldShowCancelButton_(): boolean { return this.setupState_ !== PermissionsSetupStatus.COMPLETED_SUCCESSFULLY && this.setupState_ !== PermissionsSetupStatus.NOTIFICATION_ACCESS_PROHIBITED && @@ -913,56 +858,32 @@ this.noFeatureHasBeenSetupWhenCompleted_(); } - /** - * @return {boolean} - * @private - */ - computeShouldShowDisabledDoneButton_() { + private computeShouldShowDisabledDoneButton_(): boolean { return this.setupState_ === PermissionsSetupStatus.SENT_MESSAGE_TO_PHONE_AND_WAITING_FOR_RESPONSE; } - /** - * @return {boolean} - * @private - */ - shouldShowTryAgainButton_() { + private shouldShowTryAgainButton_(): boolean { return this.setupState_ === PermissionsSetupStatus.TIMED_OUT_CONNECTING || this.setupState_ === PermissionsSetupStatus.CONNECTION_DISCONNECTED || this.noFeatureHasBeenSetupWhenCompleted_(); } - /** - * @return {boolean} - * @private - */ - shouldShowScreenLockInstructions_() { + private shouldShowScreenLockInstructions_(): boolean { return this.flowState_ === SetupFlowStatus.SET_LOCKSCREEN; } - /** - * @return {boolean} - * @private - */ - isScreenLockRequired_() { + private isScreenLockRequired_(): boolean { return loadTimeData.getBoolean('isEcheAppEnabled') && this.isPhoneScreenLockEnabled && !this.isChromeosScreenLockEnabled && this.showAppStreaming; } - /** - * @return {string} A aria label about learn more button. - * @private - */ - getLearnMoreButtonAriaLabel_() { + private getLearnMoreButtonAriaLabel_(): string { return this.i18n('multidevicePhoneHubLearnMoreAriaLabel'); } - /** - * @return {string} The finish title of the dialog. - * @private - */ - getSetupCompleteTitle_() { + private getSetupCompleteTitle_(): string { switch (this.completedMode_) { case NOTIFICATION_FEATURE: return this.i18n( @@ -988,11 +909,9 @@ } } - /** - * @return {!PhoneHubPermissionsSetupFeatureCombination} - * @private - */ - computePhoneHubPermissionsSetupMode_(mode) { + private computePhoneHubPermissionsSetupMode_( + mode: PhoneHubPermissionsSetupFeatureCombination): + PhoneHubPermissionsSetupFeatureCombination { switch (mode) { case NOTIFICATION_FEATURE: return PhoneHubPermissionsSetupFeatureCombination.NOTIFICATION; @@ -1016,8 +935,7 @@ } } - /** @private */ - onAccessStateChanged_() { + private onAccessStateChanged_(): void { if (this.flowState_ === SetupFlowStatus.INTRO && !this.showCameraRoll && !this.showNotifications && !this.showAppStreaming) { this.$.dialog.close(); @@ -1025,6 +943,16 @@ } } +declare global { + interface HTMLElementTagNameMap { + [SettingsMultidevicePermissionsSetupDialogElement.is]: + SettingsMultidevicePermissionsSetupDialogElement; + } + interface HTMLElementEventMap { + 'pin-number-selected': CustomEvent<{isPinNumberSelected: boolean}>; + } +} + customElements.define( SettingsMultidevicePermissionsSetupDialogElement.is, SettingsMultidevicePermissionsSetupDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.ts similarity index 67% rename from chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js rename to chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.ts index 33f444de..d544428 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_screen_lock_subpage.ts
@@ -12,29 +12,27 @@ import '../os_people_page/lock_screen_password_prompt_dialog.js'; import '../os_people_page/setup_pin_dialog.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {Constructor} from '../common/types.js'; import {LockScreenUnlockType, LockStateBehavior, LockStateBehaviorInterface} from '../os_people_page/lock_state_behavior.js'; import {getTemplate} from './multidevice_screen_lock_subpage.html.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {LockStateBehaviorInterface} - */ -const SettingsMultideviceScreenLockSubpageElementBase = - mixinBehaviors([I18nBehavior, LockStateBehavior], PolymerElement); +import TokenInfo = chrome.quickUnlockPrivate.TokenInfo; +import QuickUnlockMode = chrome.quickUnlockPrivate.QuickUnlockMode; -/** @polymer */ +const SettingsMultideviceScreenLockSubpageElementBase = + mixinBehaviors([LockStateBehavior], I18nMixin(PolymerElement)) as + Constructor<PolymerElement&I18nMixinInterface&LockStateBehaviorInterface>; + class SettingsMultideviceScreenLockSubpageElement extends SettingsMultideviceScreenLockSubpageElementBase { static get is() { - return 'settings-multidevice-screen-lock-subpage'; + return 'settings-multidevice-screen-lock-subpage' as const; } static get template() { @@ -47,8 +45,6 @@ * setModes_ is a partially applied function of * {@link chrome.quickUnlockPrivate.setModes} that stores the current auth * token. It's defined only when the user has entered a valid password. - * @type {Object|undefined} - * @private */ setModes_: { type: Object, @@ -56,7 +52,6 @@ /** * Authentication token. - * @private {!chrome.quickUnlockPrivate.TokenInfo|undefined} */ authToken_: { type: Object, @@ -65,7 +60,6 @@ /** * True if quick unlock settings are disabled by policy. - * @private */ quickUnlockDisabledByPolicy_: { type: Boolean, @@ -75,7 +69,6 @@ readOnly: true, }, - /** @private {boolean} */ shouldPromptPasswordDialog_: Boolean, /** Reflects whether the screen lock is enabled. */ @@ -101,6 +94,17 @@ }; } + isPasswordDialogShowing: boolean; + isScreenLockEnabled: boolean; + showSetupPinDialog: boolean; + private authToken_: TokenInfo|undefined; + private quickUnlockDisabledByPolicy_: boolean; + private setModes_: + ((modes: QuickUnlockMode[], credentials: string[], + onComplete: (success: boolean) => void) => void)|undefined; + private shouldPromptPasswordDialog_: boolean; + + static get observers() { return ['selectedUnlockTypeChanged_(selectedUnlockType)']; } @@ -115,10 +119,9 @@ /** * Called when the unlock type has changed. - * @param {!string} selected The current unlock type. - * @private + * @param selected The current unlock type. */ - selectedUnlockTypeChanged_(selected) { + private selectedUnlockTypeChanged_(selected: string): void { const pinNumberEvent = new CustomEvent('pin-number-selected', { bubbles: true, composed: true, @@ -136,7 +139,7 @@ // small chance that CrOS fails to remove the quick unlock capability. See // https://crbug.com/1054327 for details. this.hasPin = false; - this.setModes_.call(null, [], [], (result) => { + this.setModes_.call(null, [], [], (result: boolean) => { // Revert |hasPin| to true in the event setModes_ fails to set lock // state to PASSWORD only. if (!result) { @@ -148,38 +151,33 @@ } } - /** @private */ - onAuthTokenChanged_() { + private onAuthTokenChanged_(): void { if (this.authToken_ === undefined) { this.setModes_ = undefined; } else { + const token = this.authToken_.token; this.setModes_ = (modes, credentials, onComplete) => { - this.quickUnlockPrivate.setModes( - this.authToken_.token, modes, credentials, () => { - let result = true; - if (chrome.runtime.lastError) { - console.error( - 'setModes failed: ' + chrome.runtime.lastError.message); - result = false; - } - onComplete(result); - }); + this.quickUnlockPrivate.setModes(token, modes, credentials, () => { + let result = true; + if (chrome.runtime.lastError) { + console.error( + `setModes failed: ${chrome.runtime.lastError.message}`); + result = false; + } + onComplete(result); + }); }; } } - /** @private */ - onPasswordPromptDialogClose_() { + private onPasswordPromptDialogClose_(): void { this.shouldPromptPasswordDialog_ = false; } - /** - * @param {!CustomEvent<!chrome.quickUnlockPrivate.TokenInfo>} e - * @private - * */ - onAuthTokenObtained_(e) { + private onAuthTokenObtained_(e: CustomEvent<TokenInfo>): void { this.authToken_ = e.detail; - this.setLockScreenEnabled(this.authToken_.token, true, (success) => {}); + this.setLockScreenEnabled( + this.authToken_.token, true, (_success: boolean) => {}); this.isScreenLockEnabled = true; // Avoid dialog.close() of password_prompt_dialog.ts to close main dialog this.isPasswordDialogShowing = true; @@ -187,20 +185,25 @@ /** * Returns true if the setup pin section should be shown. - * @param {!string} selectedUnlockType The current unlock type. Used to let + * @param selectedUnlockType The current unlock type. Used to let * Polymer know about the dependency. - * @private */ - showConfigurePinButton_(selectedUnlockType) { + private showConfigurePinButton_(selectedUnlockType: string): boolean { return selectedUnlockType === LockScreenUnlockType.PIN_PASSWORD; } - /** @private */ - onSetupPinDialogClose_() { + private onSetupPinDialogClose_(): void { this.showSetupPinDialog = false; } } +declare global { + interface HTMLElementTagNameMap { + [SettingsMultideviceScreenLockSubpageElement.is]: + SettingsMultideviceScreenLockSubpageElement; + } +} + customElements.define( SettingsMultideviceScreenLockSubpageElement.is, SettingsMultideviceScreenLockSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts index 5cc3d86..e22bdce 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.ts
@@ -12,18 +12,17 @@ import './multidevice_feature_item.js'; -import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Constructor} from '../common/types'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; import {OsSettingsRoutes} from '../os_settings_routes.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; import {MultiDeviceFeature, MultiDevicePageContentData, MultiDeviceSettingsMode} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; import {SettingsMultideviceFeatureItemElement} from './multidevice_feature_item.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_smartlock_item.html.js'; interface SettingsMultideviceSmartlockItemElement { @@ -33,10 +32,7 @@ } const SettingsMultideviceSmartlockItemElementBase = - mixinBehaviors( - [MultiDeviceFeatureBehavior], WebUiListenerMixin(PolymerElement)) as - Constructor<PolymerElement&WebUiListenerMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(WebUiListenerMixin(PolymerElement)); class SettingsMultideviceSmartlockItemElement extends SettingsMultideviceSmartlockItemElementBase { @@ -56,6 +52,7 @@ routes: { type: Object, value: routes, + readonly: true, }, /**
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.ts similarity index 70% rename from chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js rename to chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.ts index c0dc6c7..587b2dcd 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.ts
@@ -10,6 +10,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import '../../settings_shared.css.js'; import '../../settings_vars.css.js'; @@ -20,43 +21,34 @@ import './multidevice_tether_item.js'; import './multidevice_wifi_sync_item.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; -import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; +import {DeepLinkingMixin} from '../deep_linking_mixin.js'; import {routes} from '../os_route.js'; import {OsSettingsRoutes} from '../os_settings_routes.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {RouteObserverMixin} from '../route_observer_mixin.js'; import {Route} from '../router.js'; import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js'; import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, PhoneHubFeatureAccessProhibitedReason, PhoneHubPermissionsSetupFeatureCombination} from './multidevice_constants.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_subpage.html.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {DeepLinkingBehaviorInterface} - * @implements {MultiDeviceFeatureBehaviorInterface} - * @implements {RouteObserverBehaviorInterface} - * @implements {I18nBehaviorInterface} - */ -const SettingsMultideviceSubpageElementBase = mixinBehaviors( - [ - DeepLinkingBehavior, - MultiDeviceFeatureBehavior, - RouteObserverBehavior, - I18nBehavior, - ], - PolymerElement); +interface SettingsMultideviceSubpageElement { + $: { + forgetDeviceDialog: CrDialogElement, + }; +} -/** @polymer */ +const SettingsMultideviceSubpageElementBase = MultiDeviceFeatureMixin( + DeepLinkingMixin(RouteObserverMixin(PolymerElement))); + class SettingsMultideviceSubpageElement extends SettingsMultideviceSubpageElementBase { static get is() { - return 'settings-multidevice-subpage'; + return 'settings-multidevice-subpage' as const; } static get template() { @@ -67,20 +59,19 @@ return { /** * Alias for allowing Polymer bindings to routes. - * @type {?OsSettingsRoutes} */ routes: { type: Object, value: routes, + readonly: true, }, /** * Used by DeepLinkingBehavior to focus this page's deep links. - * @type {!Set<!Setting>} */ supportedSettingIds: { type: Object, - value: () => new Set([ + value: () => new Set<Setting>([ Setting.kInstantTetheringOnOff, Setting.kMultiDeviceOnOff, Setting.kSmartLockOnOff, @@ -98,19 +89,16 @@ }; } - /** @override */ + routes: OsSettingsRoutes; + private browserProxy_: MultiDeviceBrowserProxy; + constructor() { super(); - /** @private {!MultiDeviceBrowserProxy} */ this.browserProxy_ = MultiDeviceBrowserProxyImpl.getInstance(); } - /** - * @param {!Route} route - * @param {!Route=} oldRoute - */ - currentRouteChanged(route, oldRoute) { + override currentRouteChanged(route: Route): void { // Does not apply to this page. if (route !== routes.MULTIDEVICE_FEATURES) { return; @@ -119,57 +107,40 @@ this.attemptDeepLink(); } - /** @private */ - handleVerifyButtonClick_(event) { + private handleVerifyButtonClick_(): void { this.browserProxy_.retryPendingHostSetup(); } - /** @private */ - handleAndroidMessagesButtonClick_() { + private handleAndroidMessagesButtonClick_(): void { this.browserProxy_.setUpAndroidSms(); } - /** - * @return {boolean} - * @private - */ - shouldShowIndividualFeatures_() { + private shouldShowIndividualFeatures_(): boolean { return this.pageContentData.mode === MultiDeviceSettingsMode.HOST_SET_VERIFIED; } - /** - * @return {boolean} - * @private - */ - shouldShowVerifyButton_() { + private shouldShowVerifyButton_(): boolean { return [ MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, ].includes(this.pageContentData.mode); } - /** - * @return {boolean} - * @private - */ - shouldShowSuiteToggle_() { + private shouldShowSuiteToggle_(): boolean { return this.pageContentData.mode === MultiDeviceSettingsMode.HOST_SET_VERIFIED; } - /** @private */ - handleForgetDeviceClick_() { + private handleForgetDeviceClick_(): void { this.$.forgetDeviceDialog.showModal(); } - /** @private */ - onForgetDeviceDialogCancelClick_() { + private onForgetDeviceDialogCancelClick_(): void { this.$.forgetDeviceDialog.close(); } - /** @private */ - onForgetDeviceDialogConfirmClick_() { + private onForgetDeviceDialogConfirmClick_(): void { const forgetDeviceRequestedEvent = new CustomEvent('forget-device-requested', { bubbles: true, @@ -179,11 +150,7 @@ this.$.forgetDeviceDialog.close(); } - /** - * @return {string} - * @private - */ - getStatusInnerHtml_() { + private getStatusInnerHtml_(): TrustedHTML|string { if ([ MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, @@ -194,27 +161,19 @@ this.i18n('multideviceDisabled'); } - /** - * @return {boolean} - * @private - */ - doesAndroidMessagesRequireSetUp_() { + private doesAndroidMessagesRequireSetUp_(): boolean { return this.getFeatureState(MultiDeviceFeature.MESSAGES) === MultiDeviceFeatureState.FURTHER_SETUP_REQUIRED; } - /** - * @return {boolean} - * @private - */ - isAndroidMessagesSetupButtonDisabled_() { + private isAndroidMessagesSetupButtonDisabled_(): boolean { const messagesFeatureState = this.getFeatureState(MultiDeviceFeature.MESSAGES); return !this.isSuiteOn() || messagesFeatureState === MultiDeviceFeatureState.PROHIBITED_BY_POLICY; } - getPhoneHubNotificationsTooltip_() { + private getPhoneHubNotificationsTooltip_(): string { if (!this.isFeatureAllowedByPolicy( MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS)) { return ''; @@ -235,7 +194,7 @@ } } - getPhoneHubAppsTooltip_() { + private getPhoneHubAppsTooltip_(): string { if (!this.isFeatureAllowedByPolicy(MultiDeviceFeature.ECHE)) { return ''; } @@ -245,42 +204,26 @@ return this.i18n('multideviceItemDisabledByPhoneAdminTooltip'); } - /** - * @return {boolean} - * @private - */ - shouldShowPhoneHubCameraRollItem_() { + private shouldShowPhoneHubCameraRollItem_(): boolean { return this.isFeatureSupported(MultiDeviceFeature.PHONE_HUB_CAMERA_ROLL) && (!this.isPhoneHubCameraRollSetupRequired() || !this.shouldShowPhoneHubCombinedSetupItem_()); } - /** - * @return {boolean} - * @private - */ - shouldShowPhoneHubNotificationsItem_() { + private shouldShowPhoneHubNotificationsItem_(): boolean { return this.isFeatureSupported( MultiDeviceFeature.PHONE_HUB_NOTIFICATIONS) && (!this.isPhoneHubNotificationsSetupRequired() || !this.shouldShowPhoneHubCombinedSetupItem_()); } - /** - * @return {boolean} - * @private - */ - shouldShowPhoneHubAppsItem_() { + private shouldShowPhoneHubAppsItem_(): boolean { return this.isFeatureSupported(MultiDeviceFeature.ECHE) && (!this.isPhoneHubAppsSetupRequired() || !this.shouldShowPhoneHubCombinedSetupItem_()); } - /** - * @return {boolean} - * @private - */ - shouldShowPhoneHubCombinedSetupItem_() { + private shouldShowPhoneHubCombinedSetupItem_(): boolean { let numFeaturesSetupRequired = 0; if (this.isPhoneHubCameraRollSetupRequired()) { numFeaturesSetupRequired++; @@ -294,41 +237,39 @@ return numFeaturesSetupRequired >= 2; } - /** @private */ - handleNotificationSetupClicked_() { + private handleNotificationSetupClicked_(): void { this.handlePhoneHubSetupClick( PhoneHubPermissionsSetupFeatureCombination.NOTIFICATION); } - /** @private */ - handleCameraRollSetupClicked_() { + private handleCameraRollSetupClicked_(): void { this.handlePhoneHubSetupClick( PhoneHubPermissionsSetupFeatureCombination.CAMERA_ROLL); } - /** @private */ - handleMessagingAppSetupClicked_() { + private handleMessagingAppSetupClicked_(): void { this.handlePhoneHubSetupClick( PhoneHubPermissionsSetupFeatureCombination.MESSAGING_APP); } - /** @param {!PhoneHubPermissionsSetupFeatureCombination} setupMode */ - /** @private */ - handlePhoneHubSetupClick(setupMode) { + private handlePhoneHubSetupClick( + setupMode: PhoneHubPermissionsSetupFeatureCombination): void { const permissionSetupRequestedEvent = new CustomEvent( 'permission-setup-requested', {bubbles: true, composed: true}); this.dispatchEvent(permissionSetupRequestedEvent); this.browserProxy_.logPhoneHubPermissionSetUpButtonClicked(setupMode); } - /** - * @return {boolean} - * @private - */ - isPhoneHubDisabled_() { + private isPhoneHubDisabled_(): boolean { return !this.isSuiteOn() || !this.isPhoneHubOn(); } } +declare global { + interface HTMLElementTagNameMap { + [SettingsMultideviceSubpageElement.is]: SettingsMultideviceSubpageElement; + } +} + customElements.define( SettingsMultideviceSubpageElement.is, SettingsMultideviceSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.ts index 899e4fa..0f45945092 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.ts
@@ -22,14 +22,13 @@ import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import '../../settings_shared.css.js'; -import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs} from '../../people_page/sync_browser_proxy.js'; -import {Constructor} from '../common/types.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; import {SettingsMultideviceFeatureItemElement} from './multidevice_feature_item.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_task_continuation_item.html.js'; interface SettingsMultideviceTaskContinuationItemElement { @@ -39,10 +38,7 @@ } const SettingsMultideviceTaskContinuationItemElementBase = - mixinBehaviors( - [MultiDeviceFeatureBehavior], WebUiListenerMixin(PolymerElement)) as - Constructor<PolymerElement&WebUiListenerMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(WebUiListenerMixin(PolymerElement)); class SettingsMultideviceTaskContinuationItemElement extends SettingsMultideviceTaskContinuationItemElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.ts index adcd53f..44a2f8790 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.ts
@@ -29,18 +29,17 @@ import {routes} from '../os_route.js'; import {OsSettingsRoutes} from '../os_settings_routes.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin, MultiDeviceFeatureMixinInterface} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_tether_item.html.js'; const SettingsMultideviceTetherItemElementBase = mixinBehaviors( [ NetworkListenerBehavior, - MultiDeviceFeatureBehavior, ], - PolymerElement) as - Constructor<PolymerElement&NetworkListenerBehaviorInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(PolymerElement)) as + Constructor<PolymerElement&MultiDeviceFeatureMixinInterface& + NetworkListenerBehaviorInterface>; class SettingsMultideviceTetherItemElement extends SettingsMultideviceTetherItemElementBase { @@ -72,6 +71,7 @@ routes: { type: Object, value: routes, + readonly: true, }, /**
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.ts index 31a4b94..cea02a5c 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.ts
@@ -14,21 +14,17 @@ import '../../settings_shared.css.js'; -import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {castExists} from '../assert_extras.js'; -import {Constructor} from '../common/types.js'; import {routes} from '../os_route.js'; import {Router} from '../router.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_wifi_sync_disabled_link.html.js'; const SettingsMultideviceWifiSyncDisabledLinkElementBase = - mixinBehaviors([MultiDeviceFeatureBehavior], I18nMixin(PolymerElement)) as - Constructor<PolymerElement&I18nMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(PolymerElement); class SettingsMultideviceWifiSyncDisabledLinkElement extends SettingsMultideviceWifiSyncDisabledLinkElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.ts b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.ts index 211cdbdc..2f283d3 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.ts +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.ts
@@ -20,20 +20,16 @@ import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import '../../settings_shared.css.js'; -import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Constructor} from '../common/types'; import {OsSyncBrowserProxy, OsSyncBrowserProxyImpl, OsSyncPrefs} from '../os_people_page/os_sync_browser_proxy.js'; -import {MultiDeviceFeatureBehavior, MultiDeviceFeatureBehaviorInterface} from './multidevice_feature_behavior.js'; +import {MultiDeviceFeatureMixin} from './multidevice_feature_mixin.js'; import {getTemplate} from './multidevice_wifi_sync_item.html.js'; const SettingsMultideviceWifiSyncItemElementBase = - mixinBehaviors( - [MultiDeviceFeatureBehavior], WebUiListenerMixin(PolymerElement)) as - Constructor<PolymerElement&WebUiListenerMixinInterface& - MultiDeviceFeatureBehaviorInterface>; + MultiDeviceFeatureMixin(WebUiListenerMixin(PolymerElement)); class SettingsMultideviceWifiSyncItemElement extends SettingsMultideviceWifiSyncItemElementBase {
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts index b5cad6e..2cadab8 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.ts
@@ -118,7 +118,7 @@ constructor() { super(); - /** RouteOriginBehaviorInterface override */ + /** RouteOriginMixin override */ this.route_ = routes.BLUETOOTH_DEVICE_DETAIL; this.browserProxy_ = OsBluetoothDevicesSubpageBrowserProxyImpl.getInstance();
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/local_data_recovery_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/local_data_recovery_dialog.js index 74170d3..0e0b627 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/local_data_recovery_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/local_data_recovery_dialog.js
@@ -16,7 +16,7 @@ import '../../settings_shared.css.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {AuthFactor, FactorObserverInterface, FactorObserverReceiver, ManagementType, RecoveryFactorEditor_ConfigureResult} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; +import {AuthFactor, ConfigureResult, FactorObserverInterface, FactorObserverReceiver, ManagementType} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './local_data_recovery_dialog.html.js'; @@ -94,7 +94,7 @@ const {result} = await this.recoveryFactorEditor.configure( this.authToken.token, false); - if (result !== RecoveryFactorEditor_ConfigureResult.kSuccess) { + if (result !== ConfigureResult.kSuccess) { console.error('RecoveryFactorEditor::Configure failed:', result); } } finally {
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js index bc5f8254..55b8321 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
@@ -34,7 +34,7 @@ import {LockScreenProgress, recordLockScreenProgress} from 'chrome://resources/ash/common/quick_unlock/lock_screen_constants.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; -import {AuthFactor, FactorObserverInterface, FactorObserverReceiver, ManagementType, RecoveryFactorEditor_ConfigureResult} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; +import {AuthFactor, ConfigureResult, FactorObserverInterface, FactorObserverReceiver, ManagementType} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; import {afterNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; @@ -642,13 +642,13 @@ const {result} = await this.recoveryFactorEditor.configure( this.authToken.token, shouldEnable); switch (result) { - case RecoveryFactorEditor_ConfigureResult.kSuccess: + case ConfigureResult.kSuccess: break; - case RecoveryFactorEditor_ConfigureResult.kInvalidTokenError: + case ConfigureResult.kInvalidTokenError: // This will open the password prompt. this.dispatchAuthTokenInvalidEvent_(); return; - case RecoveryFactorEditor_ConfigureResult.kClientError: + case ConfigureResult.kFatalError: console.error('Error configuring recovery'); return; }
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js index 0b89cfb3..18be3d45 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js
@@ -4,7 +4,7 @@ import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js'; -import {AuthFactorConfig, AuthFactorConfigInterface, RecoveryFactorEditor, RecoveryFactorEditorInterface} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; +import {AuthFactorConfig, AuthFactorConfigInterface, PinFactorEditor, PinFactorEditorInterface, RecoveryFactorEditor, RecoveryFactorEditorInterface} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js'; /** * @fileoverview @@ -78,6 +78,13 @@ */ recoveryFactorEditor: {type: Object, value: RecoveryFactorEditor.getRemote()}, + + /** + * Interface for calls to the ash PinFactorEditor service. May be + * overridden by tests. + * @type {PinFactorEditorInterface} + */ + pinFactorEditor: {type: Object, value: PinFactorEditor.getRemote()}, }, /** @override */ @@ -222,6 +229,13 @@ * @type {RecoveryFactorEditorInterface} */ this.recoveryFactorEditor; + + /** + * Interface for calls to the ash PinFactorEditor service. May be + * overridden by tests. + * @type {PinFactorEditorInterface} + */ + this.pinFactorEditor; } /**
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 7150fe6..5254451 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -90,13 +90,13 @@ "chromeos/multidevice_page/multidevice_combined_setup_item.ts", "chromeos/multidevice_page/multidevice_feature_item.ts", "chromeos/multidevice_page/multidevice_feature_toggle.ts", - "chromeos/multidevice_page/multidevice_notification_access_setup_dialog.js", - "chromeos/multidevice_page/multidevice_page.js", - "chromeos/multidevice_page/multidevice_permissions_setup_dialog.js", + "chromeos/multidevice_page/multidevice_notification_access_setup_dialog.ts", + "chromeos/multidevice_page/multidevice_page.ts", + "chromeos/multidevice_page/multidevice_permissions_setup_dialog.ts", "chromeos/multidevice_page/multidevice_radio_button.ts", - "chromeos/multidevice_page/multidevice_screen_lock_subpage.js", + "chromeos/multidevice_page/multidevice_screen_lock_subpage.ts", "chromeos/multidevice_page/multidevice_smartlock_item.ts", - "chromeos/multidevice_page/multidevice_subpage.js", + "chromeos/multidevice_page/multidevice_subpage.ts", "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.ts", "chromeos/multidevice_page/multidevice_task_continuation_item.ts", "chromeos/multidevice_page/multidevice_tether_item.ts", @@ -314,7 +314,9 @@ "chromeos/device_page/drag_mixin.ts", "chromeos/device_page/fake_cros_audio_config.ts", "chromeos/device_page/layout_mixin.ts", + "chromeos/device_page/fake_input_device_data.ts", "chromeos/device_page/fake_input_device_settings_provider.ts", + "chromeos/device_page/input_device_mojo_interface_provider.ts", "chromeos/device_page/input_device_settings_types.ts", "chromeos/ensure_lazy_loaded.ts", "chromeos/find_shortcut_behavior.js", @@ -329,10 +331,10 @@ "chromeos/main_page_mixin.ts", "chromeos/metrics_recorder.js", "chromeos/metrics_utils.ts", - "chromeos/multidevice_page/multidevice_browser_proxy.js", - "chromeos/multidevice_page/multidevice_constants.js", - "chromeos/multidevice_page/multidevice_feature_behavior.js", - "chromeos/multidevice_page/multidevice_metrics_logger.js", + "chromeos/multidevice_page/multidevice_browser_proxy.ts", + "chromeos/multidevice_page/multidevice_constants.ts", + "chromeos/multidevice_page/multidevice_feature_mixin.ts", + "chromeos/multidevice_page/multidevice_metrics_logger.ts", "chromeos/nearby_share_page/nearby_account_manager_browser_proxy.js", "chromeos/nearby_share_page/nearby_share_receive_manager.js", "chromeos/nearby_share_page/types.js", @@ -396,7 +398,6 @@ "chromeos/prefs_behavior.js", "chromeos/route_observer_behavior.js", "chromeos/route_observer_mixin.ts", - "chromeos/route_origin_behavior.js", "chromeos/route_origin_mixin.ts", "chromeos/router.js", "chromeos/search/combined_search_handler.ts",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index e61e62a..6a5ba65 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -15,7 +15,9 @@ import './device_page/display.js'; import './device_page/display_layout.js'; import './device_page/display_overscan_dialog.js'; +import './device_page/fake_input_device_data.js'; import './device_page/fake_input_device_settings_provider.js'; +import './device_page/input_device_mojo_interface_provider.js'; import './device_page/input_device_settings_types.js'; import './device_page/keyboard.js'; import './device_page/per_device_keyboard.js'; @@ -149,8 +151,10 @@ export {NearbySettings, NearbyShareSettingsBehavior} from '../shared/nearby_share_settings_behavior.js'; export {setCrosAudioConfigForTesting} from './device_page/cros_audio_config.js'; export {DevicePageBrowserProxy, DevicePageBrowserProxyImpl, IdleBehavior, LidClosedBehavior, NoteAppLockScreenSupport, setDisplayApiForTesting, StorageSpaceState} from './device_page/device_page_browser_proxy.js'; +export {fakeKeyboards, fakeMice, fakePointingSticks, fakeTouchpads} from './device_page/fake_input_device_data.js'; export {FakeInputDeviceSettingsProvider} from './device_page/fake_input_device_settings_provider.js'; -export {Keyboard, KeyboardSettings, MetaKey} from './device_page/input_device_settings_types.js'; +export {getInputDeviceSettingsProvider, setupFakeInputDeviceSettingsProvider} from './device_page/input_device_mojo_interface_provider.js'; +export {MetaKey} from './device_page/input_device_settings_types.js'; export {FindShortcutBehavior, FindShortcutManager} from './find_shortcut_behavior.js'; export {GoogleAssistantBrowserProxyImpl} from './google_assistant_page/google_assistant_browser_proxy.js'; export {ConsentStatus, DspHotwordState} from './google_assistant_page/google_assistant_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/route_origin_behavior.js b/chrome/browser/resources/settings/chromeos/route_origin_behavior.js deleted file mode 100644 index 0c258c7..0000000 --- a/chrome/browser/resources/settings/chromeos/route_origin_behavior.js +++ /dev/null
@@ -1,119 +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. - -import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {beforeNextRender} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {Route, Router} from './router.js'; - -import {RouteObserverBehavior} from './route_observer_behavior.js'; - -/** @polymerBehavior */ -export const RouteOriginBehaviorImpl = { - properties: { - /** - * A Map specifying which element should be focused when exiting a - * subpage. The key of the map holds a Route path, and the value holds - * either a query selector that identifies the associated element to focus - * or a function to be run when a neon-animation-finish event is handled. - * @protected {!Map<string, string|Function>} - */ - focusConfig_: { - type: Object, - value: () => new Map(), - }, - }, - - /** - * The route corresponding to this page. - * @protected {!Route|undefined} - */ - route_: undefined, - - /** - * Adds a route path to |this.focusConfig_| if the route exists. Otherwise - * it does nothing. - * @param {!Route|undefined} route - * @param {string} value A query selector leading to a button that routes - * the user to |route| if it is defined. - * @protected - */ - addFocusConfig(route, value) { - if (route) { - this.focusConfig_.set(route.path, value); - } - }, - - /** @override */ - attached() { - // All elements with this behavior must specify their route. - assert(this.route_ instanceof Route); - }, - - /** - * RouteObserverBehavior - * @param {!Route} newRoute - * @param {!Route=} prevRoute - * @protected - */ - currentRouteChanged(newRoute, prevRoute) { - // Only attempt to focus an anchor element if the most recent navigation - // was a 'pop' (backwards) navigation. - if (!Router.getInstance().lastRouteChangeWasPopstate()) { - return; - } - - // Route change does not apply to this page. - if (this.route_ !== newRoute) { - return; - } - - this.triggerFocus_(prevRoute); - }, - - /** - * Focuses the element for a given route by finding the associated - * query selector or calling the configured function. - * @param {Route=} route - * @private - */ - triggerFocus_(route) { - if (!route) { - return; - } - - const pathConfig = this.focusConfig_.get(route.path); - if (pathConfig) { - if (typeof pathConfig === 'function') { - pathConfig(); - } else if (typeof pathConfig === 'string') { - const element = assert(this.$$(String(pathConfig))); - beforeNextRender(this, () => { - focusWithoutInk(element); - }); - } - } - }, -}; - -/** @polymerBehavior */ -export const RouteOriginBehavior = - [RouteObserverBehavior, RouteOriginBehaviorImpl]; - -/** @interface */ -export class RouteOriginBehaviorInterface { - /** - * @param {!Route|undefined} route - * @param {string} value - */ - addFocusConfig(route, value) {} - - /** - * @param {!Route} newRoute - * @param {!Route=} prevRoute - * @protected - */ - currentRouteChanged(newRoute, prevRoute) {} -}
diff --git a/chrome/browser/resources/settings/metrics_browser_proxy.ts b/chrome/browser/resources/settings/metrics_browser_proxy.ts index 647e84c..7327da3 100644 --- a/chrome/browser/resources/settings/metrics_browser_proxy.ts +++ b/chrome/browser/resources/settings/metrics_browser_proxy.ts
@@ -37,8 +37,8 @@ THIRD_PARTY_COOKIES_ALLOW = 20, THIRD_PARTY_COOKIES_BLOCK_IN_INCOGNITO = 21, THIRD_PARTY_COOKIES_BLOCK = 22, - // Leave this at the end. - COUNT = 23, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 23, } /** @@ -66,8 +66,9 @@ // Deprecated in https://crbug.com/1407233. CHROME_CLEANER_CARET_NAVIGATION = 10, PASSWORDS_MANAGE_WEAK_PASSWORDS = 11, - // Leave this at the end. - COUNT = 12, + UNUSED_SITE_PERMISSIONS_REVIEW = 12, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 13, } /** @@ -88,8 +89,30 @@ UNDO_BLOCK = 5, UNDO_IGNORE = 6, UNDO_RESET = 7, - // Leave this at the end. - COUNT = 8, + OPEN_REVIEW_UI = 8, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 9, +} + +/** + * Contains all safety check unused site permissions module interactions. + * + * These values are persisted to logs. Entries should not be renumbered and + * numeric values should never be reused. + * + * Must be kept in sync with the + * SafetyChecUnusedSitePermissionsModuleInteractions enum in + * histograms/enums.xml + */ +export enum SafetyCheckUnusedSitePermissionsModuleInteractions { + OPEN_REVIEW_UI = 0, + ALLOW_AGAIN = 1, + ACKNOWLEDGE_ALL = 2, + UNDO_ALLOW_AGAIN = 3, + UNDO_ACKNOWLEDGE_ALL = 4, + MINIMIZE = 5, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 6, } /** @@ -109,8 +132,8 @@ SAFE_BROWSING_STANDARD_PROTECTION_EXPAND_ARROW_CLICKED = 5, SAFE_BROWSING_DISABLE_SAFE_BROWSING_DIALOG_CONFIRMED = 6, SAFE_BROWSING_DISABLE_SAFE_BROWSING_DIALOG_DENIED = 7, - // Leave this at the end. - COUNT = 8, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 8, } /** @@ -133,8 +156,8 @@ PROMO_ENTRY = 7, SWAA_COMPLETION_LINK = 8, PRIVACY_SANDBOX_COMPLETION_LINK = 9, - // Leave this at the end. - COUNT = 10, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 10, } /** @@ -166,8 +189,8 @@ SAFE_BROWSING_ENHANCED_TO_STANDARD = 13, SAFE_BROWSING_STANDARD_TO_ENHANCED = 14, SAFE_BROWSING_STANDARD_TO_STANDARD = 15, - // Leave this at the end. - COUNT = 16, + // Max value should be updated whenever new entries are added. + MAX_VALUE = 16, } export interface MetricsBrowserProxy { @@ -198,6 +221,33 @@ interaction: SafetyCheckNotificationsModuleInteractions): void; /** + * Helper function that calls recordBooleanHistogram for the + * Settings.SafetyCheck.NotificationsModuleEntryPointShown histogram + */ + recordSafetyCheckNotificationsModuleEntryPointShown(visible: boolean): void; + + /** + * Helper function that calls recordHistogram for + * Settings.SafetyCheck.UnusedSitePermissionsListCount histogram. + */ + recordSafetyCheckUnusedSitePermissionsListCountHistogram(suggestions: number): + void; + + /** + * Helper function that calls recordHistogram for the + * Settings.SafetyCheck.UnusedSitePermissionsModuleInteractions histogram + */ + recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + interaction: SafetyCheckUnusedSitePermissionsModuleInteractions): void; + + /** + * Helper function that calls recordBooleanHistogram for the + * Settings.SafetyCheck.UnusedSitePermissionsModuleEntryPointShown histogram + */ + recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown(visible: boolean): + void; + + /** * Helper function that calls recordHistogram for the * SettingsPage.PrivacyElementInteractions histogram */ @@ -241,7 +291,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.SafetyCheck.Interactions', interaction, - SafetyCheckInteractions.COUNT, + SafetyCheckInteractions.MAX_VALUE, ]); } @@ -257,7 +307,40 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.SafetyCheck.NotificationsModuleInteractions', interaction, - SafetyCheckNotificationsModuleInteractions.COUNT, + SafetyCheckNotificationsModuleInteractions.MAX_VALUE, + ]); + } + + recordSafetyCheckNotificationsModuleEntryPointShown(visible: boolean) { + chrome.send('metricsHandler:recordBooleanHistogram', [ + 'Settings.SafetyCheck.NotificationsModuleEntryPointShown', + visible, + ]); + } + + recordSafetyCheckUnusedSitePermissionsListCountHistogram(suggestions: + number) { + chrome.send('metricsHandler:recordInHistogram', [ + 'Settings.SafetyCheck.UnusedSitePermissionsListCount', + suggestions, + 99 /*max value for length of revoked permissions list*/, + ]); + } + + recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + interaction: SafetyCheckUnusedSitePermissionsModuleInteractions) { + chrome.send('metricsHandler:recordInHistogram', [ + 'Settings.SafetyCheck.UnusedSitePermissionsModuleInteractions', + interaction, + SafetyCheckUnusedSitePermissionsModuleInteractions.MAX_VALUE, + ]); + } + + recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown(visible: + boolean) { + chrome.send('metricsHandler:recordBooleanHistogram', [ + 'Settings.SafetyCheck.UnusedSitePermissionsModuleEntryPointShown', + visible, ]); } @@ -265,7 +348,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.PrivacyElementInteractions', interaction, - PrivacyElementInteractions.COUNT, + PrivacyElementInteractions.MAX_VALUE, ]); } @@ -276,7 +359,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'SafeBrowsing.Settings.UserAction.Default', interaction, - SafeBrowsingInteractions.COUNT, + SafeBrowsingInteractions.MAX_VALUE, ]); } @@ -285,7 +368,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.PrivacyGuide.NextNavigation', interaction, - PrivacyGuideInteractions.COUNT, + PrivacyGuideInteractions.MAX_VALUE, ]); } @@ -293,7 +376,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.PrivacyGuide.EntryExit', interaction, - PrivacyGuideInteractions.COUNT, + PrivacyGuideInteractions.MAX_VALUE, ]); } @@ -301,7 +384,7 @@ chrome.send('metricsHandler:recordInHistogram', [ 'Settings.PrivacyGuide.SettingsStates', state, - PrivacyGuideSettingsStates.COUNT, + PrivacyGuideSettingsStates.MAX_VALUE, ]); }
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts index 5f8f4c3..f793d8b4 100644 --- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts +++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
@@ -142,7 +142,7 @@ } getBubbleAnchor() { - const anchor = this.shadowRoot!.querySelector<HTMLElement>('.disc-border'); + const anchor = this.shadowRoot!.querySelector<HTMLElement>('#button'); assert(anchor); return anchor; }
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.html b/chrome/browser/resources/settings/privacy_page/security_page.html index 016c971..efaed3f 100644 --- a/chrome/browser/resources/settings/privacy_page/security_page.html +++ b/chrome/browser/resources/settings/privacy_page/security_page.html
@@ -45,6 +45,11 @@ #safeBrowsingEnhanced .bullet-line:last-of-type { padding-bottom: 12px; } + + #safeBrowsingEnhanced { + --cr-radio-button-unchecked-ripple-color: + var(--cr-radio-button-checked-ripple-color); + } </style> <picture> <source
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.ts b/chrome/browser/resources/settings/privacy_page/security_page.ts index b2ea21f4c..487b9dae 100644 --- a/chrome/browser/resources/settings/privacy_page/security_page.ts +++ b/chrome/browser/resources/settings/privacy_page/security_page.ts
@@ -227,7 +227,7 @@ this.registerHelpBubble( 'kEnhancedProtectionSettingElementId', - this.$.safeBrowsingEnhanced.getBubbleAnchor()); + this.$.safeBrowsingEnhanced.getBubbleAnchor(), {top: 10}); } /**
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts index 01b26f1..3e17d28 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts
@@ -30,7 +30,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; import {routes} from '../route.js'; -import {Router} from '../router.js'; +import {Route, RouteObserverMixin, Router} from '../router.js'; import {SiteSettingsPermissionsBrowserProxy, SiteSettingsPermissionsBrowserProxyImpl, UnusedSitePermissions} from '../site_settings/site_settings_permissions_browser_proxy.js'; import {NotificationPermission, SiteSettingsPrefsBrowserProxy, SiteSettingsPrefsBrowserProxyImpl} from '../site_settings/site_settings_prefs_browser_proxy.js'; @@ -43,7 +43,7 @@ } const SettingsSafetyCheckPageElementBase = - WebUiListenerMixin(I18nMixin(PolymerElement)); + RouteObserverMixin(WebUiListenerMixin(I18nMixin(PolymerElement))); export class SettingsSafetyCheckPageElement extends SettingsSafetyCheckPageElementBase { @@ -95,6 +95,7 @@ private safetyCheckUnusedSitePermissionsEnabled_: boolean; private notificationPermissionSites_: NotificationPermission[] = []; private unusedSitePermissions_: UnusedSitePermissions[] = []; + private shouldRecordMetrics_: boolean = false; private siteSettingsBrowserProxy_: SiteSettingsPrefsBrowserProxy = SiteSettingsPrefsBrowserProxyImpl.getInstance(); private permissionsBrowserProxy_: SiteSettingsPermissionsBrowserProxy = @@ -141,6 +142,27 @@ this.unusedSitePermissions_ = await this.permissionsBrowserProxy_ .getRevokedUnusedSitePermissionsList(); + + if (this.shouldRecordMetrics_) { + this.metricsBrowserProxy_ + .recordSafetyCheckNotificationsModuleEntryPointShown( + this.shouldShowNotificationPermissions_()); + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown( + this.shouldShowUnusedSitePermissions_()); + this.shouldRecordMetrics_ = false; + } + } + + /** + * Determine whether metrics should be recorded, namely only when the user + * visited the privacy setting page embedding Safety Check, and not when + * the element is rendered in the background. + */ + override currentRouteChanged(currentRoute: Route) { + if (currentRoute.path === routes.PRIVACY.path) { + this.shouldRecordMetrics_ = true; + } } /** Triggers the safety check. */
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_unused_site_permissions.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_unused_site_permissions.ts index 508585d..0a7e9c1 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_unused_site_permissions.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_unused_site_permissions.ts
@@ -16,6 +16,7 @@ import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; import {routes} from '../route.js'; import {Router} from '../router.js'; import {UnusedSitePermissions, SiteSettingsPermissionsBrowserProxy, SiteSettingsPermissionsBrowserProxyImpl} from '../site_settings/site_settings_permissions_browser_proxy.js'; @@ -61,6 +62,8 @@ private browserProxy_: SiteSettingsPermissionsBrowserProxy = SiteSettingsPermissionsBrowserProxyImpl.getInstance(); + private metricsBrowserProxy_: MetricsBrowserProxy = + MetricsBrowserProxyImpl.getInstance(); override connectedCallback() { super.connectedCallback(); @@ -83,6 +86,11 @@ } private onButtonClick_() { + // Log click both in action and histogram. + this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( + SafetyCheckInteractions.UNUSED_SITE_PERMISSIONS_REVIEW); + this.metricsBrowserProxy_.recordAction( + 'Settings.SafetyCheck.ReviewUnusedSitePermissions'); Router.getInstance().navigateTo( routes.SITE_SETTINGS, /* dynamicParams= */ undefined, /* removeSearch= */ true);
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts index 65fc54e..19092ec2 100644 --- a/chrome/browser/resources/settings/settings.ts +++ b/chrome/browser/resources/settings/settings.ts
@@ -41,7 +41,7 @@ export {HatsBrowserProxy, HatsBrowserProxyImpl, TrustSafetyInteraction} from './hats_browser_proxy.js'; export {loadTimeData} from './i18n_setup.js'; export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from './lifetime_browser_proxy.js'; -export {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions, SafetyCheckNotificationsModuleInteractions} from './metrics_browser_proxy.js'; +export {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions, SafetyCheckNotificationsModuleInteractions, SafetyCheckUnusedSitePermissionsModuleInteractions} from './metrics_browser_proxy.js'; export {NtpExtension, OnStartupBrowserProxy, OnStartupBrowserProxyImpl} from './on_startup_page/on_startup_browser_proxy.js'; export {SettingsOnStartupPageElement} from './on_startup_page/on_startup_page.js'; export {SettingsStartupUrlDialogElement} from './on_startup_page/startup_url_dialog.js';
diff --git a/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts b/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts index fa3a766c..2011f18 100644 --- a/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts +++ b/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts
@@ -136,11 +136,15 @@ this.sites_ = await this.browserProxy_.getNotificationPermissionReview(); this.metricsBrowserProxy_.recordSafetyCheckNotificationsListCountHistogram( - this.sites_.length); + this.sites_.length); this.sitesLoaded_ = true; this.eventTracker_.add( document, 'keydown', (e: Event) => this.onKeyDown_(e as KeyboardEvent)); + + this.metricsBrowserProxy_ + .recordSafetyCheckNotificationsModuleInteractionsHistogram( + SafetyCheckNotificationsModuleInteractions.OPEN_REVIEW_UI); } override disconnectedCallback() { @@ -228,8 +232,6 @@ for (const row of rows) { row.classList.remove('removed'); } - this.metricsBrowserProxy_.recordSafetyCheckNotificationsListCountHistogram( - this.sites_.length); } private onShowTooltip_(e: Event) {
diff --git a/chrome/browser/resources/settings/site_settings_page/unused_site_permissions.ts b/chrome/browser/resources/settings/site_settings_page/unused_site_permissions.ts index c2fbd05..6338cb0 100644 --- a/chrome/browser/resources/settings/site_settings_page/unused_site_permissions.ts +++ b/chrome/browser/resources/settings/site_settings_page/unused_site_permissions.ts
@@ -22,6 +22,7 @@ import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckUnusedSitePermissionsModuleInteractions} from '../metrics_browser_proxy.js'; import {ContentSettingsTypes, MODEL_UPDATE_DELAY_MS} from '../site_settings/constants.js'; import {SiteSettingsMixin} from '../site_settings/site_settings_mixin.js'; import {SiteSettingsPermissionsBrowserProxy, SiteSettingsPermissionsBrowserProxyImpl, UnusedSitePermissions} from '../site_settings/site_settings_permissions_browser_proxy.js'; @@ -118,6 +119,7 @@ unusedSitePermissionsReviewListExpanded_: { type: Boolean, value: true, + observer: 'onListExpandedChanged_', }, }; } @@ -135,6 +137,8 @@ private subtitleString_: string; private toastText_: string|null; private unusedSitePermissionsReviewListExpanded_: boolean; + private metricsBrowserProxy_: MetricsBrowserProxy = + MetricsBrowserProxyImpl.getInstance(); override async connectedCallback() { super.connectedCallback(); @@ -146,7 +150,12 @@ const sites = await this.browserProxy_.getRevokedUnusedSitePermissionsList(); + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsListCountHistogram(sites.length); this.onUnusedSitePermissionListChanged_(sites); + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions.OPEN_REVIEW_UI); } /** Show info that review is completed when there are no permissions left. */ @@ -239,6 +248,9 @@ this.browserProxy_.allowPermissionsAgainForUnusedSite.bind( this.browserProxy_, item.origin), this.getModelUpdateDelayMs_()); + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions.ALLOW_AGAIN); } private async onGotItClick_(e: Event) { @@ -251,6 +263,9 @@ const toastText = await PluralStringProxyImpl.getInstance().getPluralString( 'safetyCheckUnusedSitePermissionsToastBulkLabel', this.sites_.length); this.showUndoToast_(toastText); + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions.ACKNOWLEDGE_ALL); } /* Repopulate the list when unused site permission list is updated. */ @@ -282,6 +297,14 @@ this.sites_.length); } + private onListExpandedChanged_(isExpanded: boolean) { + if (!isExpanded) { + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions.MINIMIZE); + } + } + private onUndoClick_(e: Event) { e.stopPropagation(); @@ -291,12 +314,20 @@ this.browserProxy_.undoAllowPermissionsAgainForUnusedSite( this.lastUnusedSitePermissionsAllowedAgain_); this.lastUnusedSitePermissionsAllowedAgain_ = null; + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions + .UNDO_ALLOW_AGAIN); break; case Action.GOT_IT: assert(this.lastUnusedSitePermissionsListAcknowledged_ !== null); this.browserProxy_.undoAcknowledgeRevokedUnusedSitePermissionsList( this.lastUnusedSitePermissionsListAcknowledged_); this.lastUnusedSitePermissionsListAcknowledged_ = null; + this.metricsBrowserProxy_ + .recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + SafetyCheckUnusedSitePermissionsModuleInteractions + .UNDO_ACKNOWLEDGE_ALL); break; default: assertNotReached();
diff --git a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn index b4ace9d..54882fd 100644 --- a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn +++ b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
@@ -59,6 +59,7 @@ "../shared:build_ts", "//third_party/polymer/v3_0:library", "//ui/webui/resources:library", + "//ui/webui/resources/cr_components/color_change_listener:build_ts", "//ui/webui/resources/mojo:library", ] ts_path_mappings =
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html index add5fb8..ea00ca7 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html
@@ -5,6 +5,7 @@ <meta charset="utf-8"> <title>$i18n{bookmarksTabTitle}</title> <meta name="color-scheme" content="light dark"> + <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <style>
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts index f85b2b751..ca01b47 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -24,6 +24,7 @@ import '//resources/cr_elements/icons.html.js'; import '//resources/polymer/v3_0/iron-list/iron-list.js'; +import {startColorChangeUpdater} from '//resources/cr_components/color_change_listener/colors_css_updater.js'; import {getInstance as getAnnouncerInstance} from '//resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; import {CrLazyRenderElement} from '//resources/cr_elements/cr_lazy_render/cr_lazy_render.js'; @@ -164,6 +165,11 @@ private renamingId_: string; private deletionDescription_: string; + constructor() { + super(); + startColorChangeUpdater(); + } + override connectedCallback() { super.connectedCallback(); this.setAttribute('role', 'tree');
diff --git a/chrome/browser/resources/side_panel/customize_chrome/app.html b/chrome/browser/resources/side_panel/customize_chrome/app.html index 3ed36c8..d0516d6b 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/app.html +++ b/chrome/browser/resources/side_panel/customize_chrome/app.html
@@ -44,17 +44,23 @@ </style> <iron-pages selected="[[page_]]" attr-for-selected="page-name"> <div page-name="overview" id="overviewPage"> - <h1 class="header">$i18n{appearanceHeader}</h1> - <customize-chrome-appearance on-edit-theme-click="onEditThemeClick_" - id="appearanceElement"> - </customize-chrome-appearance> + <div id="appearance" class="section"> + <h1 class="header">$i18n{appearanceHeader}</h1> + <customize-chrome-appearance on-edit-theme-click="onEditThemeClick_" + id="appearanceElement"> + </customize-chrome-appearance> + </div> <hr class="horizontal-rule"> - <h1 class="header">$i18n{shortcutsHeader}</h1> - <customize-chrome-shortcuts></customize-chrome-shortcuts> + <div id="shortcuts" class="section"> + <h1 class="header">$i18n{shortcutsHeader}</h1> + <customize-chrome-shortcuts></customize-chrome-shortcuts> + </div> <template is="dom-if" if="[[modulesEnabled_]]"> <hr class="horizontal-rule"> - <h1 class="header">$i18n{cardsHeader}</h1> - <customize-chrome-cards></customize-chrome-cards> + <div id="modules" class="section"> + <h1 class="header">$i18n{cardsHeader}</h1> + <customize-chrome-cards></customize-chrome-cards> + </div> </template> </div> <customize-chrome-categories on-back-click="onBackClick_"
diff --git a/chrome/browser/resources/side_panel/customize_chrome/app.ts b/chrome/browser/resources/side_panel/customize_chrome/app.ts index fb00159..d007e960 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/app.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/app.ts
@@ -9,6 +9,7 @@ import './shortcuts.js'; import './themes.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -16,9 +17,16 @@ import {AppearanceElement} from './appearance.js'; import {CategoriesElement} from './categories.js'; import {ChromeColorsElement} from './chrome_colors.js'; -import {BackgroundCollection} from './customize_chrome.mojom-webui.js'; +import {BackgroundCollection, CustomizeChromeSection} from './customize_chrome.mojom-webui.js'; +import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; import {ThemesElement} from './themes.js'; +const SECTION_TO_SELECTOR = { + [CustomizeChromeSection.kAppearance]: '#appearance', + [CustomizeChromeSection.kShortcuts]: '#shortcuts', + [CustomizeChromeSection.kModules]: '#modules', +}; + export enum CustomizeChromePage { OVERVIEW = 'overview', CATEGORIES = 'categories', @@ -64,6 +72,35 @@ private page_: CustomizeChromePage; private selectedCollection_: BackgroundCollection|null; + private scrollToSectionListenerId_: number|null = null; + + override connectedCallback() { + super.connectedCallback(); + this.scrollToSectionListenerId_ = + CustomizeChromeApiProxy.getInstance() + .callbackRouter.scrollToSection.addListener( + (section: CustomizeChromeSection) => { + const selector = SECTION_TO_SELECTOR[section]; + const element = this.shadowRoot!.querySelector(selector); + if (!element) { + return; + } + this.page_ = CustomizeChromePage.OVERVIEW; + element.scrollIntoView({behavior: 'auto'}); + }); + // We wait for load because `scrollIntoView` above requires the page to be + // laid out. + window.addEventListener('load', () => { + CustomizeChromeApiProxy.getInstance().handler.updateScrollToSection(); + }, {once: true}); + } + + override disconnectedCallback() { + super.disconnectedCallback(); + assert(this.scrollToSectionListenerId_); + CustomizeChromeApiProxy.getInstance().callbackRouter.removeListener( + this.scrollToSectionListenerId_); + } private onBackClick_() { switch (this.page_) {
diff --git a/chrome/browser/resources/side_panel/customize_chrome/check_mark_wrapper.html b/chrome/browser/resources/side_panel/customize_chrome/check_mark_wrapper.html index 0817641..f9b6ae8b 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/check_mark_wrapper.html +++ b/chrome/browser/resources/side_panel/customize_chrome/check_mark_wrapper.html
@@ -22,6 +22,7 @@ right: var(--customize-chrome-check-mark-wrapper-end); top: var(--customize-chrome-check-mark-wrapper-top); width: var(--customize-chrome-check-mark-wrapper-size); + z-index: 1; } :host(:not([checked])) svg { @@ -48,7 +49,7 @@ } :host([checked]) ::slotted(*) { - box-shadow: 0 0 0 2px var(--customize-chrome-check-mark-wrapper-color); + border: 2px solid var(--customize-chrome-check-mark-wrapper-color); } </style> <svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
diff --git a/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.html b/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.html index d63a6b0a3..9b50429b 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.html +++ b/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.html
@@ -52,6 +52,7 @@ -webkit-mask-image: url(chrome://resources/cr_components/customize_themes/colorize.svg); -webkit-mask-repeat: no-repeat; -webkit-mask-size: 100%; + background-color: var(--google-grey-700); height: 20px; left: calc(50% - 10px); pointer-events: none; @@ -62,6 +63,9 @@ customize-chrome-color { --customize-chrome-color-border-radius: 12px; + --customize-chrome-color-check-mark-end: -4px; + --customize-chrome-color-check-mark-size: 20px; + --customize-chrome-color-check-mark-top: -6px; padding: 0; } </style> @@ -75,13 +79,15 @@ <div id="customColorContainer" class="tile" title="$i18n{colorPickerLabel}" - aria-label="$i18n{colorPickerLabel}" + aria-label$="$i18n{colorPickerLabel}" + aria-checked$="[[isCustomColorSelected_]]" tabindex="0" on-click="onCustomColorClick_"> <customize-chrome-color id="customColor" background-color="[[customColor_.background]]" - foreground-color="[[customColor_.foreground]]"> + foreground-color="[[customColor_.foreground]]" + checked="[[isCustomColorSelected_]]"> </customize-chrome-color> <div id="colorPickerIcon"></div> <input id="colorPicker" type="color" tabindex="-1" aria-hidden="true" @@ -91,21 +97,25 @@ id="defaultColor" class="tile" title="$i18n{defaultColorName}" - aria-label="$i18n{defaultColorName}" + aria-label$="$i18n{defaultColorName}" + aria-checked$="[[isDefaultColorSelected_]]" tabindex="0" on-click="onDefaultColorClick_" background-color="[[defaultColor_.background]]" - foreground-color="[[defaultColor_.foreground]]"> + foreground-color="[[defaultColor_.foreground]]" + checked="[[isDefaultColorSelected_]]"> </customize-chrome-color> <template is="dom-repeat" id="chromeColorsRepeat" items="[[colors_]]"> <customize-chrome-color class="chrome-color tile" title="[[item.name]]" aria-label$="[[item.name]]" + aria-checked$="[[isChromeColorSelected_(item.seed, selectedColor_)]]" tabindex="0" on-click="onChromeColorClick_" background-color="[[item.background]]" - foreground-color="[[item.foreground]]"> + foreground-color="[[item.foreground]]" + checked="[[isChromeColorSelected_(item.seed, selectedColor_)]]"> </customize-chrome-color> </template> </cr-grid>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.ts b/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.ts index 085201c..bca7236 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/chrome_colors.ts
@@ -9,9 +9,11 @@ import {hexColorToSkColor, skColorToRgba} from 'chrome://resources/js/color_utils.js'; import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js'; +import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js'; import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getTemplate} from './chrome_colors.html.js'; +import {ColorElement} from './color.js'; import {Color, ColorType, DARK_DEFAULT_COLOR, LIGHT_DEFAULT_COLOR, SelectedColor} from './color_utils.js'; import {ChromeColor, CustomizeChromePageHandlerInterface, Theme} from './customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; @@ -21,7 +23,9 @@ backButton: HTMLElement, colorPicker: HTMLInputElement, colorPickerIcon: HTMLElement, - defaultColor: HTMLElement, + defaultColor: ColorElement, + customColor: ColorElement, + customColorContainer: HTMLElement, }; } @@ -46,6 +50,10 @@ type: Object, computed: 'computeSelectedColor_(theme_, colors_)', }, + isDefaultColorSelected_: { + type: Object, + computed: 'computeIsDefaultColorSelected_(selectedColor_)', + }, isCustomColorSelected_: { type: Object, computed: 'computeIsCustomColorSelected_(selectedColor_)', @@ -100,6 +108,10 @@ this.setThemeListenerId_!); } + private computeIsDefaultColorSelected_(): boolean { + return this.selectedColor_.type === ColorType.DEFAULT; + } + private computeIsCustomColorSelected_(): boolean { return this.selectedColor_.type === ColorType.CUSTOM; } @@ -128,18 +140,23 @@ LIGHT_DEFAULT_COLOR; } + private isChromeColorSelected_(color: SkColor): boolean { + return this.selectedColor_.type === ColorType.CHROME && + this.selectedColor_.chromeColor!.value === color.value; + } + private onBackClick_() { this.dispatchEvent(new Event('back-click')); } private onDefaultColorClick_() { - this.pageHandler_.removeBackgroundImage(); this.pageHandler_.setDefaultColor(); + this.pageHandler_.removeBackgroundImage(); } private onChromeColorClick_(e: DomRepeatEvent<ChromeColor>) { - this.pageHandler_.removeBackgroundImage(); this.pageHandler_.setSeedColor(e.model.item.seed); + this.pageHandler_.removeBackgroundImage(); } private onCustomColorClick_() { @@ -148,9 +165,9 @@ } private onCustomColorChange_(e: Event) { - this.pageHandler_.removeBackgroundImage(); this.pageHandler_.setSeedColor( hexColorToSkColor((e.target as HTMLInputElement).value)); + this.pageHandler_.removeBackgroundImage(); } private updateCustomColor_() {
diff --git a/chrome/browser/resources/side_panel/customize_chrome/color.html b/chrome/browser/resources/side_panel/customize_chrome/color.html index e39a232..c538a4a 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/color.html +++ b/chrome/browser/resources/side_panel/customize_chrome/color.html
@@ -1,6 +1,9 @@ <style> :host { --customize-chrome-color-border-radius: 50%; + --customize-chrome-color-check-mark-end: -1px; + --customize-chrome-color-check-mark-size: 16px; + --customize-chrome-color-check-mark-top: 0; box-sizing: border-box; cursor: pointer; display: block; @@ -14,28 +17,25 @@ } svg { - border: 1px solid var(--customize-chrome-color-border-color, - var(--customize-chrome-color-foreground-color)); border-radius: var(--customize-chrome-color-border-radius); box-sizing: border-box; display: block; width: 100%; } - :host([checked]) svg { - width: calc(100% - 4px); - } - - customize-chrome-check-mark { - --customize-chrome-check-mark-wrapper-end: -1px; + customize-chrome-check-mark-wrapper { + --customize-chrome-check-mark-wrapper-end: var(--customize-chrome-color-check-mark-end); + --customize-chrome-check-mark-wrapper-size: var(--customize-chrome-color-check-mark-size); + --customize-chrome-check-mark-wrapper-top: var(--customize-chrome-color-check-mark-top); } #background { fill: var(--customize-chrome-color-background-color); } - :host([checked]) svg { - border: none; + :host(:not([checked])) svg { + border: 1px solid var(--customize-chrome-color-border-color, + var(--customize-chrome-color-foreground-color)); } :host([background-color-hidden]) #background {
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.html b/chrome/browser/resources/side_panel/customize_chrome/themes.html index 9247b22..5d10b1a 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.html +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.html
@@ -38,6 +38,7 @@ } .image-container { + border-radius: 12px; overflow: hidden; padding-top: 100%; position: relative; @@ -62,10 +63,6 @@ transform: translateX(-50%); } - .image-container { - border-radius: 12px; - } - #refreshDailyToggleContainer { display: flex; justify-content: space-between; @@ -76,6 +73,17 @@ font-size: 13px; line-height: 20px; } + + customize-chrome-check-mark-wrapper { + --customize-chrome-check-mark-wrapper-end: -4px; + --customize-chrome-check-mark-wrapper-size: 20px; + --customize-chrome-check-mark-wrapper-top: -6px; + } + + customize-chrome-check-mark-wrapper[checked] .image-container { + padding-top: calc(100% - 4px); + width: calc(100% - 4px); + } </style> <div id="headerContainer"> <cr-icon-button on-click="onBackClick_" id="backButton" @@ -93,13 +101,17 @@ <cr-grid columns="3"> <template is="dom-repeat" id="themesRepeat" items="[[themes_]]"> <div class="tile theme" tabindex="0" role="button" - on-click="onSelectTheme_" title="[[item.attribution1]]"> - <div class="image-container"> - <img is="cr-auto-img" - auto-src="[[item.previewImageUrl.url]]" - draggable="false"> - </img> - </div> + on-click="onSelectTheme_" title$="[[item.attribution1]]" + aria-checked$="[[isThemeSelected_(item.attribution1, theme_)]]"> + <customize-chrome-check-mark-wrapper + checked="[[isThemeSelected_(item.imageUrl.url, theme_)]]"> + <div class="image-container"> + <img is="cr-auto-img" + auto-src="[[item.previewImageUrl.url]]" + draggable="false"> + </img> + </div> + </customize-chrome-check-mark-wrapper> </div> </template> </cr-grid>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/themes.ts b/chrome/browser/resources/side_panel/customize_chrome/themes.ts index 78fa3cc8..2f870af 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/themes.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/themes.ts
@@ -7,6 +7,7 @@ import 'chrome://resources/cr_elements/cr_icons.css.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; +import './check_mark_wrapper.js'; import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; @@ -129,6 +130,12 @@ this.pageHandler_.setDailyRefreshCollectionId(''); } } + + private isThemeSelected_(url: string) { + return this.theme_ && this.theme_.backgroundImage && + this.theme_.backgroundImage.url.url === url && + !this.isRefreshToggleChecked_; + } } 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 a612b111..ce59a1f5 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -66,15 +66,14 @@ // the names set in read_anything_font_model.cc. // TODO(1266555): The displayed names of the fonts should be messages that // will be translated to other languages. - private defaultFontName: string = 'Standard font'; + private defaultFontName: string = 'sans-serif'; private validFontNames: Array<{name: string, css: string}> = [ {name: 'Standard font', css: 'Standard font'}, {name: 'Sans-serif', css: 'sans-serif'}, {name: 'Serif', css: 'serif'}, - {name: 'Avenir', css: 'avenir'}, - {name: 'Comic Neue', css: '"Comic Neue"'}, + {name: 'Arial', css: 'Arial'}, {name: 'Comic Sans MS', css: '"Comic Sans MS"'}, - {name: 'Poppins', css: 'poppins'}, + {name: 'Times New Roman', css: '"Times New Roman"'}, ]; override connectedCallback() {
diff --git a/chrome/browser/resources/side_panel/user_notes/user_note.ts b/chrome/browser/resources/side_panel/user_notes/user_note.ts index f85fc11e..d047c8e 100644 --- a/chrome/browser/resources/side_panel/user_notes/user_note.ts +++ b/chrome/browser/resources/side_panel/user_notes/user_note.ts
@@ -98,7 +98,7 @@ } private getContentEditable_() { - return this.editing_ ? 'true' : 'false'; + return this.editing_ ? 'plaintext-only' : 'false'; } private clearInput_() {
diff --git a/chrome/browser/resources/webapks/OWNERS b/chrome/browser/resources/webapks/OWNERS index 3fa3f22..3f3a939 100644 --- a/chrome/browser/resources/webapks/OWNERS +++ b/chrome/browser/resources/webapks/OWNERS
@@ -1 +1 @@ -file://components/webapk/OWNERS +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index 50770aa2..da80c70f 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -294,6 +294,8 @@ "extension_telemetry/tabs_execute_script_signal.h", "extension_telemetry/tabs_execute_script_signal_processor.cc", "extension_telemetry/tabs_execute_script_signal_processor.h", + "hash_realtime_service_factory.cc", + "hash_realtime_service_factory.h", "incident_reporting/binary_integrity_analyzer.cc", "incident_reporting/binary_integrity_analyzer.h", "incident_reporting/binary_integrity_incident.cc", @@ -382,6 +384,7 @@ "//components/prefs", "//components/safe_browsing/core/browser:verdict_cache_manager", "//components/safe_browsing/core/browser/db", + "//components/safe_browsing/core/browser/hashprefix_realtime:hash_realtime_service", "//components/safe_browsing/core/browser/realtime:policy_engine", "//components/safe_browsing/core/browser/realtime:url_lookup_service_base", "//components/safe_browsing/core/common/proto:client_model_proto",
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc index 676742a7..0c96bdc 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc
@@ -94,80 +94,6 @@ kDisabled, }; -class ReporterRunnerPolicyTest - : public InProcessBrowserTest, - public ::testing::WithParamInterface<ReporterRunnerPolicy> { - public: - ReporterRunnerPolicyTest() { - policy_ = GetParam(); - component_updater::SetRegisterSwReporterComponentCallbackForTesting( - base::BindOnce(&ReporterRunnerPolicyTest::ComponentRegistered, - base::Unretained(this))); - } - - ReporterRunnerPolicyTest(const ReporterRunnerPolicyTest&) = delete; - ReporterRunnerPolicyTest& operator=(const ReporterRunnerPolicyTest&) = delete; - - void WaitForComponentRegistration() { waiter_.Wait(); } - - protected: - ReporterRunnerPolicy policy_; - - private: - void SetUpCommandLine(base::CommandLine* command_line) override {} - - // Make sure the component will be installed during the test. - void SetUpDefaultCommandLine(base::CommandLine* command_line) override { - base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM); - InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line); - test_launcher_utils::RemoveCommandLineSwitch( - default_command_line, switches::kDisableComponentUpdate, command_line); - } - - void SetUpInProcessBrowserTestFixture() override { - policy_provider_.SetDefaultReturns( - /*is_initialization_complete_return=*/true, - /*is_first_policy_load_complete_return=*/true); - policy::BrowserPolicyConnector::SetPolicyProviderForTesting( - &policy_provider_); - - // Setup polices as needed. - if (policy_ != ReporterRunnerPolicy::kNoPolicy) { - bool is_enabled = policy_ == ReporterRunnerPolicy::kEnabled; - policy::PolicyMap policies; - policies.Set(policy::key::kChromeCleanupEnabled, - policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_PLATFORM, base::Value(is_enabled), - nullptr); - policy_provider_.UpdateChromePolicy(policies); - } - } - - void ComponentRegistered() { waiter_.Signal(); } - - testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_; - Waiter waiter_; -}; - -IN_PROC_BROWSER_TEST_P(ReporterRunnerPolicyTest, CheckComponent) { - WaitForComponentRegistration(); - - // If the cleaner is disabled by policy, there should be no reporter - // component installed. Otherwise it should be installed. - std::vector<std::string> component_ids = - g_browser_process->component_updater()->GetComponentIDs(); - bool sw_component_registered = - base::Contains(component_ids, component_updater::kSwReporterComponentId); - ASSERT_EQ(policy_ != ReporterRunnerPolicy::kDisabled, - sw_component_registered); -} - -INSTANTIATE_TEST_SUITE_P(PolicyControl, - ReporterRunnerPolicyTest, - ::testing::Values(ReporterRunnerPolicy::kNoPolicy, - ReporterRunnerPolicy::kEnabled, - ReporterRunnerPolicy::kDisabled)); - // The state of the the enterprise policy to use during tests. enum class PolicyState { kNoLogs, // Don't set the policy for logs.
diff --git a/chrome/browser/safe_browsing/hash_realtime_service_factory.cc b/chrome/browser/safe_browsing/hash_realtime_service_factory.cc new file mode 100644 index 0000000..c140e42 --- /dev/null +++ b/chrome/browser/safe_browsing/hash_realtime_service_factory.cc
@@ -0,0 +1,60 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/safe_browsing/hash_realtime_service_factory.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/network_context_service_factory.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h" +#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" +#include "components/safe_browsing/core/browser/verdict_cache_manager.h" +#include "components/safe_browsing/core/common/safe_browsing_prefs.h" +#include "content/public/browser/browser_context.h" +#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h" + +namespace safe_browsing { + +// static +HashRealTimeService* HashRealTimeServiceFactory::GetForProfile( + Profile* profile) { + return static_cast<HashRealTimeService*>( + GetInstance()->GetServiceForBrowserContext(profile, /*create=*/true)); +} + +// static +HashRealTimeServiceFactory* HashRealTimeServiceFactory::GetInstance() { + return base::Singleton<HashRealTimeServiceFactory>::get(); +} + +HashRealTimeServiceFactory::HashRealTimeServiceFactory() + : ProfileKeyedServiceFactory("HashRealTimeService") { + DependsOn(VerdictCacheManagerFactory::GetInstance()); + DependsOn(NetworkContextServiceFactory::GetInstance()); +} + +KeyedService* HashRealTimeServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + if (!g_browser_process->safe_browsing_service()) { + return nullptr; + } + Profile* profile = Profile::FromBrowserContext(context); + auto url_loader_factory = + std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>( + g_browser_process->safe_browsing_service()->GetURLLoaderFactory( + profile)); + return new HashRealTimeService( + network::SharedURLLoaderFactory::Create(std::move(url_loader_factory)), + VerdictCacheManagerFactory::GetForProfile(profile), + base::BindRepeating( + &HashRealTimeServiceFactory::IsEnhancedProtectionEnabled, profile)); +} + +// static +bool HashRealTimeServiceFactory::IsEnhancedProtectionEnabled(Profile* profile) { + return safe_browsing::IsEnhancedProtectionEnabled(*(profile->GetPrefs())); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/hash_realtime_service_factory.h b/chrome/browser/safe_browsing/hash_realtime_service_factory.h new file mode 100644 index 0000000..fa079146 --- /dev/null +++ b/chrome/browser/safe_browsing/hash_realtime_service_factory.h
@@ -0,0 +1,52 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SAFE_BROWSING_HASH_REALTIME_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_SAFE_BROWSING_HASH_REALTIME_SERVICE_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +class KeyedService; +class Profile; + +namespace content { +class BrowserContext; +} + +namespace safe_browsing { + +class HashRealTimeService; + +// Singleton that owns HashRealTimeService objects, one for each active +// Profile. It listens to profile destroy events and destroy its associated +// service. It returns nullptr if the profile is in the Incognito mode. +class HashRealTimeServiceFactory : public ProfileKeyedServiceFactory { + public: + // Creates the service if it doesn't exist already for the given |profile|. + // If the service already exists, return its pointer. + static HashRealTimeService* GetForProfile(Profile* profile); + + // Get the singleton instance. + static HashRealTimeServiceFactory* GetInstance(); + + HashRealTimeServiceFactory(const HashRealTimeServiceFactory&) = delete; + HashRealTimeServiceFactory& operator=(const HashRealTimeServiceFactory&) = + delete; + + private: + friend struct base::DefaultSingletonTraits<HashRealTimeServiceFactory>; + + HashRealTimeServiceFactory(); + ~HashRealTimeServiceFactory() override = default; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + + static bool IsEnhancedProtectionEnabled(Profile* profile); +}; + +} // namespace safe_browsing +#endif // CHROME_BROWSER_SAFE_BROWSING_HASH_REALTIME_SERVICE_FACTORY_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index fc49634..40b0cc7f 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -86,6 +86,7 @@ #endif #if BUILDFLAG(FULL_SAFE_BROWSING) +#include "chrome/browser/safe_browsing/hash_realtime_service_factory.h" #include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_analyzer.h" #endif @@ -174,8 +175,9 @@ shutdown_ = true; // Remove Profile creation/destruction observers. - if (g_browser_process->profile_manager()) + if (g_browser_process->profile_manager()) { g_browser_process->profile_manager()->RemoveObserver(this); + } observed_profiles_.RemoveAllObservations(); // Delete the PrefChangeRegistrars, whose dtors also unregister |this| as an @@ -197,8 +199,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); NetworkContextService* service = NetworkContextServiceFactory::GetForBrowserContext(browser_context); - if (!service) + if (!service) { return nullptr; + } return service->GetNetworkContext(); } @@ -209,8 +212,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); NetworkContextService* service = NetworkContextServiceFactory::GetForBrowserContext(browser_context); - if (!service) + if (!service) { return nullptr; + } return service->GetURLLoaderFactory(); } @@ -219,8 +223,9 @@ content::BrowserContext* browser_context) { NetworkContextService* service = NetworkContextServiceFactory::GetForBrowserContext(browser_context); - if (!service) + if (!service) { return; + } service->FlushNetworkInterfaceForTesting(); } @@ -256,8 +261,9 @@ PasswordProtectionService* SafeBrowsingService::GetPasswordProtectionService( Profile* profile) const { - if (IsSafeBrowsingEnabled(*profile->GetPrefs())) + if (IsSafeBrowsingEnabled(*profile->GetPrefs())) { return ChromePasswordProtectionServiceFactory::GetForProfile(profile); + } return nullptr; } @@ -277,6 +283,15 @@ services_delegate_->AddDownloadManager(download_manager); } +HashRealTimeService* SafeBrowsingService::GetHashRealTimeService( + Profile* profile) { +#if BUILDFLAG(FULL_SAFE_BROWSING) + return safe_browsing::HashRealTimeServiceFactory::GetForProfile(profile); +#else + return nullptr; +#endif +} + SafeBrowsingUIManager* SafeBrowsingService::CreateUIManager() { return new SafeBrowsingUIManager( std::make_unique<ChromeSafeBrowsingUIManagerDelegate>(), @@ -303,8 +318,9 @@ std::unique_ptr<network::PendingSharedURLLoaderFactory> browser_url_loader_factory) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (enabled_) + if (enabled_) { return; + } enabled_ = true; @@ -345,8 +361,9 @@ void SafeBrowsingService::OnProfileAdded(Profile* profile) { // Some services are disabled by default based on the profile type, e.g. the // System Profile, in which Safe browsing is not needed. - if (AreKeyedServicesDisabledForProfileByDefault(profile)) + if (AreKeyedServicesDisabledForProfileByDefault(profile)) { return; + } // Start following the safe browsing preference on |pref_service|. PrefService* pref_service = profile->GetPrefs(); @@ -446,10 +463,11 @@ } } - if (enabled_by_prefs_) + if (enabled_by_prefs_) { Start(); - else + } else { Stop(false); + } state_callback_list_.Notify(); @@ -475,8 +493,9 @@ report->set_show_download_in_folder(show_download_in_folder.value()); } std::string token = DownloadProtectionService::GetDownloadPingToken(download); - if (!token.empty()) + if (!token.empty()) { report->set_token(token); + } if (IsExtendedReportingEnabled(*profile->GetPrefs()) && base::FeatureList::IsEnabled(kSafeBrowsingCsbrrNewDownloadTrigger)) { PopulateDownloadWarningActions(download, report.get());
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index cd5bdc89..a2d6889 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -77,6 +77,7 @@ class SafeBrowsingServiceFactory; class SafeBrowsingUIManager; class TriggerManager; +class HashRealTimeService; // Construction needs to happen on the main thread. // The SafeBrowsingService owns both the UI and Database managers which do @@ -173,6 +174,10 @@ // Adds |download_manager| to the set monitored by safe browsing. void AddDownloadManager(content::DownloadManager* download_manager); + // Gets the hash-prefix real-time lookup service associated with the profile, + // or creates one if one does not already exist. + HashRealTimeService* GetHashRealTimeService(Profile* profile); + // Type for subscriptions to SafeBrowsing service state. typedef base::RepeatingClosureList::Subscription StateSubscription;
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index cdcdfae..eb1eb12f 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -67,6 +67,10 @@ if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) return; + registrar_.Add(this, + content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, + content::NotificationService::AllSources()); + most_visited_sites_ = ChromeMostVisitedSitesFactory::NewForProfile(profile_); if (most_visited_sites_) { most_visited_sites_->EnableCustomLinks(false); @@ -96,12 +100,8 @@ InstantService::~InstantService() = default; -void InstantService::AddInstantProcess(content::RenderProcessHost* host) { - process_ids_.insert(host->GetID()); - // The same process may be added for multiple WebContents. Only observe once. - if (host_observation_.IsObservingSource(host)) { - host_observation_.AddObservation(host); - } +void InstantService::AddInstantProcess(int process_id) { + process_ids_.insert(process_id); } bool InstantService::IsInstantProcess(int process_id) const { @@ -177,15 +177,28 @@ ThemeServiceFactory::GetForProfile(profile_)->RemoveObserver(this); } -void InstantService::RenderProcessHostDestroyed( - content::RenderProcessHost* host) { - Profile* renderer_profile = static_cast<Profile*>(host->GetBrowserContext()); - if (profile_ == renderer_profile) { - process_ids_.erase(host->GetID()); - host_observation_.RemoveObservation(host); +void InstantService::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { + content::RenderProcessHost* rph = + content::Source<content::RenderProcessHost>(source).ptr(); + Profile* renderer_profile = + static_cast<Profile*>(rph->GetBrowserContext()); + if (profile_ == renderer_profile) + OnRendererProcessTerminated(rph->GetID()); + break; + } + default: + NOTREACHED() << "Unexpected notification type in InstantService."; } } +void InstantService::OnRendererProcessTerminated(int process_id) { + process_ids_.erase(process_id); +} + void InstantService::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) { DCHECK_EQ(observed_theme, native_theme_); // Force the theme information to rebuild so the correct using_dark_colors
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h index ab04cac2c..4a60bc11 100644 --- a/chrome/browser/search/instant_service.h +++ b/chrome/browser/search/instant_service.h
@@ -14,7 +14,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/scoped_multi_source_observation.h" #include "base/scoped_observation.h" #include "base/time/time.h" #include "build/build_config.h" @@ -25,7 +24,8 @@ #include "components/ntp_tiles/ntp_tile.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_registry_simple.h" -#include "content/public/browser/render_process_host_observer.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" #include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme_observer.h" #include "url/gurl.h" @@ -54,7 +54,7 @@ // necessary information (most visited tiles and theme info) updated in those // renderer processes. class InstantService : public KeyedService, - public content::RenderProcessHostObserver, + public content::NotificationObserver, public ntp_tiles::MostVisitedSites::Observer, public ui::NativeThemeObserver, public ThemeServiceObserver { @@ -66,9 +66,9 @@ ~InstantService() override; - // Add RenderProcessHosts that are associated with Instant processes and query - // based on PID. - void AddInstantProcess(content::RenderProcessHost* host); + // Add, remove, and query RenderProcessHost IDs that are associated with + // Instant processes. + void AddInstantProcess(int process_id); bool IsInstantProcess(int process_id) const; // Adds/Removes InstantService observers. @@ -127,8 +127,13 @@ // KeyedService: void Shutdown() override; - // content::RenderProcessHostObserver: - void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; + // content::NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + // Called when a renderer process is terminated. + void OnRendererProcessTerminated(int process_id); // ui::NativeThemeObserver: void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; @@ -166,6 +171,8 @@ base::ObserverList<InstantServiceObserver>::Unchecked observers_; + content::NotificationRegistrar registrar_; + // Data source for NTP tiles (aka Most Visited tiles). May be null. std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites_; @@ -173,10 +180,6 @@ raw_ptr<PrefService> pref_service_; - base::ScopedMultiSourceObservation<content::RenderProcessHost, - content::RenderProcessHostObserver> - host_observation_{this}; - base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver> theme_observation_{this};
diff --git a/chrome/browser/search/most_visited_iframe_source_unittest.cc b/chrome/browser/search/most_visited_iframe_source_unittest.cc index 94c3ba48..e753306 100644 --- a/chrome/browser/search/most_visited_iframe_source_unittest.cc +++ b/chrome/browser/search/most_visited_iframe_source_unittest.cc
@@ -14,7 +14,6 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/browser_task_environment.h" -#include "content/public/test/mock_render_process_host.h" #include "ipc/ipc_message.h" #include "net/base/request_priority.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" @@ -24,8 +23,11 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +const int kNonInstantRendererPID = 0; const char kNonInstantOrigin[] = "http://evil"; +const int kInstantRendererPID = 1; const char kInstantOrigin[] = "chrome-search://instant"; +const int kInvalidRendererPID = 42; class TestMostVisitedIframeSource : public MostVisitedIframeSource { public: @@ -69,10 +71,6 @@ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), response_(nullptr) {} - int GetInstantRendererPID() const { return mock_host_.GetID(); } - int GetNonInstantRendererPID() const { return mock_host_.GetID() + 1; } - int GetInvalidRendererPID() const { return mock_host_.GetID() + 2; } - TestMostVisitedIframeSource* source() { return source_.get(); } std::string response_string() { @@ -104,7 +102,7 @@ source_ = std::make_unique<TestMostVisitedIframeSource>(); source_->set_origin(kInstantOrigin); auto* instant_service = InstantServiceFactory::GetForProfile(&profile_); - instant_service->AddInstantProcess(&mock_host_); + instant_service->AddInstantProcess(kInstantRendererPID); response_ = nullptr; } @@ -117,30 +115,28 @@ content::BrowserTaskEnvironment task_environment_; TestingProfile profile_; - content::MockRenderProcessHost mock_host_{&profile_}; std::unique_ptr<TestMostVisitedIframeSource> source_; scoped_refptr<base::RefCountedMemory> response_; }; TEST_F(MostVisitedIframeSourceTest, ShouldServiceRequest) { source()->set_origin(kNonInstantOrigin); - EXPECT_FALSE( - ShouldService("http://test/loader.js", GetNonInstantRendererPID())); + EXPECT_FALSE(ShouldService("http://test/loader.js", kNonInstantRendererPID)); source()->set_origin(kInstantOrigin); EXPECT_FALSE( - ShouldService("chrome-search://bogus/valid.js", GetInstantRendererPID())); + ShouldService("chrome-search://bogus/valid.js", kInstantRendererPID)); source()->set_origin(kInstantOrigin); EXPECT_FALSE( - ShouldService("chrome-search://test/bogus.js", GetInstantRendererPID())); + ShouldService("chrome-search://test/bogus.js", kInstantRendererPID)); source()->set_origin(kInstantOrigin); EXPECT_TRUE( - ShouldService("chrome-search://test/valid.js", GetInstantRendererPID())); + ShouldService("chrome-search://test/valid.js", kInstantRendererPID)); source()->set_origin(kNonInstantOrigin); - EXPECT_FALSE(ShouldService("chrome-search://test/valid.js", - GetNonInstantRendererPID())); + EXPECT_FALSE( + ShouldService("chrome-search://test/valid.js", kNonInstantRendererPID)); source()->set_origin(std::string()); EXPECT_FALSE( - ShouldService("chrome-search://test/valid.js", GetInvalidRendererPID())); + ShouldService("chrome-search://test/valid.js", kInvalidRendererPID)); } TEST_F(MostVisitedIframeSourceTest, GetMimeType) {
diff --git a/chrome/browser/serial/serial_chooser_context.cc b/chrome/browser/serial/serial_chooser_context.cc index 8e05d90..de35197 100644 --- a/chrome/browser/serial/serial_chooser_context.cc +++ b/chrome/browser/serial/serial_chooser_context.cc
@@ -68,44 +68,16 @@ const uint64_t* data = reinterpret_cast<const uint64_t*>(buffer.data()); absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(data[0], data[1]); + base::UnguessableToken::Deserialize(data[0], data[1]); if (!token.has_value()) { return base::UnguessableToken(); } return token.value(); } -base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port) { - base::Value::Dict value; - if (port.display_name && !port.display_name->empty()) { - value.Set(kPortNameKey, *port.display_name); - } else { - value.Set(kPortNameKey, port.path.LossyDisplayName()); - } - - if (!SerialChooserContext::CanStorePersistentEntry(port)) { - value.Set(kTokenKey, EncodeToken(port.token)); - return base::Value(std::move(value)); - } - -#if BUILDFLAG(IS_WIN) - // Windows provides a handy device identifier which we can rely on to be - // sufficiently stable for identifying devices across restarts. - value.Set(kDeviceInstanceIdKey, port.device_instance_id); -#else - DCHECK(port.has_vendor_id); - value.Set(kVendorIdKey, port.vendor_id); - DCHECK(port.has_product_id); - value.Set(kProductIdKey, port.product_id); - DCHECK(port.serial_number); - value.Set(kSerialNumberKey, *port.serial_number); - -#if BUILDFLAG(IS_MAC) - DCHECK(port.usb_driver_name && !port.usb_driver_name->empty()); - value.Set(kUsbDriverKey, *port.usb_driver_name); -#endif // BUILDFLAG(IS_MAC) -#endif // BUILDFLAG(IS_WIN) - return base::Value(std::move(value)); +bool IsPolicyGrantedObject(const base::Value& object) { + return object.is_dict() && object.GetDict().size() == 1 && + object.GetDict().contains(kPortNameKey); } base::Value VendorAndProductIdsToValue(uint16_t vendor_id, @@ -171,9 +143,49 @@ SerialChooserContext::~SerialChooserContext() = default; +// static +base::Value SerialChooserContext::PortInfoToValue( + const device::mojom::SerialPortInfo& port) { + base::Value::Dict value; + if (port.display_name && !port.display_name->empty()) { + value.Set(kPortNameKey, *port.display_name); + } else { + value.Set(kPortNameKey, port.path.LossyDisplayName()); + } + + if (!SerialChooserContext::CanStorePersistentEntry(port)) { + value.Set(kTokenKey, EncodeToken(port.token)); + return base::Value(std::move(value)); + } + +#if BUILDFLAG(IS_WIN) + // Windows provides a handy device identifier which we can rely on to be + // sufficiently stable for identifying devices across restarts. + value.Set(kDeviceInstanceIdKey, port.device_instance_id); +#else + DCHECK(port.has_vendor_id); + value.Set(kVendorIdKey, port.vendor_id); + DCHECK(port.has_product_id); + value.Set(kProductIdKey, port.product_id); + DCHECK(port.serial_number); + value.Set(kSerialNumberKey, *port.serial_number); + +#if BUILDFLAG(IS_MAC) + DCHECK(port.usb_driver_name && !port.usb_driver_name->empty()); + value.Set(kUsbDriverKey, *port.usb_driver_name); +#endif // BUILDFLAG(IS_MAC) +#endif // BUILDFLAG(IS_WIN) + return base::Value(std::move(value)); +} + std::string SerialChooserContext::GetKeyForObject(const base::Value& object) { if (!IsValidObject(object)) return std::string(); + + if (IsPolicyGrantedObject(object)) { + return *object.FindStringKey(kPortNameKey); + } + #if BUILDFLAG(IS_WIN) return *(object.FindStringKey(kDeviceInstanceIdKey)); #else @@ -189,6 +201,10 @@ } bool SerialChooserContext::IsValidObject(const base::Value& object) { + if (IsPolicyGrantedObject(object)) { + return true; + } + if (!object.is_dict() || !object.FindStringKey(kPortNameKey)) return false;
diff --git a/chrome/browser/serial/serial_chooser_context.h b/chrome/browser/serial/serial_chooser_context.h index c9800eb..c240af8 100644 --- a/chrome/browser/serial/serial_chooser_context.h +++ b/chrome/browser/serial/serial_chooser_context.h
@@ -48,6 +48,8 @@ ~SerialChooserContext() override; + static base::Value PortInfoToValue(const device::mojom::SerialPortInfo& port); + // ObjectPermissionContextBase: std::string GetKeyForObject(const base::Value& object) override; bool IsValidObject(const base::Value& object) override;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java index 96ae67d..7e50221 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java
@@ -232,8 +232,8 @@ public void shareLinkToTextTest_GenerationError() { mLinkToTextCoordinator.initLinkToTextCoordinator( mTab, mShareCallback, mChromeShareExtras, SHARE_START_TIME, VISIBLE_URL, ""); - setGenerationRemoteRequestResults("", new Integer(LinkGenerationError.EMPTY_SELECTION), - new Integer(LinkGenerationReadyStatus.REQUESTED_AFTER_READY)); + setGenerationRemoteRequestResults("", Integer.valueOf(LinkGenerationError.EMPTY_SELECTION), + Integer.valueOf(LinkGenerationReadyStatus.REQUESTED_AFTER_READY)); mLinkToTextCoordinator.shareLinkToText(); // Check that shows share sheet without link to text @@ -261,8 +261,8 @@ // Receiving generation result after timeout, should not trigger another sharesheet. mLinkToTextCoordinator.onRemoteRequestCompleted("", - new Integer(LinkGenerationError.EMPTY_SELECTION), - new Integer(LinkGenerationReadyStatus.REQUESTED_BEFORE_READY)); + Integer.valueOf(LinkGenerationError.EMPTY_SELECTION), + Integer.valueOf(LinkGenerationReadyStatus.REQUESTED_BEFORE_READY)); verify(mShareCallback, times(1)).showShareSheet(any(), any(), anyLong()); // No new histogram is recorded. @@ -275,8 +275,8 @@ public void shareLinkToTextTest_Timeout_AfterRemoteRequestComplete() { mLinkToTextCoordinator.initLinkToTextCoordinator( mTab, mShareCallback, mChromeShareExtras, SHARE_START_TIME, VISIBLE_URL, ""); - setGenerationRemoteRequestResults("selector", new Integer(LinkGenerationError.NONE), - new Integer(LinkGenerationReadyStatus.REQUESTED_AFTER_READY)); + setGenerationRemoteRequestResults("selector", Integer.valueOf(LinkGenerationError.NONE), + Integer.valueOf(LinkGenerationReadyStatus.REQUESTED_AFTER_READY)); mLinkToTextCoordinator.shareLinkToText(); // Check that shows share sheet without link to text @@ -309,8 +309,8 @@ // Receiving generation result should not trigger another sharesheet. mLinkToTextCoordinator.onRemoteRequestCompleted("", - new Integer(LinkGenerationError.EMPTY_SELECTION), - new Integer(LinkGenerationReadyStatus.REQUESTED_BEFORE_READY)); + Integer.valueOf(LinkGenerationError.EMPTY_SELECTION), + Integer.valueOf(LinkGenerationReadyStatus.REQUESTED_BEFORE_READY)); verify(mShareCallback, times(0)).showShareSheet(any(), any(), anyLong()); // No new histogram is recorded.
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc index 47a31b604..6018e496 100644 --- a/chrome/browser/shell_integration.cc +++ b/chrome/browser/shell_integration.cc
@@ -86,18 +86,29 @@ } } -} // namespace - -DefaultWebClientSetPermission GetDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetDefaultWebClientSetPermission( + internal::WebClientSetMethod method) { #if BUILDFLAG(CHROME_FOR_TESTING) return SET_DEFAULT_NOT_ALLOWED; #else - return internal::GetPlatformSpecificDefaultWebClientSetPermission(); + return internal::GetPlatformSpecificDefaultWebClientSetPermission(method); #endif } +} // namespace + +DefaultWebClientSetPermission GetDefaultBrowserSetPermission() { + return GetDefaultWebClientSetPermission( + internal::WebClientSetMethod::kDefaultBrowser); +} + +DefaultWebClientSetPermission GetDefaultSchemeClientSetPermission() { + return GetDefaultWebClientSetPermission( + internal::WebClientSetMethod::kDefaultSchemeHandler); +} + bool CanSetAsDefaultBrowser() { - return GetDefaultWebClientSetPermission() != SET_DEFAULT_NOT_ALLOWED; + return GetDefaultBrowserSetPermission() != SET_DEFAULT_NOT_ALLOWED; } base::CommandLine CommandLineArgsForLauncher( @@ -262,7 +273,7 @@ void DefaultBrowserWorker::SetAsDefaultImpl( base::OnceClosure on_finished_callback) { - switch (GetDefaultWebClientSetPermission()) { + switch (GetDefaultBrowserSetPermission()) { case SET_DEFAULT_NOT_ALLOWED: // This is a no-op on channels where set-default is not allowed, but not // an error. @@ -350,7 +361,7 @@ void DefaultSchemeClientWorker::SetAsDefaultImpl( base::OnceClosure on_finished_callback) { - switch (GetDefaultWebClientSetPermission()) { + switch (GetDefaultSchemeClientSetPermission()) { case SET_DEFAULT_NOT_ALLOWED: // Not allowed, do nothing. break;
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h index 6d39d79..7f634f7 100644 --- a/chrome/browser/shell_integration.h +++ b/chrome/browser/shell_integration.h
@@ -57,10 +57,12 @@ SET_DEFAULT_INTERACTIVE, }; -// Returns requirements for making the running browser either the default -// browser or the default client application for specific schemes for the -// current user. -DefaultWebClientSetPermission GetDefaultWebClientSetPermission(); +// Returns requirements for making the running browser the default browser. +DefaultWebClientSetPermission GetDefaultBrowserSetPermission(); + +// Returns requirements for making the running browser the default client +// application for specific schemes outside of the default browser. +DefaultWebClientSetPermission GetDefaultSchemeClientSetPermission(); // Returns true if the running browser can be set as the default browser, // whether user interaction is needed or not. Use @@ -314,11 +316,20 @@ namespace internal { +// The different ways to set the default web client. +enum class WebClientSetMethod { + // Method to set the default browser. + kDefaultBrowser, + + // Method to set a default scheme handler outside of default browser. + kDefaultSchemeHandler, +}; + // Returns requirements for making the running browser either the default // browser or the default client application for specific schemes for the // current user, according to a specific platform. -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission(); +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method); } // namespace internal } // namespace shell_integration
diff --git a/chrome/browser/shell_integration_android.cc b/chrome/browser/shell_integration_android.cc index 7e1d0699a..da62682f 100644 --- a/chrome/browser/shell_integration_android.cc +++ b/chrome/browser/shell_integration_android.cc
@@ -39,8 +39,8 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { NOTIMPLEMENTED(); return SET_DEFAULT_NOT_ALLOWED; }
diff --git a/chrome/browser/shell_integration_chromeos.cc b/chrome/browser/shell_integration_chromeos.cc index 983dbcb6..e2ff092 100644 --- a/chrome/browser/shell_integration_chromeos.cc +++ b/chrome/browser/shell_integration_chromeos.cc
@@ -36,8 +36,8 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { return SET_DEFAULT_NOT_ALLOWED; }
diff --git a/chrome/browser/shell_integration_fuchsia.cc b/chrome/browser/shell_integration_fuchsia.cc index 4d16133..6c25360 100644 --- a/chrome/browser/shell_integration_fuchsia.cc +++ b/chrome/browser/shell_integration_fuchsia.cc
@@ -45,8 +45,8 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { return SET_DEFAULT_UNATTENDED; }
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index ca1c0b6..18c954c 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc
@@ -847,8 +847,8 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { return SET_DEFAULT_UNATTENDED; }
diff --git a/chrome/browser/shell_integration_mac.mm b/chrome/browser/shell_integration_mac.mm index 86aae92..0299d27 100644 --- a/chrome/browser/shell_integration_mac.mm +++ b/chrome/browser/shell_integration_mac.mm
@@ -109,7 +109,7 @@ return false; } - if (GetDefaultWebClientSetPermission() != SET_DEFAULT_UNATTENDED) { + if (GetDefaultSchemeClientSetPermission() != SET_DEFAULT_UNATTENDED) { return false; } @@ -270,8 +270,8 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { // This should be `SET_DEFAULT_INTERACTIVE`, but that changes how // `DefaultBrowserWorker` and `DefaultSchemeClientWorker` work. // TODO(https://crbug.com/1393452): Migrate all callers to the new API,
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index c65b1d5..52cb07e2 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc
@@ -783,15 +783,16 @@ namespace internal { -DefaultWebClientSetPermission -GetPlatformSpecificDefaultWebClientSetPermission() { +DefaultWebClientSetPermission GetPlatformSpecificDefaultWebClientSetPermission( + WebClientSetMethod method) { if (!install_static::SupportsSetAsDefaultBrowser()) { return SET_DEFAULT_NOT_ALLOWED; } if (ShellUtil::CanMakeChromeDefaultUnattended()) { return SET_DEFAULT_UNATTENDED; } - if (CanSetAsDefaultDirectly()) { + if (method == WebClientSetMethod::kDefaultBrowser && + CanSetAsDefaultDirectly()) { return SET_DEFAULT_UNATTENDED; } // Setting the default web client generally requires user interaction in
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 6ad5185c..59559ca 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -51,7 +51,7 @@ #include "url/gurl.h" #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc index d02500c..92d7f97e 100644 --- a/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc +++ b/chrome/browser/signin/chromeos_mirror_account_consistency_browsertest.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -23,6 +22,7 @@ #include "components/signin/core/browser/signin_header_helper.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/identity_manager/identity_test_utils.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 7fcea78..1259d9a06 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -47,7 +47,6 @@ #include "chrome/common/themes/autogenerated_theme_util.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/common/password_manager_ui.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/browser/signin/user_cloud_signin_restriction_policy_fetcher.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_namespace.h" @@ -57,6 +56,7 @@ #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/signin/public/base/signin_metrics.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/signin/public/identity_manager/accounts_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "google_apis/gaia/gaia_auth_util.h" @@ -905,8 +905,11 @@ absl::optional<std::string> managed_account_profile_level_signin_restriction) const { // No enterprise separation required for consumer accounts. - if (policy::BrowserPolicyConnector::IsNonEnterpriseUser(email)) + if (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail(email) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise) { return false; + } auto intercepted_account_info = identity_manager_->FindExtendedAccountInfoByEmailAddress(email);
diff --git a/chrome/browser/site_isolation/site_details_browsertest.cc b/chrome/browser/site_isolation/site_details_browsertest.cc index 4bbfbce1..afd28291 100644 --- a/chrome/browser/site_isolation/site_details_browsertest.cc +++ b/chrome/browser/site_isolation/site_details_browsertest.cc
@@ -915,8 +915,9 @@ BackForwardCacheSiteDetailsBrowserTest() { // Enable BackForwardCache. feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/chrome/browser/storage_access_api/storage_access_grant_permission_context.cc b/chrome/browser/storage_access_api/storage_access_grant_permission_context.cc index 56cac79..5a3161b 100644 --- a/chrome/browser/storage_access_api/storage_access_grant_permission_context.cc +++ b/chrome/browser/storage_access_api/storage_access_grant_permission_context.cc
@@ -104,12 +104,6 @@ StorageAccessGrantPermissionContext::~StorageAccessGrantPermissionContext() = default; -bool StorageAccessGrantPermissionContext::IsRestrictedToSecureOrigins() const { - // The Storage Access API and associated grants are allowed on insecure - // origins as well as secure ones. - return false; -} - void StorageAccessGrantPermissionContext::DecidePermissionForTesting( const permissions::PermissionRequestID& id, const GURL& requesting_origin,
diff --git a/chrome/browser/storage_access_api/storage_access_grant_permission_context.h b/chrome/browser/storage_access_api/storage_access_grant_permission_context.h index e0a4c610..3da12366 100644 --- a/chrome/browser/storage_access_api/storage_access_grant_permission_context.h +++ b/chrome/browser/storage_access_api/storage_access_grant_permission_context.h
@@ -68,7 +68,6 @@ private: // PermissionContextBase: - bool IsRestrictedToSecureOrigins() const override; void DecidePermission( const permissions::PermissionRequestID& id, const GURL& requesting_origin,
diff --git a/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc b/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc index e100661..2c365bb4 100644 --- a/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc +++ b/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc
@@ -145,12 +145,12 @@ }; TEST_F(StorageAccessGrantPermissionContextAPIDisabledTest, - InsecureOriginsAreAllowed) { + InsecureOriginsDisallowed) { GURL insecure_url = GURL("http://www.example.com"); StorageAccessGrantPermissionContext permission_context(profile()); - EXPECT_TRUE(permission_context.IsPermissionAvailableToOrigins(insecure_url, - insecure_url)); - EXPECT_TRUE(permission_context.IsPermissionAvailableToOrigins( + EXPECT_FALSE(permission_context.IsPermissionAvailableToOrigins(insecure_url, + insecure_url)); + EXPECT_FALSE(permission_context.IsPermissionAvailableToOrigins( insecure_url, GetRequesterURL())); }
diff --git a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc index d289ead..079e348 100644 --- a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc +++ b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
@@ -1022,7 +1022,7 @@ NavigationInitiationType::kAnchorLinkActivate), ::testing::Bool())); -class AdClickNavigationHandleStatusBrowserTest : public AdTaggingBrowserTest { +class AdClickLandingPageMetricsBrowserTest : public AdTaggingBrowserTest { public: void SetUpCommandLine(base::CommandLine* command_line) override { // Popups without user gesture is blocked by default. Turn off the switch @@ -1031,8 +1031,9 @@ } }; -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, - BrowserInitiated) { +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, BrowserInitiated) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); @@ -1043,9 +1044,21 @@ navigation_observer.last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 1u); + ukm_recorder.ExpectEntryMetric( + entries[0], ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, + 1); + ukm_recorder.ExpectEntryMetric( + entries[0], + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, WindowOpen) { +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, WindowOpen) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); @@ -1072,6 +1085,16 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 0); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } // Popup from non-ad script with gesture @@ -1093,6 +1116,16 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromNonAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 3u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 1); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } // Popup from ad script with gesture @@ -1114,6 +1147,16 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 4u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 1); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 1); } RenderFrameHost* child = @@ -1139,6 +1182,16 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 5u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 0); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } // Popup from ad iframe with gesture @@ -1159,11 +1212,23 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 6u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 1); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 1); } } -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, SetTopLocationFromCrossOriginAdIframe) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); @@ -1185,10 +1250,22 @@ navigation_observer.last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 1); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 1); } -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, SetTopLocationFromCrossOriginNonAdIframe) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); @@ -1209,10 +1286,22 @@ navigation_observer.last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromNonAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, 1); + ukm_recorder.ExpectEntryMetric( + entries.back(), + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, NavigateCrossOriginIframeFromNonAdScript) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); @@ -1245,10 +1334,18 @@ blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromNonAd); } + + // No event is recorded for subframe navigation. The recorded event is for the + // initial page load. + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 1u); } -IN_PROC_BROWSER_TEST_F(AdClickNavigationHandleStatusBrowserTest, +IN_PROC_BROWSER_TEST_F(AdClickLandingPageMetricsBrowserTest, NavigateCrossOriginIframeFromAdScript) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL url = embedded_test_server()->GetURL("a.com", "/ad_tagging/frame_factory.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); @@ -1281,6 +1378,12 @@ blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); } + + // No event is recorded for subframe navigation. The recorded event is for the + // initial page load. + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 1u); } class AdTaggingEventFromSubframeBrowserTest @@ -1629,7 +1732,9 @@ } IN_PROC_BROWSER_TEST_F(AdTaggingFencedFrameBrowserTest, - AdClickNavigationHandleStatus_PopupFromAdFencedFrame) { + AdClickLandingPageMetrics_PopupFromAdFencedFrame) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GetURL("frame_factory.html?primary"))); @@ -1654,11 +1759,22 @@ navigation_observer.last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries[1], ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, + 1); + ukm_recorder.ExpectEntryMetric( + entries[1], + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 1); } -IN_PROC_BROWSER_TEST_F( - AdTaggingFencedFrameBrowserTest, - AdClickNavigationHandleStatus_PopupFromNonAdFencedFrame) { +IN_PROC_BROWSER_TEST_F(AdTaggingFencedFrameBrowserTest, + AdClickLandingPageMetrics_PopupFromNonAdFencedFrame) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GetURL("frame_factory.html?primary"))); @@ -1683,11 +1799,23 @@ navigation_observer.last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromNonAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries[1], ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, + 1); + ukm_recorder.ExpectEntryMetric( + entries[1], + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } IN_PROC_BROWSER_TEST_F( AdTaggingFencedFrameBrowserTest, - AdClickNavigationHandleStatus_TopNavigationFromOpaqueModeAdFencedFrame) { + AdClickLandingPageMetrics_TopNavigationFromOpaqueModeAdFencedFrame) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL main_url = GetURL("frame_factory.html?primary"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); @@ -1709,11 +1837,23 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries[1], ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, + 1); + ukm_recorder.ExpectEntryMetric( + entries[1], + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 1); } IN_PROC_BROWSER_TEST_F( AdTaggingFencedFrameBrowserTest, - AdClickNavigationHandleStatus_TopNavigationFromOpaqueModeNonAdFencedFrame) { + AdClickLandingPageMetrics_TopNavigationFromOpaqueModeNonAdFencedFrame) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + GURL main_url = GetURL("frame_factory.html?primary"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); @@ -1735,6 +1875,16 @@ .last_navigation_initiator_activation_and_ad_status(), blink::mojom::NavigationInitiatorActivationAndAdStatus:: kStartedWithTransientActivationFromNonAd); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::PageLoadInitiatorForAdTagging::kEntryName); + EXPECT_EQ(entries.size(), 2u); + ukm_recorder.ExpectEntryMetric( + entries[1], ukm::builders::PageLoadInitiatorForAdTagging::kFromUserName, + 1); + ukm_recorder.ExpectEntryMetric( + entries[1], + ukm::builders::PageLoadInitiatorForAdTagging::kFromAdClickName, 0); } } // namespace
diff --git a/chrome/browser/supervised_user/BUILD.gn b/chrome/browser/supervised_user/BUILD.gn index c977f86..0134ce7 100644 --- a/chrome/browser/supervised_user/BUILD.gn +++ b/chrome/browser/supervised_user/BUILD.gn
@@ -15,6 +15,7 @@ "//chrome/browser/profiles:profile", "//chrome/common:constants", "//components/prefs", + "//components/supervised_user/core/common", ] if (is_android) { sources += [ "android/supervised_user_settings_service_bridge.cc" ] @@ -132,9 +133,9 @@ android_library("javatests") { testonly = true sources = [ - "android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java", - "android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java", - "android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentUnitTest.java", + "android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsTest.java", + "android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java", + "android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentTest.java", ] deps = [ ":test_support_java",
diff --git a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsTest.java similarity index 98% rename from chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java rename to chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsTest.java index c40bfa8..8154a54 100644 --- a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsUnitTest.java +++ b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalMetricsTest.java
@@ -22,7 +22,7 @@ */ @RunWith(BaseJUnit4ClassRunner.class) @Batch(Batch.PER_CLASS) -public class WebsiteParentApprovalMetricsUnitTest { +public class WebsiteParentApprovalMetricsTest { @Rule public final HistogramTestRule mHistogramTestRule = new HistogramTestRule();
diff --git a/chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java similarity index 100% rename from chrome/browser/supervised_user/android/java/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java rename to chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/WebsiteParentApprovalTest.java
diff --git a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentUnitTest.java b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentTest.java similarity index 98% rename from chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentUnitTest.java rename to chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentTest.java index a88f106..1c171ac 100644 --- a/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentUnitTest.java +++ b/chrome/browser/supervised_user/android/javatests/src/org/chromium/chrome/browser/supervised_user/website_approval/WebsiteApprovalSheetContentTest.java
@@ -21,7 +21,7 @@ */ @RunWith(BaseJUnit4ClassRunner.class) @Batch(Batch.UNIT_TESTS) -public class WebsiteApprovalSheetContentUnitTest { +public class WebsiteApprovalSheetContentTest { private static final String PREFIX = "https://www."; private static final String BASE_URL = "somehost.com";
diff --git a/chrome/browser/supervised_user/android/supervised_user_settings_service_bridge.cc b/chrome/browser/supervised_user/android/supervised_user_settings_service_bridge.cc index 6fd6e99..e2c76f2 100644 --- a/chrome/browser/supervised_user/android/supervised_user_settings_service_bridge.cc +++ b/chrome/browser/supervised_user/android/supervised_user_settings_service_bridge.cc
@@ -8,10 +8,10 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/profiles/profile_key.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" #include "chrome/browser/supervised_user/test_support_jni_headers/SupervisedUserSettingsBridge_jni.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" using base::android::JavaParamRef;
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc index a0f02bf..aa3376b0 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/supervised_user/kids_chrome_management/kids_management_service.h" #include "chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.h" #include "chrome/browser/supervised_user/kids_chrome_management/kidschromemanagement_messages.pb.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" @@ -37,6 +36,8 @@ #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" #include "components/signin/public/identity_manager/tribool.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc index 81f1bbf..253a3db 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/supervised_user/child_accounts/child_account_service.h" #include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h" #include "chrome/browser/supervised_user/child_accounts/family_info_fetcher.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/public/base/list_accounts_test_utils.h" @@ -21,6 +20,8 @@ #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc index f7cb16e..83ccb6f 100644 --- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc +++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
@@ -18,11 +18,11 @@ #include "base/values.h" #include "chrome/browser/supervised_user/child_accounts/kids_management_api.h" #include "chrome/browser/supervised_user/kids_chrome_management/kids_external_fetcher.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "components/signin/public/base/consent_level.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/primary_account_access_token_fetcher.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "google_apis/gaia/gaia_constants.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h"
diff --git a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc index 3a2cbe3..672622f 100644 --- a/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc +++ b/chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc
@@ -16,13 +16,13 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/child_accounts/kids_management_api.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/chrome_switches.h" #include "components/signin/public/base/consent_level.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/primary_account_access_token_fetcher.h" #include "components/signin/public/identity_manager/scope_set.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "google_apis/gaia/gaia_constants.h"
diff --git a/chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.cc b/chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.cc index 10b8bd8..69ac28d8f 100644 --- a/chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.cc +++ b/chrome/browser/supervised_user/kids_chrome_management/kids_chrome_management_client.cc
@@ -14,13 +14,13 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/child_accounts/kids_management_api.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "components/google/core/common/google_util.h" #include "components/signin/public/base/consent_level.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/primary_account_access_token_fetcher.h" #include "components/signin/public/identity_manager/scope_set.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "google_apis/gaia/gaia_constants.h"
diff --git a/chrome/browser/supervised_user/kids_chrome_management/kids_external_fetcher.cc b/chrome/browser/supervised_user/kids_chrome_management/kids_external_fetcher.cc index d83553d..e2d23f5 100644 --- a/chrome/browser/supervised_user/kids_chrome_management/kids_external_fetcher.cc +++ b/chrome/browser/supervised_user/kids_chrome_management/kids_external_fetcher.cc
@@ -18,9 +18,9 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "chrome/browser/supervised_user/kids_chrome_management/kids_access_token_fetcher.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "google_apis/gaia/google_service_auth_error.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/chrome/browser/supervised_user/kids_chrome_management/kids_management_service_unittest.cc b/chrome/browser/supervised_user/kids_chrome_management/kids_management_service_unittest.cc index 780825a..32e593db 100644 --- a/chrome/browser/supervised_user/kids_chrome_management/kids_management_service_unittest.cc +++ b/chrome/browser/supervised_user/kids_chrome_management/kids_management_service_unittest.cc
@@ -20,11 +20,11 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/sync/sync_service_factory.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/public/base/test_signin_client.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/supervised_user/core/common/pref_names.h" #include "content/public/test/browser_task_environment.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
diff --git a/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.cc b/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.cc index a04a3f1..35779ee 100644 --- a/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.cc +++ b/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.cc
@@ -9,9 +9,10 @@ #include "base/strings/string_piece.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/supervised_user/kids_chrome_management/kidschromemanagement_messages.pb.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" namespace { using ::base::StringPiece;
diff --git a/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager_unittest.cc b/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager_unittest.cc index 6339726..f66c38a 100644 --- a/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager_unittest.cc +++ b/chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager_unittest.cc
@@ -8,9 +8,10 @@ #include "base/strings/string_piece.h" #include "chrome/browser/supervised_user/kids_chrome_management/kidschromemanagement_messages.pb.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/supervised_user/parental_control_metrics_unittest.cc b/chrome/browser/supervised_user/parental_control_metrics_unittest.cc index cc47601b..53259a58 100644 --- a/chrome/browser/supervised_user/parental_control_metrics_unittest.cc +++ b/chrome/browser/supervised_user/parental_control_metrics_unittest.cc
@@ -24,6 +24,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/supervised_user/core/common/pref_names.h" #include "components/sync_preferences/pref_service_syncable.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/supervised_user/permission_request_creator_mock.cc b/chrome/browser/supervised_user/permission_request_creator_mock.cc index dc98da35..014efd49 100644 --- a/chrome/browser/supervised_user/permission_request_creator_mock.cc +++ b/chrome/browser/supervised_user/permission_request_creator_mock.cc
@@ -11,9 +11,9 @@ #include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" namespace {
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc index 4f4c786..5b110b28 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.cc +++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -22,13 +22,13 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/web_approvals_manager.h" -#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_delegate.h" #include "components/prefs/pref_service.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/pref_names.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc index 5c4f013..71c25bfe 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator_mock.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_interstitial.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service.h" @@ -36,6 +35,7 @@ #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc index 031dc63..4cf0348 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -18,7 +18,6 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/common/chrome_switches.h" @@ -30,6 +29,8 @@ #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/base/signin_switches.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "extensions/buildflags/buildflags.h" namespace {
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc b/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc index 11d3f2b5..55a829c 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc
@@ -10,7 +10,6 @@ #include "base/test/scoped_feature_list.h" #include "base/values.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_pref_store.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/common/net/safe_search_util.h" @@ -18,6 +17,8 @@ #include "components/autofill/core/common/autofill_prefs.h" #include "components/prefs/testing_pref_store.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "extensions/buildflags/buildflags.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index e66fea5..4b38e1f 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -30,7 +30,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" @@ -43,6 +42,8 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/supervised_user/core/common/features.h" +#include "components/supervised_user/core/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_user_settings.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service_browsertest.cc b/chrome/browser/supervised_user/supervised_user_service_browsertest.cc index 98a3e1e..de1fc17 100644 --- a/chrome/browser/supervised_user/supervised_user_service_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_service_browsertest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" @@ -32,6 +31,7 @@ #include "chrome/common/net/safe_search_util.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" #include "content/public/test/url_loader_interceptor.h"
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc index d59692b0..16f110d 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -19,10 +19,10 @@ #include "base/strings/string_util.h" #include "base/task/sequenced_task_runner.h" #include "base/values.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/chrome_constants.h" #include "components/prefs/json_pref_store.h" #include "components/prefs/pref_filter.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync/model/sync_change.h" #include "components/sync/model/sync_change_processor.h" #include "components/sync/protocol/entity_specifics.pb.h"
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc index 834255e6..c0d20838 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc
@@ -12,8 +12,8 @@ #include "base/json/json_reader.h" #include "base/strings/string_util.h" #include "base/test/mock_callback.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "components/prefs/testing_pref_store.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/sync/model/sync_change.h" #include "components/sync/protocol/entity_specifics.pb.h" #include "components/sync/protocol/managed_user_setting_specifics.pb.h"
diff --git a/chrome/browser/supervised_user/supervised_user_model_type_controller_unittest.cc b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller_unittest.cc similarity index 100% rename from chrome/browser/supervised_user/supervised_user_model_type_controller_unittest.cc rename to chrome/browser/supervised_user/supervised_user_sync_model_type_controller_unittest.cc
diff --git a/chrome/browser/supervised_user/supervised_user_test_util.cc b/chrome/browser/supervised_user/supervised_user_test_util.cc index c629b26..f213458 100644 --- a/chrome/browser/supervised_user/supervised_user_test_util.cc +++ b/chrome/browser/supervised_user/supervised_user_test_util.cc
@@ -5,8 +5,8 @@ #include "chrome/browser/supervised_user/supervised_user_test_util.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/pref_names.h" namespace supervised_user_test_util {
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc b/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc index 45ea637..f5a4951f 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_url_filter_browsertest.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_interstitial.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service.h" @@ -34,6 +33,7 @@ #include "components/infobars/core/infobar.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/supervised_user/web_approvals_manager.cc b/chrome/browser/supervised_user/web_approvals_manager.cc index c1b3be31..6c129f9 100644 --- a/chrome/browser/supervised_user/web_approvals_manager.cc +++ b/chrome/browser/supervised_user/web_approvals_manager.cc
@@ -15,9 +15,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/url_matcher/url_util.h" #include "content/public/browser/web_contents.h" #include "url/gurl.h"
diff --git a/chrome/browser/sync/test/integration/sync_integration_tests_sources.gni b/chrome/browser/sync/test/integration/sync_integration_tests_sources.gni index 8acc609..eb9c7a79 100644 --- a/chrome/browser/sync/test/integration/sync_integration_tests_sources.gni +++ b/chrome/browser/sync/test/integration/sync_integration_tests_sources.gni
@@ -52,6 +52,7 @@ "../browser/sync/test/integration/two_client_autocomplete_sync_test.cc", "../browser/sync/test/integration/two_client_autofill_sync_test.cc", "../browser/sync/test/integration/two_client_bookmarks_sync_test.cc", + "../browser/sync/test/integration/two_client_contact_info_sync_test.cc", "../browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc", "../browser/sync/test/integration/two_client_dictionary_sync_test.cc", "../browser/sync/test/integration/two_client_extension_apps_sync_test.cc",
diff --git a/chrome/browser/sync/test/integration/two_client_contact_info_sync_test.cc b/chrome/browser/sync/test/integration/two_client_contact_info_sync_test.cc new file mode 100644 index 0000000..166652d9 --- /dev/null +++ b/chrome/browser/sync/test/integration/two_client_contact_info_sync_test.cc
@@ -0,0 +1,160 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <tuple> +#include <vector> + +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/sync/test/integration/contact_info_helper.h" +#include "chrome/browser/sync/test/integration/status_change_checker.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/personal_data_manager_observer.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/sync/base/features.h" +#include "components/sync/test/fake_server_http_post_provider.h" +#include "content/public/test/browser_test.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +using autofill::AutofillProfile; +using autofill::PersonalDataManager; +using contact_info_helper::BuildTestAccountProfile; +using contact_info_helper::GetPersonalDataManager; +using contact_info_helper::PersonalDataManagerProfileChecker; +using testing::UnorderedElementsAre; + +MATCHER(PointeeEquals, "") { + return *std::get<0>(arg) == *std::get<1>(arg); +} + +// Helper class to wait until all clients have the same profiles. +class AutofillProfilesEqualChecker + : public StatusChangeChecker, + public autofill::PersonalDataManagerObserver { + public: + explicit AutofillProfilesEqualChecker(std::vector<Profile*> profiles) { + for (Profile* profile : profiles) { + pdms_.push_back(contact_info_helper::GetPersonalDataManager(profile)); + pdms_.back()->AddObserver(this); + } + } + + ~AutofillProfilesEqualChecker() override { + for (PersonalDataManager* pdm : pdms_) { + pdm->RemoveObserver(this); + } + } + + // StatusChangeChecker implementation. + bool IsExitConditionSatisfied(std::ostream* os) override { + if (pdms_.empty()) { + return true; + } + // Compare the profiles of `pdms_[0]` with every other PDM's profiles. + testing::Matcher<std::vector<AutofillProfile*>> matcher = + testing::UnorderedPointwise(PointeeEquals(), pdms_[0]->GetProfiles()); + for (size_t i = 1; i < pdms_.size(); i++) { + testing::StringMatchResultListener listener; + if (!testing::ExplainMatchResult(matcher, pdms_[i]->GetProfiles(), + &listener)) { + *os << listener.str(); + return false; + } + } + return true; + } + + // PersonalDataManagerObserver implementation. + void OnPersonalDataChanged() override { CheckExitCondition(); } + + private: + std::vector<PersonalDataManager*> pdms_; +}; + +class TwoClientContactInfoSyncTest : public SyncTest { + public: + TwoClientContactInfoSyncTest() : SyncTest(TWO_CLIENT) { + features_.InitWithFeatures( + /*enabled_features=*/{syncer::kSyncEnableContactInfoDataType, + autofill::features:: + kAutofillAccountProfilesUnionView}, + /*disabled_features=*/{}); + } + + private: + base::test::ScopedFeatureList features_; +}; + +IN_PROC_BROWSER_TEST_F(TwoClientContactInfoSyncTest, SyncAddUpdateDelete) { + ASSERT_TRUE(SetupSync()); + // Add `profile` on client 0 and expect it to appear on client 1. + AutofillProfile profile = BuildTestAccountProfile(); + GetPersonalDataManager(GetProfile(0))->AddProfile(profile); + // Here and below `AutofillProfilesEqualChecker()` cannot be used directly. + // Since `AddProfile()` happens asynchronously, the condition would be true + // immediately, because no profiles are stored in either PDM yet. + EXPECT_TRUE( + PersonalDataManagerProfileChecker(GetPersonalDataManager(GetProfile(1)), + UnorderedElementsAre(profile)) + .Wait()); + // Now update it from client 1 and expect the update on client 0. + profile.SetRawInfo(autofill::EMAIL_ADDRESS, + u"new-" + profile.GetRawInfo(autofill::EMAIL_ADDRESS)); + GetPersonalDataManager(GetProfile(1))->UpdateProfile(profile); + EXPECT_TRUE( + PersonalDataManagerProfileChecker(GetPersonalDataManager(GetProfile(0)), + UnorderedElementsAre(profile)) + .Wait()); + // Finally, remove the `profile` from client 0 and expect removal on client 1. + GetPersonalDataManager(GetProfile(0))->RemoveByGUID(profile.guid()); + EXPECT_TRUE(PersonalDataManagerProfileChecker( + GetPersonalDataManager(GetProfile(1)), testing::IsEmpty()) + .Wait()); +} + +// Adds different profiles with identical GUIDs from both clients. Expects that +// only one copy is retained at each client. +// Since new and migrated profiles receive a randomly generated GUID, collisions +// like this are not expected in practice. +// Whichever profile makes it to the server first wins, since clients always +// merge in favor of the remote version. +IN_PROC_BROWSER_TEST_F(TwoClientContactInfoSyncTest, DuplicateGUID) { + const AutofillProfile kProfile0 = BuildTestAccountProfile(); + // Constructs a second profile with the same GUID but different content (the + // exact difference is irrelevant). The lambda is used to keep it const. + const AutofillProfile kProfile1 = [&] { + AutofillProfile profile = kProfile0; + profile.SetRawInfo(autofill::EMAIL_ADDRESS, + u"new-" + profile.GetRawInfo(autofill::EMAIL_ADDRESS)); + return profile; + }(); + CHECK_EQ(kProfile0.guid(), kProfile1.guid()); + CHECK_NE(kProfile0, kProfile1); + ASSERT_TRUE(SetupSync()); + + // Since `AddProfile()` happens asynchronously, wait for the change to + // propagate locally. + fake_server::FakeServerHttpPostProvider::DisableNetwork(); + GetPersonalDataManager(GetProfile(0))->AddProfile(kProfile0); + GetPersonalDataManager(GetProfile(1))->AddProfile(kProfile1); + EXPECT_TRUE( + PersonalDataManagerProfileChecker(GetPersonalDataManager(GetProfile(0)), + UnorderedElementsAre(kProfile0)) + .Wait()); + EXPECT_TRUE( + PersonalDataManagerProfileChecker(GetPersonalDataManager(GetProfile(1)), + UnorderedElementsAre(kProfile1)) + .Wait()); + + // Sync and expect equal profiles eventually. + fake_server::FakeServerHttpPostProvider::EnableNetwork(); + EXPECT_TRUE(AutofillProfilesEqualChecker(GetAllProfiles()).Wait()); +} + +} // namespace
diff --git a/chrome/browser/tabmodel/OWNERS b/chrome/browser/tabmodel/OWNERS index 722432c2..69e8b30 100644 --- a/chrome/browser/tabmodel/OWNERS +++ b/chrome/browser/tabmodel/OWNERS
@@ -2,3 +2,4 @@ dtrainor@chromium.org hnakashima@chromium.org meiliang@chromium.org +wnwen@chromium.org
diff --git a/chrome/browser/tabmodel/internal/BUILD.gn b/chrome/browser/tabmodel/internal/BUILD.gn index e2465734..30b06ca 100644 --- a/chrome/browser/tabmodel/internal/BUILD.gn +++ b/chrome/browser/tabmodel/internal/BUILD.gn
@@ -6,15 +6,25 @@ android_library("java") { visibility = [ "//chrome/android:*" ] + + # This target is currently used to ensure that we avoid regressing the Kotlin + # support added in http://go/crrv/c/4179272. sources = [ + # These two factory files need to stay as Java files for the + # //chrome/browser/tabmodel:factory_javafactory target. "android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerFactory.java", - "android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.java", "android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerFactory.java", + + # Please keep this file in Kotlin to prevent regressions in kotlin support. + "android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.kt", + + # Please keep the following file in Java for build_speed/benchmark.py. "android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java", ] deps = [ "//base:base_java", "//chrome/browser/tab:java", "//chrome/browser/tabmodel:java", + "//third_party/android_deps:org_jetbrains_kotlin_kotlin_stdlib_java", ] }
diff --git a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.java b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.java deleted file mode 100644 index 1336a73..0000000 --- a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.java +++ /dev/null
@@ -1,96 +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.chrome.browser.tabmodel; - -import android.util.SparseArray; - -import org.chromium.chrome.browser.tab.Tab; - -/** - * Data that will be used later when a tab is opened via an intent. Often only the necessary - * subset of the data will be set. All data is removed once the tab finishes initializing. - */ -public class AsyncTabParamsManagerImpl implements AsyncTabParamsManager { - /** A map of tab IDs to AsyncTabParams consumed by Activities started asynchronously. */ - private final SparseArray<AsyncTabParams> mAsyncTabParams = new SparseArray<>(); - - private boolean mAddedToIncognitoTabHostRegistry; - - @Override - public void add(int tabId, AsyncTabParams params) { - mAsyncTabParams.put(tabId, params); - - if (!mAddedToIncognitoTabHostRegistry) { - // Make sure async incognito tabs are taken into account when, for example, - // checking if any incognito tabs exist. - IncognitoTabHostRegistry.getInstance().register(new AsyncTabsIncognitoTabHost(this)); - mAddedToIncognitoTabHostRegistry = true; - } - } - - @Override - public boolean hasParamsForTabId(int tabId) { - return mAsyncTabParams.get(tabId) != null; - } - - @Override - public boolean hasParamsWithTabToReparent() { - for (int i = 0; i < mAsyncTabParams.size(); i++) { - if (mAsyncTabParams.get(mAsyncTabParams.keyAt(i)).getTabToReparent() == null) continue; - return true; - } - return false; - } - - @Override - public SparseArray<AsyncTabParams> getAsyncTabParams() { - return mAsyncTabParams; - } - - @Override - public AsyncTabParams remove(int tabId) { - AsyncTabParams data = mAsyncTabParams.get(tabId); - mAsyncTabParams.remove(tabId); - return data; - } - - AsyncTabParamsManagerImpl() {} - - private static class AsyncTabsIncognitoTabHost implements IncognitoTabHost { - private final AsyncTabParamsManager mAsyncTabParamsManager; - - private AsyncTabsIncognitoTabHost(AsyncTabParamsManager asyncTabParamsManager) { - mAsyncTabParamsManager = asyncTabParamsManager; - } - - @Override - public boolean hasIncognitoTabs() { - SparseArray<AsyncTabParams> asyncTabParams = mAsyncTabParamsManager.getAsyncTabParams(); - for (int i = 0; i < asyncTabParams.size(); i++) { - Tab tab = asyncTabParams.valueAt(i).getTabToReparent(); - if (tab != null && tab.isIncognito()) { - return true; - } - } - return false; - } - - @Override - public void closeAllIncognitoTabs() { - SparseArray<AsyncTabParams> asyncTabParams = mAsyncTabParamsManager.getAsyncTabParams(); - for (int i = 0; i < asyncTabParams.size(); i++) { - Tab tab = asyncTabParams.valueAt(i).getTabToReparent(); - if (tab != null && tab.isIncognito()) { - mAsyncTabParamsManager.remove(tab.getId()); - } - } - } - - @Override - public boolean isActiveModel() { - return false; - } - } -}
diff --git a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.kt b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.kt new file mode 100644 index 0000000..cbf59aec7 --- /dev/null +++ b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManagerImpl.kt
@@ -0,0 +1,75 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.tabmodel + +import android.util.SparseArray + +/** + * Data that will be used later when a tab is opened via an intent. Often only the necessary subset + * of the data will be set. All data is removed once the tab finishes initializing. + */ +class AsyncTabParamsManagerImpl internal constructor() : AsyncTabParamsManager { + /** A map of tab IDs to AsyncTabParams consumed by Activities started asynchronously. */ + private val mAsyncTabParams = SparseArray<AsyncTabParams>() + private var mAddedToIncognitoTabHostRegistry = false + + override fun add(tabId: Int, params: AsyncTabParams) { + mAsyncTabParams.put(tabId, params) + if (!mAddedToIncognitoTabHostRegistry) { + // Make sure async incognito tabs are taken into account when, for example, + // checking if any incognito tabs exist. + IncognitoTabHostRegistry.getInstance().register(AsyncTabsIncognitoTabHost(this)) + mAddedToIncognitoTabHostRegistry = true + } + } + + override fun hasParamsForTabId(tabId: Int) = mAsyncTabParams[tabId] != null + + override fun hasParamsWithTabToReparent(): Boolean { + for (i in 0 until mAsyncTabParams.size()) { + if (mAsyncTabParams[mAsyncTabParams.keyAt(i)].tabToReparent == null) continue + return true + } + return false + } + + override fun getAsyncTabParams(): SparseArray<AsyncTabParams> { + return mAsyncTabParams + } + + override fun remove(tabId: Int): AsyncTabParams? { + val data = mAsyncTabParams[tabId] + mAsyncTabParams.remove(tabId) + return data + } + + private class AsyncTabsIncognitoTabHost( + private val mAsyncTabParamsManager: AsyncTabParamsManager + ) : IncognitoTabHost { + override fun hasIncognitoTabs(): Boolean { + val asyncTabParams = mAsyncTabParamsManager.asyncTabParams + for (i in 0 until asyncTabParams.size()) { + val tab = asyncTabParams.valueAt(i).tabToReparent + if (tab != null && tab.isIncognito) { + return true + } + } + return false + } + + override fun closeAllIncognitoTabs() { + val asyncTabParams = mAsyncTabParamsManager.asyncTabParams + for (i in 0 until asyncTabParams.size()) { + val tab = asyncTabParams.valueAt(i).tabToReparent + if (tab != null && tab.isIncognito) { + mAsyncTabParamsManager.remove(tab.id) + } + } + } + + override fun isActiveModel(): Boolean { + return false + } + } +}
diff --git a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java index ff1f3f86..02139be 100644 --- a/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java +++ b/chrome/browser/tabmodel/internal/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerImpl.java
@@ -61,6 +61,8 @@ return Pair.create(i, assignedSelector); } } + // The following log statement is used in tools/android/build_speed/benchmark.py. Please + // update the string there if this string is updated. throw new IllegalStateException( "TabModelSelector is assigned to an Activity but has no index."); }
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index 72516f7..bf46d27c 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -1471,8 +1471,9 @@ feature_list_.InitWithFeaturesAndParameters( /*enabled_features=*/ { - {features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}, + {features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}, {features::kOmniboxTriggerForPrerender2, {}}, }, /*disabled_features=*/{});
diff --git a/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc b/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc index 8966346..973160b 100644 --- a/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc +++ b/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc
@@ -188,6 +188,13 @@ return ChildFrameAt(GetFrame(), 0); } + std::string CookiesFromFetchWithCredentials(content::RenderFrameHost* frame, + const std::string& host, + const bool cors_enabled) { + return storage::test::FetchWithCredentials( + frame, https_server_.GetURL(host, "/echoheader?cookie"), cors_enabled); + } + net::test_server::EmbeddedTestServer& https_server() { return https_server_; } private: @@ -204,14 +211,12 @@ SetBlockThirdPartyCookies(true); // Set a cookie on `kHostB` and `kHostC`. - content::SetCookie(browser()->profile(), GetURL(kHostB), - "thirdparty=b;SameSite=None;Secure"); + SetCrossSiteCookieOnHost(kHostB); ASSERT_EQ(content::GetCookies(browser()->profile(), GetURL(kHostB)), - "thirdparty=b"); - content::SetCookie(browser()->profile(), GetURL(kHostC), - "thirdparty=c;SameSite=None;Secure"); + "cross-site=b.test"); + SetCrossSiteCookieOnHost(kHostC); ASSERT_EQ(content::GetCookies(browser()->profile(), GetURL(kHostC)), - "thirdparty=c"); + "cross-site=c.test"); NavigateToPageWithFrame(kHostA); NavigateFrameTo(kHostB, "/iframe.html"); @@ -253,15 +258,23 @@ ->GetCookieManagerForBrowserProcess() ->SetTopLevelStorageAccessSettings(settings, base::DoNothing()); + // document.hasStorageAccess() does not have cookie access with top-level + // storage access grant. EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); NavigateFrameTo(kHostB, "/iframe.html"); NavigateNestedFrameTo(kHostC, "/echoheader?cookie"); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); - EXPECT_EQ(GetNestedFrameContent(), "thirdparty=c"); - EXPECT_EQ(ReadCookiesViaJS(GetNestedFrame()), "thirdparty=c"); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetNestedFrame())); + EXPECT_EQ(GetNestedFrameContent(), "None"); + EXPECT_EQ(ReadCookiesViaJS(GetNestedFrame()), ""); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetNestedFrame(), kHostC, + /*cors_enabled=*/true), + "cross-site=c.test"); } IN_PROC_BROWSER_TEST_F(RequestStorageAccessForOriginBrowserTest, @@ -336,6 +349,9 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostASubdomain, + /*cors_enabled=*/true), + "None"); } // Tests to validate First-Party Set use with `requestStorageAccessForOrigin`. @@ -384,23 +400,29 @@ // the requestor, because it is a service domain. EXPECT_TRUE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostB).spec())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); // Repeated calls should also return true. EXPECT_TRUE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostB).spec())); // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that - // the cookie is sent. + // the cookie is sent for the cors-enabled subresource request. NavigateFrameTo(kHostB, "/echoheader?cookie"); - EXPECT_EQ(GetFrameContent(), "cross-site=b.test"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); - - // Also validate that an additional site C was not granted access. - NavigateFrameTo(kHostC, "/echoheader?cookie"); EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); + + // Also validate that an additional site C was not granted access. + NavigateFrameTo(kHostC, "/echoheader?cookie"); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostC, + /*cors_enabled=*/true), + "None"); content::FetchHistogramsFromChildProcesses(); @@ -426,6 +448,9 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostA, + /*cors_enabled=*/true), + "None"); // The promise should be rejected; `khostB` is a service domain. EXPECT_FALSE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostA).spec())); @@ -437,6 +462,9 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostA, + /*cors_enabled=*/true), + "None"); content::FetchHistogramsFromChildProcesses(); EXPECT_THAT(histogram_tester.GetBucketCount( @@ -461,12 +489,18 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); // `kHostB` cannot be granted access via `RequestStorageAccessForOrigin`, // because the call is not from the top-level page and because `kHostB` is a // service domain. EXPECT_FALSE(storage::test::RequestStorageAccessForOrigin( GetFrame(), GetURL(kHostA).spec())); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that // the cookie is not sent. @@ -474,6 +508,9 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); // However, a regular `requestStorageAccess` call should be granted; // requesting on behalf of another domain is what is not acceptable. @@ -511,6 +548,9 @@ EXPECT_FALSE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostD).spec())); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostD, + /*cors_enabled=*/true), + "None"); // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that // the cookie is not sent. @@ -518,6 +558,9 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostD, + /*cors_enabled=*/true), + "None"); content::FetchHistogramsFromChildProcesses(); EXPECT_THAT(histogram_tester.GetBucketCount( @@ -542,24 +585,37 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); EXPECT_TRUE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostB).spec())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that - // the cookie is sent: + // the cookie is sent for the cors-enabled subresource request. NavigateFrameTo(kHostB, "/echoheader?cookie"); - EXPECT_EQ(GetFrameContent(), "cross-site=b.test"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(GetFrameContent(), "None"); + EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); + // Subresource request with cors disabled does not have cookie access. + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/false), + "None"); NavigateToPageWithFrame(kHostASubdomain); NavigateFrameTo(kHostB, "/echoheader?cookie"); // Storage access grants are scoped to the embedded origin on the top-level - // site. Accordingly, the access should be granted. - EXPECT_EQ(GetFrameContent(), "cross-site=b.test"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + // site. Accordingly, the access is be granted for subresource request. + EXPECT_EQ(GetFrameContent(), "None"); + EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); } IN_PROC_BROWSER_TEST_F( @@ -578,24 +634,37 @@ EXPECT_EQ(GetFrameContent(), "None"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "None"); EXPECT_TRUE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostB).spec())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that - // the cookie is sent: + // the cookie is sent for the cors-enabled subresource request. NavigateFrameTo(kHostB, "/echoheader?cookie"); - EXPECT_EQ(GetFrameContent(), "cross-site=b.test"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(GetFrameContent(), "None"); + EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); + // Subresource request with cors disabled does not have cookie access. + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/false), + "None"); NavigateToPageWithFrame(kHostA); NavigateFrameTo(kHostB, "/echoheader?cookie"); // When top-level site scoping is enabled, the subdomain's grant counts for // the less-specific domain; otherwise, it does not. - EXPECT_EQ(GetFrameContent(), "cross-site=b.test"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(GetFrameContent(), "None"); + EXPECT_EQ(ReadCookiesViaJS(GetFrame()), ""); + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test"); } // Tests to validate `requestStorageAccessForOrigin` behavior with FPS disabled. @@ -737,22 +806,22 @@ EXPECT_EQ(GetFrameContent(), "cross-site=b.test(partitioned)"); EXPECT_EQ(ReadCookiesViaJS(GetFrame()), "cross-site=b.test(partitioned)"); EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), + "cross-site=b.test(partitioned)"); // kHostA can request storage access on behalf of kHostB, and it is granted // (by an implicit grant): EXPECT_TRUE(storage::test::RequestStorageAccessForOrigin( GetPrimaryMainFrame(), GetURL(kHostB).spec())); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); - - // When the frame subsequently navigates to an endpoint on kHostB, kHostB's - // unpartitioned and partitioned cookies are sent, and the iframe retains - // storage access. + // When the frame makes a subresource request to an endpoint on kHostB, + // kHostB's unpartitioned and partitioned cookies are sent, and the iframe + // retains storage access. NavigateFrameTo(kHostB, "/echoheader?cookie"); - EXPECT_EQ(GetFrameContent(), + EXPECT_FALSE(storage::test::HasStorageAccessForFrame(GetFrame())); + EXPECT_EQ(CookiesFromFetchWithCredentials(GetFrame(), kHostB, + /*cors_enabled=*/true), "cross-site=b.test; cross-site=b.test(partitioned)"); - EXPECT_EQ(ReadCookiesViaJS(GetFrame()), - "cross-site=b.test; cross-site=b.test(partitioned)"); - EXPECT_TRUE(storage::test::HasStorageAccessForFrame(GetFrame())); } } // namespace
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e6221c4f..ff7d4590 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3905,8 +3905,6 @@ "views/frame/immersive_mode_controller_mac.h", "views/frame/immersive_mode_controller_mac.mm", "views/frame/native_browser_frame_factory_mac.mm", - "views/frame/window_controls_overlay_input_routing_mac.h", - "views/frame/window_controls_overlay_input_routing_mac.mm", "views/tab_contents/chrome_web_contents_view_delegate_views_mac.h", "views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm", "webui/help/version_updater_mac.h", @@ -4216,6 +4214,10 @@ "autofill/payments/save_card_bubble_controller_impl.cc", "autofill/payments/save_card_bubble_controller_impl.h", "autofill/payments/save_card_ui.h", + "autofill/payments/save_iban_bubble_controller.h", + "autofill/payments/save_iban_bubble_controller_impl.cc", + "autofill/payments/save_iban_bubble_controller_impl.h", + "autofill/payments/save_iban_ui.h", "autofill/payments/save_payment_icon_controller.cc", "autofill/payments/save_payment_icon_controller.h", "autofill/payments/save_upi_bubble.h", @@ -4361,6 +4363,8 @@ "views/autofill/payments/save_card_manage_cards_bubble_views.h", "views/autofill/payments/save_card_offer_bubble_views.cc", "views/autofill/payments/save_card_offer_bubble_views.h", + "views/autofill/payments/save_iban_bubble_view.cc", + "views/autofill/payments/save_iban_bubble_view.h", "views/autofill/payments/save_payment_icon_view.cc", "views/autofill/payments/save_payment_icon_view.h", "views/autofill/payments/save_upi_offer_bubble_views.cc", @@ -5070,8 +5074,6 @@ "views/side_panel/webview/webview_side_panel_coordinator.h", "views/side_search/default_search_icon_source.cc", "views/side_search/default_search_icon_source.h", - "views/side_search/side_search_browser_controller.cc", - "views/side_search/side_search_browser_controller.h", "views/side_search/side_search_icon_view.cc", "views/side_search/side_search_icon_view.h", "views/side_search/side_search_views_utils.cc", @@ -5740,6 +5742,8 @@ "web_applications/web_app_ui_utils.cc", "web_applications/web_app_ui_utils.h", "web_applications/web_app_uninstall_dialog.h", + "web_applications/webui_web_app_navigation_throttle.cc", + "web_applications/webui_web_app_navigation_throttle.h", "webui/extensions/extension_basic_info.cc", "webui/extensions/extension_basic_info.h", "webui/extensions/extension_icon_source.cc",
diff --git a/chrome/browser/ui/android/fast_checkout/java/src/org/chromium/chrome/browser/ui/fast_checkout/data/FastCheckoutCreditCard.java b/chrome/browser/ui/android/fast_checkout/java/src/org/chromium/chrome/browser/ui/fast_checkout/data/FastCheckoutCreditCard.java index bd4bdf466..9ebbf66 100644 --- a/chrome/browser/ui/android/fast_checkout/java/src/org/chromium/chrome/browser/ui/fast_checkout/data/FastCheckoutCreditCard.java +++ b/chrome/browser/ui/android/fast_checkout/java/src/org/chromium/chrome/browser/ui/fast_checkout/data/FastCheckoutCreditCard.java
@@ -5,13 +5,13 @@ package org.chromium.chrome.browser.ui.fast_checkout.data; import android.content.Context; +import android.util.ArrayMap; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.browser.ui.fast_checkout.R; import org.chromium.components.autofill.VirtualCardEnrollmentState; import org.chromium.url.GURL; -import java.util.HashMap; import java.util.Map; /** @@ -20,22 +20,23 @@ public class FastCheckoutCreditCard { // Mappings from name: chrome/browser/ui/autofill/autofill_popup_controller_utils.cc // Mappings to resource: chrome/browser/android/resource_id.h - private static final Map<String, Integer> sResourceMap = new HashMap<String, Integer>() { - { - put("americanExpressCC", R.drawable.amex_card); - put("dinersCC", R.drawable.diners_card); - put("discoverCC", R.drawable.discover_card); - put("eloCC", R.drawable.elo_card); - put("genericCC", R.drawable.ic_credit_card_black); - put("jcbCC", R.drawable.jcb_card); - put("masterCardCC", R.drawable.mc_card); - put("mirCC", R.drawable.mir_card); - put("troyCC", R.drawable.troy_card); - put("unionPayCC", R.drawable.unionpay_card); - put("visaCC", R.drawable.visa_card); - put("googlePay", R.drawable.google_pay); - } - }; + private static final Map<String, Integer> sResourceMap; + static { + Map<String, Integer> map = new ArrayMap<>(); + map.put("americanExpressCC", R.drawable.amex_card); + map.put("dinersCC", R.drawable.diners_card); + map.put("discoverCC", R.drawable.discover_card); + map.put("eloCC", R.drawable.elo_card); + map.put("genericCC", R.drawable.ic_credit_card_black); + map.put("jcbCC", R.drawable.jcb_card); + map.put("masterCardCC", R.drawable.mc_card); + map.put("mirCC", R.drawable.mir_card); + map.put("troyCC", R.drawable.troy_card); + map.put("unionPayCC", R.drawable.unionpay_card); + map.put("visaCC", R.drawable.visa_card); + map.put("googlePay", R.drawable.google_pay); + sResourceMap = map; + } private final String mGUID; private final String mOrigin; private final boolean mIsLocal;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index dbfe4e14..2b30bcd0 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -760,11 +760,6 @@ mListPropertyModel.set(SuggestionListProperties.LIST_IS_FINAL, isFinal); } - @Override - public void setGroupCollapsedState(int groupId, boolean state) { - mDropdownViewInfoListManager.setGroupCollapsedState(groupId, state); - } - /** * Load the url corresponding to the typed omnibox text. * @param eventTime The timestamp the load was triggered by the user.
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java index e0f97e3..55678e6 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java
@@ -4,10 +4,9 @@ package org.chromium.chrome.browser.omnibox.suggestions; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_EXPANDED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_COLLAPSED_WITH_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_EXPANDED_WITH_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_EXPANDED_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_NO_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_WITH_HEADER; import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_INVALID; import android.util.ArraySet; @@ -150,9 +149,9 @@ @SmallTest public void groupsDetails_cacheAllSaneGroupConfig() { var groupsDetails = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .putGroupConfigs(30, SECTION_3_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) + .putGroupConfigs(30, SECTION_3_WITH_HEADER) .build(); AutocompleteResult dataToCache = AutocompleteResult.fromCache(null, groupsDetails); @@ -166,8 +165,8 @@ public void groupsDetails_restoreInvalidGroupsDetailsFromCache() { final SharedPreferencesManager manager = SharedPreferencesManager.getInstance(); var groupsDetails = GroupsInfo.newBuilder() - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .putGroupConfigs(30, SECTION_1_EXPANDED_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) + .putGroupConfigs(30, SECTION_1_NO_HEADER) .build(); // Write to disk. @@ -210,7 +209,7 @@ list.add(createSuggestionBuilder(33).setGroupId(1).build()); var groupsDetails = - GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_COLLAPSED_WITH_HEADER).build(); + GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_WITH_HEADER).build(); AutocompleteResult dataToCache = AutocompleteResult.fromCache(list, groupsDetails); CachedZeroSuggestionsManager.saveToCache(dataToCache); @@ -273,12 +272,12 @@ // Write 3 wrong group groupsDetails to the cache var groupsDetailsExpected = GroupsInfo.newBuilder() - .putGroupConfigs(12, SECTION_2_COLLAPSED_WITH_HEADER) + .putGroupConfigs(12, SECTION_2_WITH_HEADER) .putGroupConfigs(AutocompleteMatch.INVALID_GROUP, SECTION_INVALID) .build(); var groupsDetailsWithInvalidItems = GroupsInfo.newBuilder() - .putGroupConfigs(12, SECTION_2_COLLAPSED_WITH_HEADER) + .putGroupConfigs(12, SECTION_2_WITH_HEADER) .putGroupConfigs(AutocompleteMatch.INVALID_GROUP, SECTION_INVALID) .build();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java index 1276355d..9ae4a767 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java
@@ -16,9 +16,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_EXPANDED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_EXPANDED_WITH_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_EXPANDED_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_NO_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_WITH_HEADER; import androidx.test.filters.SmallTest; @@ -103,7 +103,7 @@ public void headers_buildsHeaderForFirstSuggestion() { final List<AutocompleteMatch> actualList = new ArrayList<>(); final var groupsDetails = - GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_EXPANDED_WITH_HEADER).build(); + GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_WITH_HEADER).build(); when(mMockSuggestionProcessor.doesProcessSuggestion(any(), anyInt())).thenReturn(true); AutocompleteMatch suggestion = @@ -119,7 +119,7 @@ AutocompleteResult.fromCache(actualList, groupsDetails)); verifier.verify(mMockHeaderProcessor, times(1)) - .populateModel(any(), eq(SECTION_2_EXPANDED_WITH_HEADER.getHeaderText())); + .populateModel(any(), eq(SECTION_2_WITH_HEADER.getHeaderText())); verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestion), any(), eq(0)); verifier.verify(mMockSuggestionProcessor, times(1)) @@ -142,8 +142,8 @@ public void headers_buildsHeadersOnlyWhenGroupChanges() { final List<AutocompleteMatch> actualList = new ArrayList<>(); final var groupsDetails = GroupsInfo.newBuilder() - .putGroupConfigs(1, SECTION_2_EXPANDED_WITH_HEADER) - .putGroupConfigs(2, SECTION_3_EXPANDED_WITH_HEADER) + .putGroupConfigs(1, SECTION_2_WITH_HEADER) + .putGroupConfigs(2, SECTION_3_WITH_HEADER) .build(); when(mMockSuggestionProcessor.doesProcessSuggestion(any(), anyInt())).thenReturn(true); @@ -172,13 +172,13 @@ verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionWithNoGroup), any(), eq(0)); verifier.verify(mMockHeaderProcessor, times(1)) - .populateModel(any(), eq(SECTION_2_EXPANDED_WITH_HEADER.getHeaderText())); + .populateModel(any(), eq(SECTION_2_WITH_HEADER.getHeaderText())); verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionForGroup1), any(), eq(1)); verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionForGroup1), any(), eq(2)); verifier.verify(mMockHeaderProcessor, times(1)) - .populateModel(any(), eq(SECTION_3_EXPANDED_WITH_HEADER.getHeaderText())); + .populateModel(any(), eq(SECTION_3_WITH_HEADER.getHeaderText())); verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionForGroup2), any(), eq(3)); verifier.verify(mMockSuggestionProcessor, times(1)) @@ -208,8 +208,8 @@ public void headers_respectGroupHeadersWithNoTitle() { final List<AutocompleteMatch> actualList = new ArrayList<>(); final var groupsDetails = GroupsInfo.newBuilder() - .putGroupConfigs(1, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(2, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(1, SECTION_1_NO_HEADER) + .putGroupConfigs(2, SECTION_2_WITH_HEADER) .build(); when(mMockSuggestionProcessor.doesProcessSuggestion(any(), anyInt())).thenReturn(true); @@ -242,7 +242,7 @@ verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionForGroup1), any(), eq(2)); verifier.verify(mMockHeaderProcessor, times(1)) - .populateModel(any(), eq(SECTION_2_EXPANDED_WITH_HEADER.getHeaderText())); + .populateModel(any(), eq(SECTION_2_WITH_HEADER.getHeaderText())); verifier.verify(mMockSuggestionProcessor, times(1)) .populateModel(eq(suggestionForGroup2), any(), eq(3)); verifier.verify(mMockSuggestionProcessor, times(1)) @@ -475,7 +475,7 @@ final List<AutocompleteMatch> actualList = new ArrayList<>(); final var groupsDetails = - GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_EXPANDED_WITH_HEADER).build(); + GroupsInfo.newBuilder().putGroupConfigs(1, SECTION_2_WITH_HEADER).build(); when(mMockSuggestionProcessor.doesProcessSuggestion(any(), anyInt())).thenReturn(true); AutocompleteMatch suggestion =
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java index aad9ee7..2eb1632d7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.omnibox.suggestions; import android.content.Context; -import android.util.SparseBooleanArray; import android.view.View; import androidx.annotation.NonNull; @@ -14,7 +13,6 @@ import org.chromium.chrome.browser.omnibox.OmniboxFeatures; import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; -import org.chromium.components.omnibox.GroupsProto.GroupConfig; import org.chromium.components.omnibox.GroupsProto.GroupSection; import org.chromium.components.omnibox.GroupsProto.GroupsInfo; import org.chromium.ui.base.DeviceFormFactor; @@ -30,7 +28,6 @@ class DropdownItemViewInfoListManager { private final Context mContext; private final ModelList mManagedModel; - private final SparseBooleanArray mGroupsCollapsedState; private int mLayoutDirection; private @BrandedColorScheme int mBrandedColorScheme; private List<DropdownItemViewInfo> mSourceViewInfoList; @@ -47,7 +44,6 @@ mLayoutDirection = View.LAYOUT_DIRECTION_INHERIT; mBrandedColorScheme = BrandedColorScheme.LIGHT_BRANDED_THEME; mSourceViewInfoList = Collections.emptyList(); - mGroupsCollapsedState = new SparseBooleanArray(); mManagedModel = managedModel; mListActiveOmniboxTopSmallMargin = mContext.getResources().getDimensionPixelSize( @@ -88,30 +84,6 @@ } } - /** - * Toggle the collapsed state of suggestions belonging to specific group. - * - * @param groupId ID of the group whose collapsed state is expected to change. - * @param groupIsCollapsed Collapsed state of the group. - */ - void setGroupCollapsedState(int groupId, boolean groupIsCollapsed) { - if (getGroupCollapsedState(groupId) == groupIsCollapsed) return; - mGroupsCollapsedState.put(groupId, groupIsCollapsed); - if (groupIsCollapsed) { - removeSuggestionsForGroup(groupId); - } else { - insertSuggestionsForGroup(groupId); - } - } - - /** - * @param groupId ID of the suggestions group. - * @return True, if group should be collapsed, otherwise false. - */ - private boolean getGroupCollapsedState(int groupId) { - return mGroupsCollapsedState.get(groupId, /* defaultCollapsedState= */ false); - } - /** @return Whether the supplied view info is a header for the specific group of suggestions. */ private boolean isGroupHeaderWithId(DropdownItemViewInfo info, int groupId) { return (info.type == OmniboxSuggestionUiType.HEADER && info.groupId == groupId); @@ -121,7 +93,6 @@ void clear() { mSourceViewInfoList.clear(); mManagedModel.clear(); - mGroupsCollapsedState.clear(); } void onNativeInitialized() { @@ -137,14 +108,8 @@ void setSourceViewInfoList( @NonNull List<DropdownItemViewInfo> sourceList, @NonNull GroupsInfo groupsInfo) { mSourceViewInfoList = sourceList; - mGroupsCollapsedState.clear(); final var groupsDetails = groupsInfo.getGroupConfigsMap(); - // Clone information about the recommended group collapsed state. - for (var entry : groupsDetails.entrySet()) { - mGroupsCollapsedState.put(entry.getKey(), - entry.getValue().getVisibility() == GroupConfig.Visibility.HIDDEN); - } // Build a new list of suggestions. Honor the default collapsed state. final List<ListItem> suggestionsList = new ArrayList<>(); @@ -198,10 +163,7 @@ previousSection = currentSection; } - final boolean groupIsDefaultCollapsed = getGroupCollapsedState(item.groupId); - if (!groupIsDefaultCollapsed || isGroupHeaderWithId(item, item.groupId)) { - suggestionsList.add(item); - } + suggestionsList.add(item); } // round the bottom corners of the last suggestion. @@ -229,82 +191,6 @@ } /** - * Remove all suggestions that belong to specific group. - * - * @param groupId Group ID of suggestions that should be removed. - */ - private void removeSuggestionsForGroup(int groupId) { - int index; - int count = 0; - - for (index = mManagedModel.size() - 1; index >= 0; index--) { - DropdownItemViewInfo viewInfo = (DropdownItemViewInfo) mManagedModel.get(index); - if (isGroupHeaderWithId(viewInfo, groupId)) { - break; - } else if (viewInfo.groupId == groupId) { - count++; - } else if (count > 0 && viewInfo.groupId != groupId) { - break; - } - } - if (count > 0) { - // Skip group header when dropping items. - mManagedModel.removeRange(index + 1, count); - } - } - - /** - * Insert all suggestions that belong to specific group. - * - * @param groupId Group ID of suggestions that should be removed. - */ - private void insertSuggestionsForGroup(int groupId) { - int insertPosition = 0; - - // Search for the insert position. - // Iterate through all *available* view infos until we find the first element that we - // should insert. To determine the insertion point we skip past all *displayed* view - // infos that were also preceding elements that we want to insert. - for (; insertPosition < mManagedModel.size(); insertPosition++) { - final DropdownItemViewInfo viewInfo = - (DropdownItemViewInfo) mManagedModel.get(insertPosition); - // Insert suggestions directly below their header. - if (isGroupHeaderWithId(viewInfo, groupId)) break; - } - - // Check if reached the end of the list. - if (insertPosition == mManagedModel.size()) return; - - // insertPosition points to header - advance the index and see if we already have - // elements belonging to that group on the list. - insertPosition++; - if (insertPosition < mManagedModel.size() - && ((DropdownItemViewInfo) mManagedModel.get(insertPosition)).groupId == groupId) { - return; - } - - // Find elements to insert. - int firstElementIndex = -1; - int count = 0; - for (int index = 0; index < mSourceViewInfoList.size(); index++) { - final DropdownItemViewInfo viewInfo = mSourceViewInfoList.get(index); - if (isGroupHeaderWithId(viewInfo, groupId)) { - firstElementIndex = index + 1; - } else if (viewInfo.groupId == groupId) { - count++; - } else if (count > 0 && viewInfo.groupId != groupId) { - break; - } - } - - if (count != 0 && firstElementIndex != -1) { - mManagedModel.addAll( - mSourceViewInfoList.subList(firstElementIndex, firstElementIndex + count), - insertPosition); - } - } - - /** * Return the top margin for the suggestion list in pixel size. * The padding size between the Omnibox and the top suggestion is dependent on the top * suggestion type and variations of the experiment:
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManagerUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManagerUnitTest.java index 4e133af..1cdcb29 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManagerUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManagerUnitTest.java
@@ -4,18 +4,10 @@ package org.chromium.chrome.browser.omnibox.suggestions; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_COLLAPSED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_EXPANDED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_COLLAPSED_WITH_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_EXPANDED_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_NO_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_WITH_HEADER; import android.content.Context; import android.view.View; @@ -132,207 +124,6 @@ @Test @SmallTest - public void modelUpdates_visibilityChangesOnlyUpdateTheModel() { - // This change confirms that we do not re-create entire model, but instead insert/remove - // items that have been added/removed from the list. - final List<DropdownItemViewInfo> list = Arrays.asList( - // Group 1: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - // Group 2: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2)); - - mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder().build()); - verifyModelEquals(list); - - // Monitor updates moving forward. - reset(mListObserver); - - // Collapse group 1. - mManager.setGroupCollapsedState(1, true); - verify(mListObserver, times(1)).onItemRangeRemoved(any(), eq(1), eq(2)); - // Collapse group 2. - mManager.setGroupCollapsedState(2, true); - verify(mListObserver, times(1)).onItemRangeRemoved(any(), eq(2), eq(2)); - - // Expand group 1. - mManager.setGroupCollapsedState(1, false); - verify(mListObserver, times(1)).onItemRangeInserted(any(), eq(1), eq(2)); - - // Expand group 2. - mManager.setGroupCollapsedState(2, false); - verify(mListObserver, times(1)).onItemRangeInserted(any(), eq(4), eq(2)); - - verifyNoMoreInteractions(mListObserver); - } - - @Test - @SmallTest - public void groupHandling_toggleGroupExpandedState() { - final List<DropdownItemViewInfo> listWithBothGroupsExpanded = Arrays.asList( - // Group 1: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - // Group 2: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2)); - - mManager.setSourceViewInfoList(listWithBothGroupsExpanded, GroupsInfo.newBuilder().build()); - verifyModelEquals(listWithBothGroupsExpanded); - - // Toggle group 1. - final List<DropdownItemViewInfo> listWithGroup1Collapsed = new ArrayList<>(); - listWithGroup1Collapsed.add(listWithBothGroupsExpanded.get(0)); - listWithGroup1Collapsed.addAll(listWithBothGroupsExpanded.subList(3, 6)); - mManager.setGroupCollapsedState(1, true); - verifyModelEquals(listWithGroup1Collapsed); - mManager.setGroupCollapsedState(1, false); - verifyModelEquals(listWithBothGroupsExpanded); - - // Toggle group 2. - final List<DropdownItemViewInfo> listWithGroup2Collapsed = - listWithBothGroupsExpanded.subList(0, 4); - mManager.setGroupCollapsedState(2, true); - verifyModelEquals(listWithGroup2Collapsed); - mManager.setGroupCollapsedState(2, false); - verifyModelEquals(listWithBothGroupsExpanded); - - // Toggle both groups. - final List<DropdownItemViewInfo> listWithBothGroupsCollapsed = - listWithGroup1Collapsed.subList(0, 2); - mManager.setGroupCollapsedState(2, true); - verifyModelEquals(listWithGroup2Collapsed); - mManager.setGroupCollapsedState(1, true); - verifyModelEquals(listWithBothGroupsCollapsed); - mManager.setGroupCollapsedState(2, false); - verifyModelEquals(listWithGroup1Collapsed); - mManager.setGroupCollapsedState(1, false); - verifyModelEquals(listWithBothGroupsExpanded); - } - - @Test - @SmallTest - public void groupHandling_defaultGroupExpandedState() { - final List<DropdownItemViewInfo> listWithBothGroupsExpanded = Arrays.asList( - // Group 1: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - // Group 2: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2)); - - // Receive suggestions list with group 1 default-collapsed. - mManager.setSourceViewInfoList(listWithBothGroupsExpanded, - GroupsInfo.newBuilder() - .putGroupConfigs(1, SECTION_1_COLLAPSED_NO_HEADER) - .putGroupConfigs(2, SECTION_2_EXPANDED_WITH_HEADER) - .build()); - - final List<DropdownItemViewInfo> listWithGroup1Collapsed = new ArrayList<>(); - listWithGroup1Collapsed.add(listWithBothGroupsExpanded.get(0)); - listWithGroup1Collapsed.addAll(listWithBothGroupsExpanded.subList(3, 6)); - verifyModelEquals(listWithGroup1Collapsed); - - // Expand suggestions for group 1. - mManager.setGroupCollapsedState(1, false); - verifyModelEquals(listWithBothGroupsExpanded); - - // Receive suggestions list with group 2 default-collapsed. - mManager.setSourceViewInfoList(listWithBothGroupsExpanded, - GroupsInfo.newBuilder() - .putGroupConfigs(1, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(2, SECTION_2_COLLAPSED_WITH_HEADER) - .build()); - final List<DropdownItemViewInfo> listWithGroup2Collapsed = - listWithBothGroupsExpanded.subList(0, 4); - verifyModelEquals(listWithGroup2Collapsed); - // Expand suggestions for group 2. - mManager.setGroupCollapsedState(2, false); - verifyModelEquals(listWithBothGroupsExpanded); - - // Receive suggestions list with both groups default-collapsed. - mManager.setSourceViewInfoList(listWithBothGroupsExpanded, - GroupsInfo.newBuilder() - .putGroupConfigs(1, SECTION_1_COLLAPSED_NO_HEADER) - .putGroupConfigs(2, SECTION_2_COLLAPSED_WITH_HEADER) - .build()); - final List<DropdownItemViewInfo> listWithBothGroupsCollapsed = - listWithGroup1Collapsed.subList(0, 2); - verifyModelEquals(listWithBothGroupsCollapsed); - mManager.setGroupCollapsedState(2, false); - verifyModelEquals(listWithGroup1Collapsed); - mManager.setGroupCollapsedState(1, false); - verifyModelEquals(listWithBothGroupsExpanded); - } - - @Test - @SmallTest - public void groupHandling_expandingAlreadyExpandedGroupAddsNoNewElementns() { - final List<DropdownItemViewInfo> list = Arrays.asList( - // Group 1: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - // Group 2: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2)); - - mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder().build()); - verifyModelEquals(list); - - // Expand group 1. - mManager.setGroupCollapsedState(1, false); - verifyModelEquals(list); - - // Expand group 2. - mManager.setGroupCollapsedState(2, false); - verifyModelEquals(list); - } - - @Test - @SmallTest - public void groupHandling_collapseAlreadyCollapsedListIsNoOp() { - final List<DropdownItemViewInfo> list = Arrays.asList( - // Group 1: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 1), - // Group 2: header + 2 suggestions - new DropdownItemViewInfo(mHeaderProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2), - new DropdownItemViewInfo(mBasicSuggestionProcessor, mModel, 2)); - - mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder().build()); - verifyModelEquals(list); - - // Collapse group 1. - final List<DropdownItemViewInfo> listWithGroup1Collapsed = new ArrayList<>(); - listWithGroup1Collapsed.add(list.get(0)); - listWithGroup1Collapsed.addAll(list.subList(3, 6)); - mManager.setGroupCollapsedState(1, true); - verifyModelEquals(listWithGroup1Collapsed); - mManager.setGroupCollapsedState(1, true); - verifyModelEquals(listWithGroup1Collapsed); - - // Collapse group 2. - final List<DropdownItemViewInfo> listWithBothGroupsCollapsed = - listWithGroup1Collapsed.subList(0, 2); - mManager.setGroupCollapsedState(2, true); - verifyModelEquals(listWithBothGroupsCollapsed); - mManager.setGroupCollapsedState(2, true); - verifyModelEquals(listWithBothGroupsCollapsed); - } - - @Test - @SmallTest public void updateSuggestionsList_suggestionsAreRebuiltOnSubsequentInteractions() { // This test validates scenario: // 1. user focuses omnibox @@ -416,8 +207,8 @@ mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list); @@ -483,8 +274,8 @@ // Receive suggestions list with group 1 default-collapsed. mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list); @@ -552,8 +343,8 @@ // Receive suggestions list with group 1 default-collapsed. mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list); @@ -619,8 +410,8 @@ // Receive suggestions list with group 1 default-collapsed. mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list); @@ -688,8 +479,8 @@ // Receive suggestions list with group 1 default-collapsed. mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list); @@ -757,8 +548,8 @@ // Receive suggestions list with group 1 default-collapsed. mManager.setSourceViewInfoList(list, GroupsInfo.newBuilder() - .putGroupConfigs(groupIdNoHeader, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(groupIdWithHeader, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(groupIdNoHeader, SECTION_1_NO_HEADER) + .putGroupConfigs(groupIdWithHeader, SECTION_2_WITH_HEADER) .build()); verifyModelEquals(list);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java index 30d509b..9e9c2ff 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java
@@ -62,14 +62,6 @@ void onSwitchToTab(@NonNull AutocompleteMatch suggestion, int position); /** - * Toggle expanded state of suggestion items belonging to specific group. - * - * @param groupId ID of Suggestion Group whose visibility changed. - * @param isCollapsed True if group should appear collapsed, otherwise false. - */ - void setGroupCollapsedState(int groupId, boolean isCollapsed); - - /** * Update the content of the Omnibox without triggering the Navigation. * * @param text The text to be displayed in the Omnibox.
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java index b44895fc..3103b00 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
@@ -67,41 +67,43 @@ private static final @DrawableRes int ICON_VOICE = R.drawable.btn_mic; private static final @DrawableRes int ICON_FAVICON = 0; // Favicons do not come from resources. - private static final Map<Integer, String> ICON_TYPE_NAMES = new HashMap<Integer, String>() { - { - put(ICON_BOOKMARK, "BOOKMARK"); - put(ICON_HISTORY, "HISTORY"); - put(ICON_GLOBE, "GLOBE"); - put(ICON_MAGNIFIER, "MAGNIFIER"); - put(ICON_VOICE, "VOICE"); - put(ICON_FAVICON, "FAVICON"); - } - }; + private static final Map<Integer, String> ICON_TYPE_NAMES; + static { + Map<Integer, String> map = new HashMap<>(); + map.put(ICON_BOOKMARK, "BOOKMARK"); + map.put(ICON_HISTORY, "HISTORY"); + map.put(ICON_GLOBE, "GLOBE"); + map.put(ICON_MAGNIFIER, "MAGNIFIER"); + map.put(ICON_VOICE, "VOICE"); + map.put(ICON_FAVICON, "FAVICON"); + ICON_TYPE_NAMES = map; + } - private static final Map<Integer, String> SUGGESTION_TYPE_NAMES = new HashMap<Integer, String>( - OmniboxSuggestionType.NUM_TYPES) { - { - put(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "URL_WHAT_YOU_TYPED"); - put(OmniboxSuggestionType.HISTORY_URL, "HISTORY_URL"); - put(OmniboxSuggestionType.HISTORY_TITLE, "HISTORY_TITLE"); - put(OmniboxSuggestionType.HISTORY_BODY, "HISTORY_BODY"); - put(OmniboxSuggestionType.HISTORY_KEYWORD, "HISTORY_KEYWORD"); - put(OmniboxSuggestionType.NAVSUGGEST, "NAVSUGGEST"); - put(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, "SEARCH_WHAT_YOU_TYPED"); - put(OmniboxSuggestionType.SEARCH_HISTORY, "SEARCH_HISTORY"); - put(OmniboxSuggestionType.SEARCH_SUGGEST, "SEARCH_SUGGEST"); - put(OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, "SEARCH_SUGGEST_ENTITY"); - put(OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, "SEARCH_SUGGEST_TAIL"); - put(OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, "SEARCH_SUGGEST_PERSONALIZED"); - put(OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, "SEARCH_SUGGEST_PROFILE"); - put(OmniboxSuggestionType.SEARCH_OTHER_ENGINE, "SEARCH_OTHER_ENGINE"); - put(OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, "NAVSUGGEST_PERSONALIZED"); - put(OmniboxSuggestionType.VOICE_SUGGEST, "VOICE_SUGGEST"); - put(OmniboxSuggestionType.DOCUMENT_SUGGESTION, "DOCUMENT_SUGGESTION"); - // Note: CALCULATOR suggestions are not handled by basic suggestion processor. - // These suggestions are now processed by AnswerSuggestionProcessor instead. - } - }; + private static final Map<Integer, String> SUGGESTION_TYPE_NAMES; + static { + Map<Integer, String> map = new HashMap<>(); + ; + map.put(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "URL_WHAT_YOU_TYPED"); + map.put(OmniboxSuggestionType.HISTORY_URL, "HISTORY_URL"); + map.put(OmniboxSuggestionType.HISTORY_TITLE, "HISTORY_TITLE"); + map.put(OmniboxSuggestionType.HISTORY_BODY, "HISTORY_BODY"); + map.put(OmniboxSuggestionType.HISTORY_KEYWORD, "HISTORY_KEYWORD"); + map.put(OmniboxSuggestionType.NAVSUGGEST, "NAVSUGGEST"); + map.put(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, "SEARCH_WHAT_YOU_TYPED"); + map.put(OmniboxSuggestionType.SEARCH_HISTORY, "SEARCH_HISTORY"); + map.put(OmniboxSuggestionType.SEARCH_SUGGEST, "SEARCH_SUGGEST"); + map.put(OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, "SEARCH_SUGGEST_ENTITY"); + map.put(OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, "SEARCH_SUGGEST_TAIL"); + map.put(OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, "SEARCH_SUGGEST_PERSONALIZED"); + map.put(OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, "SEARCH_SUGGEST_PROFILE"); + map.put(OmniboxSuggestionType.SEARCH_OTHER_ENGINE, "SEARCH_OTHER_ENGINE"); + map.put(OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, "NAVSUGGEST_PERSONALIZED"); + map.put(OmniboxSuggestionType.VOICE_SUGGEST, "VOICE_SUGGEST"); + map.put(OmniboxSuggestionType.DOCUMENT_SUGGESTION, "DOCUMENT_SUGGESTION"); + // Note: CALCULATOR suggestions are not handled by basic suggestion processor. + // These suggestions are now processed by AnswerSuggestionProcessor instead. + SUGGESTION_TYPE_NAMES = map; + } public @Rule TestRule mFeaturesProcessor = new Features.JUnitProcessor(); public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_landscape_view.xml b/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_landscape_view.xml index ab43d4db..c2776b5a 100644 --- a/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_landscape_view.xml +++ b/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_landscape_view.xml
@@ -57,16 +57,18 @@ app:leading="@dimen/text_size_medium_leading" /> <FrameLayout - android:id="@+id/fre_browser_managed_by_organization" + android:id="@+id/fre_browser_managed_by" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="16dp" > + android:layout_marginTop="16dp"> <include layout="@layout/fre_tos_privacy_disclaimer" + android:id="@+id/privacy_disclaimer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="start" /> + </FrameLayout> <ProgressBar
diff --git a/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_portrait_view.xml b/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_portrait_view.xml index 757734b..2944baa 100644 --- a/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_portrait_view.xml +++ b/chrome/browser/ui/android/signin/java/res/layout/signin_first_run_portrait_view.xml
@@ -67,13 +67,14 @@ app:leading="@dimen/text_size_medium_leading" /> <FrameLayout - android:id="@+id/fre_browser_managed_by_organization" + android:id="@+id/fre_browser_managed_by" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp"> <include layout="@layout/fre_tos_privacy_disclaimer" + android:id="@+id/privacy_disclaimer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunView.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunView.java index 49293bd..cce55fd 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunView.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunView.java
@@ -26,6 +26,7 @@ private TextView mTitle; private TextView mSubtitle; private View mBrowserManagedHeader; + private TextView mPrivacyDisclaimer; private ProgressBar mInitialLoadProgressSpinner; private ViewGroup mSelectedAccount; private ImageView mExpandIcon; @@ -45,7 +46,7 @@ mTitle = findViewById(R.id.title); mSubtitle = findViewById(R.id.subtitle); - mBrowserManagedHeader = findViewById(R.id.fre_browser_managed_by_organization); + mBrowserManagedHeader = findViewById(R.id.fre_browser_managed_by); mInitialLoadProgressSpinner = findViewById(R.id.fre_native_and_policy_load_progress_spinner); mSelectedAccount = findViewById(R.id.signin_fre_selected_account); @@ -55,6 +56,7 @@ mFooter = findViewById(R.id.signin_fre_footer); mSigninProgressSpinner = findViewById(R.id.fre_signin_progress_spinner); mSigninProgressText = findViewById(R.id.fre_signin_progress_text); + mPrivacyDisclaimer = (TextView) findViewById(R.id.privacy_disclaimer); if (FREMobileIdentityConsistencyFieldTrial.shouldHideTitleUntilPoliciesAreLoaded()) { mTitle.setVisibility(INVISIBLE); @@ -65,6 +67,10 @@ return mBrowserManagedHeader; } + TextView getPrivacyDisclaimer() { + return mPrivacyDisclaimer; + } + ProgressBar getInitialLoadProgressSpinnerView() { return mInitialLoadProgressSpinner; }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunViewBinder.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunViewBinder.java index c3b168b1..dd5be93f 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunViewBinder.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunViewBinder.java
@@ -43,6 +43,8 @@ final boolean isSelectedAccountSupervised = model.get(SigninFirstRunProperties.IS_SELECTED_ACCOUNT_SUPERVISED); view.getSelectedAccountView().setEnabled(!isSelectedAccountSupervised); + + updateBrowserManagedHeaderView(view, model); updateVisibility(view, model); } else if (propertyKey == SigninFirstRunProperties.SHOW_INITIAL_LOAD_PROGRESS_SPINNER) { final boolean showInitialLoadProgressSpinner = @@ -59,9 +61,7 @@ } updateVisibility(view, model); } else if (propertyKey == SigninFirstRunProperties.FRE_POLICY) { - view.getBrowserManagedHeaderView().setVisibility( - model.get(SigninFirstRunProperties.FRE_POLICY) != null ? View.VISIBLE - : View.GONE); + updateBrowserManagedHeaderView(view, model); } else if (propertyKey == SigninFirstRunProperties.IS_SIGNIN_SUPPORTED) { if (!model.get(SigninFirstRunProperties.IS_SIGNIN_SUPPORTED)) { view.getContinueButtonView().setText(R.string.continue_button); @@ -75,6 +75,33 @@ } } + private static void updateBrowserManagedHeaderView( + SigninFirstRunView view, PropertyModel model) { + // Supervised accounts do not have any enterprise policy set, but they set app + // restrictions which the policy load listener considers as policy. But if child + // accounts are loaded dynamically, policy load listener may say there are no + // policies on device. Because of the entangled nature of IS_SELECTED_ACCOUNT_SUPERVISED + // and FRE_POLICY they are both handled in this function as one of these properties + // will get updated before the other. + final boolean hasPolicy = model.get(SigninFirstRunProperties.FRE_POLICY) != null; + final boolean isAccountSupervised = + model.get(SigninFirstRunProperties.IS_SELECTED_ACCOUNT_SUPERVISED); + + if (isAccountSupervised) { + view.getBrowserManagedHeaderView().setVisibility(View.VISIBLE); + view.getPrivacyDisclaimer().setText(R.string.fre_browser_managed_by_parents); + view.getPrivacyDisclaimer().setCompoundDrawablesRelativeWithIntrinsicBounds( + R.drawable.ic_account_child_20dp, 0, 0, 0); + } else if (hasPolicy) { + view.getBrowserManagedHeaderView().setVisibility(View.VISIBLE); + view.getPrivacyDisclaimer().setText(R.string.fre_browser_managed_by_organization); + view.getPrivacyDisclaimer().setCompoundDrawablesRelativeWithIntrinsicBounds( + R.drawable.ic_business, 0, 0, 0); + } else { + view.getBrowserManagedHeaderView().setVisibility(View.GONE); + } + } + private static void updateSelectedAccount(SigninFirstRunView view, PropertyModel model) { if (!model.get(SigninFirstRunProperties.IS_SIGNIN_SUPPORTED)) { return;
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index f193408..df04512 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1078,10 +1078,10 @@ <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_DESCRIPTION_3" desc="A paragraph on the 'Enhanced ad privacy in Chrome' page that provides notice to Chrome users outside of the EEA. **** CONTEXT PRIVACY SANDBOX **** Chrome’s Privacy Sandbox initiative 1) deprecates third-party cookies in Chrome, 2) supports free and open content on the web (by finding better ways to support ads online), 3) while providing stronger privacy protections for users. You can see a high-level description of this public project at www.privacysanbox.com. **** CONTEXT ROW NOTICE **** 1) This screen provides notice to Chrome users outside of the European Economic Area (EEA) (we typically refer to this screen as “Rest of World” or “ROW”). It follows guidelines established by the GDPR. 2) We’re using similar but distinct content for EEA / ROW because legal requirements differ. For ROW, we can provide notice for all 3 settings, and so all 3 settings can appear on a single screen. " formatter_data="android_java"> To measure the performance of an ad, limited types of data can be shared among sites, such as the time of day an ad was shown to you. </message> - <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_LEARN_MORE_DESCRIPTION_ANDROID" desc=""> + <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_EEA_LEARN_MORE_DESCRIPTION_ANDROID" desc="As part of Privacy Sandbox (see details below), both Chrome and Android devices will have a new setting called 'Ad measurement'. Some details are different, but these settings essentially do the same thing. The Chrome setting allows sites you visit to ask Chrome for information that helps them measure the performance of their ads, linking 1) an ad for site B the user sees on site A, with 2) a purchase or other action the user might take on site B. On Android, it's essentially the same story only it's between apps and not sites. The challenge is that on Android, Chrome is a browser but it's also an App. This paragraph helps the user understand that, if both settings are on, information about the user's actions on a site might be connected with actions the user takes in an app. **** CONTEXT PRIVACY SANDBOX **** Chrome’s Privacy Sandbox initiative 1) deprecates third-party cookies in Chrome, 2) supports free and open content on the web (by finding better ways to support ads online), 3) while providing stronger privacy protections for users. You can see a high-level description of this public project at www.privacysanbox.com."> Your Android device may include a similar setting. If Ad measurement is turned on in Chrome and on your Android device, a company may be able to measure the effectiveness of an ad across web sites you visit and apps you use. </message> - <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_ANDROID" desc=""> + <message name="IDS_PRIVACY_SANDBOX_M1_NOTICE_ROW_LEARN_MORE_DESCRIPTION_ANDROID" desc="As part of Privacy Sandbox (see details below), both Chrome and Android devices will have a new setting called 'Ad measurement'. Some details are different, but these settings essentially do the same thing. The Chrome setting allows sites you visit to ask Chrome for information that helps them measure the performance of their ads, linking 1) an ad for site B the user sees on site A, with 2) a purchase or other action the user might take on site B. On Android, it's essentially the same story only it's between apps and not sites. The challenge is that on Android, Chrome is a browser but it's also an App. This paragraph helps the user understand that, if both settings are on, information about the user's actions on a site might be connected with actions the user takes in an app. **** CONTEXT PRIVACY SANDBOX **** Chrome’s Privacy Sandbox initiative 1) deprecates third-party cookies in Chrome, 2) supports free and open content on the web (by finding better ways to support ads online), 3) while providing stronger privacy protections for users. You can see a high-level description of this public project at www.privacysanbox.com."> Your Android device may include a similar setting. If Ad measurement is turned on in Chrome and on your Android device, a company may be able to measure the effectiveness of an ad across web sites you visit and apps you use. </message> @@ -2527,6 +2527,12 @@ <message name="IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS" desc="Context sensitive menu item for deep linking into google lens. [CHAR_LIMIT=30]"> Search image with Google Lens <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> </message> + <message name="IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_1" desc="ALT TXT 1: Context sensitive menu item for deep linking into google lens. [CHAR_LIMIT=30]"> + Search image with Google <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> + </message> + <message name="IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_2" desc="ALT TXT 2: Context sensitive menu item for deep linking into google lens. [CHAR_LIMIT=30]"> + Search inside image with Google <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> + </message> <message name="IDS_CONTEXTMENU_TRANSLATE_IMAGE_WITH_GOOGLE_LENS" desc="Context sensitive chip for deep linking into google lens for translate results. [CHAR_LIMIT=30]"> Translate image with Google Lens <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> </message> @@ -2976,6 +2982,9 @@ <message name="IDS_FRE_BROWSER_MANAGED_BY_ORGANIZATION" desc="Text that indicates the browser is managed by policy"> Your browser is managed by your organization </message> + <message name="IDS_FRE_BROWSER_MANAGED_BY_PARENTS" desc="Text that indicates the browser is managed by parents"> + Your browser is managed by your parents + </message> <!-- Signin First Run strings --> <message name="IDS_SIGNIN_FRE_DISMISS_BUTTON" desc="Button on the very first screen of Chrome to continue without signing into Chrome. Ensure consistency with OneGoogle strings while still omitting “Chrome” (see e.g. TC ID 5336438894576002929).">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_1.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_1.png.sha1 new file mode 100644 index 0000000..e510c95 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_1.png.sha1
@@ -0,0 +1 @@ +c17ad78e45a207fbe70108af64095cb3592c2880 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_2.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_2.png.sha1 new file mode 100644 index 0000000..27daacff --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_SEARCH_IMAGE_WITH_GOOGLE_LENS_ALT_TEXT_2.png.sha1
@@ -0,0 +1 @@ +a88a98b1f2c655195834a6bba1e74389ea8d9636 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FRE_BROWSER_MANAGED_BY_PARENTS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FRE_BROWSER_MANAGED_BY_PARENTS.png.sha1 new file mode 100644 index 0000000..591b00ed --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FRE_BROWSER_MANAGED_BY_PARENTS.png.sha1
@@ -0,0 +1 @@ +520b7df6553d4ab2b4cb2ab76fdc0b0e325543aa \ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java index 65b0c01a..3c0fd18 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarFeatures.java
@@ -17,6 +17,8 @@ private static final String ALLOW_CAPTURES = "allow_captures"; private static final MutableFlagWithSafeDefault sSuppressionFlag = new MutableFlagWithSafeDefault(ChromeFeatureList.SUPPRESS_TOOLBAR_CAPTURES, false); + private static final MutableFlagWithSafeDefault sRecordSuppressionMetrics = + new MutableFlagWithSafeDefault(ChromeFeatureList.RECORD_SUPPRESSION_METRICS, true); /** Private constructor to avoid instantiation. */ private ToolbarFeatures() {} @@ -41,4 +43,13 @@ public static boolean shouldSuppressCaptures() { return sSuppressionFlag.isEnabled(); } -} \ No newline at end of file + + /** + * Returns whether to record metrics from suppression experiment. This allows an arm of + * suppression to run without the overhead from reporting any extra metrics in Java. Using a + * feature instead of a param to utilize Java side caching. + */ + public static boolean shouldRecordSuppressionMetrics() { + return sRecordSuppressionMetrics.isEnabled(); + } +}
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java index 4196f53..96b93237 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/CaptureReadinessResult.java
@@ -8,6 +8,7 @@ import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.top.ToolbarSnapshotState.ToolbarSnapshotDifference; import java.lang.annotation.Retention; @@ -102,6 +103,10 @@ } public static void logCaptureReasonFromResult(CaptureReadinessResult result) { + if (!ToolbarFeatures.shouldRecordSuppressionMetrics()) { + return; + } + // The Java -> C++ layer makes passing enums tricky so we store the integer value and then // convert it to a proto enum on the C++ side. If we pass a -1 we will not set that // corresponding field.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java index 6d89d248..f79fe636 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java
@@ -17,6 +17,7 @@ import android.view.View; import android.view.ViewStub; +import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.appcompat.content.res.AppCompatResources; @@ -47,6 +48,8 @@ import org.chromium.ui.util.TokenHolder; import org.chromium.ui.widget.OptimizedFrameLayout; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.function.BooleanSupplier; /** @@ -230,6 +233,21 @@ @VisibleForTesting protected static class ToolbarViewResourceAdapter extends ViewResourceAdapter { + /** + * Emitted at various points during the in motion observer method. Note that it is not the + * toolbar that is in motion, but the toolbar's handling of the compositor being in motion. + * Treat this list as append only and keep it in sync with ToolbarInMotionStage in + * enums.xml. + **/ + @IntDef({ToolbarInMotionStage.SUPPRESSION_ENABLED, ToolbarInMotionStage.READINESS_CHECKED, + ToolbarInMotionStage.NUM_ENTRIES}) + @Retention(RetentionPolicy.SOURCE) + @interface ToolbarInMotionStage { + int SUPPRESSION_ENABLED = 0; + int READINESS_CHECKED = 1; + int NUM_ENTRIES = 2; + } + private final int[] mTempPosition = new int[2]; private final Rect mLocationBarRect = new Rect(); private final Rect mToolbarRect = new Rect(); @@ -413,6 +431,11 @@ return; } + if (ToolbarFeatures.shouldRecordSuppressionMetrics()) { + RecordHistogram.recordEnumeratedHistogram("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.SUPPRESSION_ENABLED, ToolbarInMotionStage.NUM_ENTRIES); + } + if (!Boolean.TRUE.equals(compositorInMotion)) { if (mControlsToken == TokenHolder.INVALID_TOKEN) { // Only needed when the ConstraintsChecker doesn't drive the capture. @@ -426,6 +449,12 @@ } } else if (super.isDirty() && mControlContainerIsVisibleSupplier.getAsBoolean()) { CaptureReadinessResult captureReadinessResult = mToolbar.isReadyForTextureCapture(); + if (ToolbarFeatures.shouldRecordSuppressionMetrics() + && compositorInMotion != null) { + RecordHistogram.recordEnumeratedHistogram("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.READINESS_CHECKED, + ToolbarInMotionStage.NUM_ENTRIES); + } if (captureReadinessResult.blockReason == TopToolbarBlockCaptureReason.SNAPSHOT_SAME) { setDirtyRectEmpty();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java index c58e2da..29b0b83d 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
@@ -30,10 +30,13 @@ import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.toolbar.ToolbarFeatures; import org.chromium.chrome.browser.toolbar.top.CaptureReadinessResult.TopToolbarAllowCaptureReason; import org.chromium.chrome.browser.toolbar.top.CaptureReadinessResult.TopToolbarBlockCaptureReason; import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer.ToolbarViewResourceAdapter; +import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer.ToolbarViewResourceAdapter.ToolbarInMotionStage; import org.chromium.chrome.browser.toolbar.top.ToolbarSnapshotState.ToolbarSnapshotDifference; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.chrome.test.util.browser.Features.JUnitProcessor; @@ -314,6 +317,13 @@ @Test public void testIsDirty_InMotion2() { ToolbarViewResourceAdapter adapter = makeAndInitAdapter(); + // Unfortunately this gets emitted once during initialization and we cannot easily reset. + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.SUPPRESSION_ENABLED)); + Assert.assertEquals(0, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.READINESS_CHECKED)); Mockito.when(mToolbar.isReadyForTextureCapture()) .thenReturn(CaptureReadinessResult.readyWithSnapshotDifference( @@ -326,6 +336,12 @@ "Android.TopToolbar.BlockCaptureReason", TopToolbarBlockCaptureReason.COMPOSITOR_IN_MOTION)); changeInMotion(/*inMotion*/ true, /*expectResourceRequested*/ false); + Assert.assertEquals(2, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.SUPPRESSION_ENABLED)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.READINESS_CHECKED)); Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "Android.TopToolbar.BlockCaptureReason", @@ -333,10 +349,40 @@ Assert.assertTrue(didAdapterLockControls()); changeInMotion(/*inMotion*/ false, /*expectResourceRequested*/ true); + Assert.assertEquals(3, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.SUPPRESSION_ENABLED)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting("Android.TopToolbar.InMotionStage", + ToolbarInMotionStage.READINESS_CHECKED)); Assert.assertFalse(didAdapterLockControls()); } @Test + @DisableFeatures(ChromeFeatureList.RECORD_SUPPRESSION_METRICS) + public void testIsDirty_InMotion2_NoMetrics() { + Assert.assertFalse(ToolbarFeatures.shouldRecordSuppressionMetrics()); + ToolbarViewResourceAdapter adapter = makeAndInitAdapter(); + + Mockito.when(mToolbar.isReadyForTextureCapture()) + .thenReturn(CaptureReadinessResult.readyWithSnapshotDifference( + ToolbarSnapshotDifference.URL_TEXT)); + Mockito.when(mTab.isNativePage()).thenReturn(false); + mIsVisible = true; + + changeInMotion(/*inMotion*/ true, /*expectResourceRequested*/ false); + Assert.assertTrue(didAdapterLockControls()); + changeInMotion(/*inMotion*/ false, /*expectResourceRequested*/ true); + Assert.assertFalse(didAdapterLockControls()); + + Assert.assertEquals( + 0, RecordHistogram.getHistogramTotalCountForTesting("Android.TopToolbar.InMotion")); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + "Android.TopToolbar.InMotionStage")); + } + + @Test public void testIsDirty_ConstraintsIgnoredOnNativePage() { ToolbarViewResourceAdapter adapter = new ToolbarViewResourceAdapter(mToolbarContainer, false);
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc index 758af44..4a3559c4cc3 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -487,9 +487,17 @@ } void ChromeNewWindowClient::ShowKeyboardShortcutViewer() { + if (ash::features::ShouldOnlyShowNewShortcutApp()) { + ShowShortcutCustomizationApp(); + return; + } ash::ToggleKeyboardShortcutViewer(); } +void ChromeNewWindowClient::ShowShortcutCustomizationApp() { + chrome::ShowShortcutCustomizationApp(ProfileManager::GetActiveUserProfile()); +} + void ChromeNewWindowClient::ShowTaskManager() { chrome::OpenTaskManager(nullptr); }
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.h b/chrome/browser/ui/ash/chrome_new_window_client.h index c0f6e70..125ab25 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.h +++ b/chrome/browser/ui/ash/chrome_new_window_client.h
@@ -43,6 +43,7 @@ void OpenGetHelp() override; void RestoreTab() override; void ShowKeyboardShortcutViewer() override; + void ShowShortcutCustomizationApp() override; void ShowTaskManager() override; void OpenDiagnostics() override; void OpenFeedbackPage(FeedbackSource source,
diff --git a/chrome/browser/ui/ash/crosapi_new_window_delegate.cc b/chrome/browser/ui/ash/crosapi_new_window_delegate.cc index f7bf927..66b1c49 100644 --- a/chrome/browser/ui/ash/crosapi_new_window_delegate.cc +++ b/chrome/browser/ui/ash/crosapi_new_window_delegate.cc
@@ -187,6 +187,10 @@ delegate_->ShowKeyboardShortcutViewer(); } +void CrosapiNewWindowDelegate::ShowShortcutCustomizationApp() { + delegate_->ShowShortcutCustomizationApp(); +} + void CrosapiNewWindowDelegate::ShowTaskManager() { delegate_->ShowTaskManager(); }
diff --git a/chrome/browser/ui/ash/crosapi_new_window_delegate.h b/chrome/browser/ui/ash/crosapi_new_window_delegate.h index 6ce96d3..9ee158d 100644 --- a/chrome/browser/ui/ash/crosapi_new_window_delegate.h +++ b/chrome/browser/ui/ash/crosapi_new_window_delegate.h
@@ -42,6 +42,7 @@ void OpenGetHelp() override; void RestoreTab() override; void ShowKeyboardShortcutViewer() override; + void ShowShortcutCustomizationApp() override; void ShowTaskManager() override; void OpenDiagnostics() override; void OpenFeedbackPage(FeedbackSource source,
diff --git a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc index 422abc9..822e8b4c 100644 --- a/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc +++ b/chrome/browser/ui/ash/desks/chrome_saved_desk_delegate.cc
@@ -318,7 +318,6 @@ } if (app_id == app_constants::kLacrosAppId) { - // TODO(avynn): Add lacros support for tab groups. const std::string* lacros_window_id = window->GetProperty(app_restore::kLacrosWindowId); DCHECK(lacros_window_id); @@ -460,8 +459,10 @@ return; } + app_launch_info->tab_group_infos = state->groups; app_launch_info->urls = state->urls; app_launch_info->active_tab_index = state->active_index; + app_launch_info->first_non_pinned_tab_index = state->first_non_pinned_index; std::move(callback).Run(std::move(app_launch_info)); }
diff --git a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc index 6e67352a..2947a542 100644 --- a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc +++ b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
@@ -31,6 +31,7 @@ #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_test_util.h" #include "ash/wm/window_state.h" +#include "ash/wm/window_util.h" #include "base/containers/contains.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" @@ -1107,13 +1108,11 @@ EXPECT_EQ(1, desks_controller->GetActiveDeskIndex()); // Get the floated window from newly created desk. - auto* float_controller = ash::Shell::Get()->float_controller(); - auto* floated_window = float_controller->FindFloatedWindowOfDesk( - desks_controller->active_desk()); - DCHECK(floated_window); - DCHECK(ash::WindowState::Get(floated_window)->IsFloated()); + auto* floated_window = ash::window_util::GetFloatedWindowForActiveDesk(); + ASSERT_TRUE(floated_window); + ASSERT_TRUE(ash::WindowState::Get(floated_window)->IsFloated()); // Restored floated window to the saved bounds instead of default bounds. - DCHECK_EQ(floated_window->bounds(), browser_bounds); + EXPECT_EQ(floated_window->bounds(), browser_bounds); } // Tests that launching a template that contains a browser window with tab
diff --git a/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc b/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc index 7b4e72a..3dca200 100644 --- a/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc +++ b/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc
@@ -33,6 +33,7 @@ #include "components/app_restore/restore_data.h" #include "components/app_restore/window_info.h" #include "components/services/app_service/public/cpp/app_types.h" +#include "components/tab_groups/tab_group_info.h" #include "extensions/common/extension.h" namespace { @@ -300,17 +301,21 @@ for (const auto& [restore_window_id, app_restore_data] : iter.second) { if (!app_restore_data->active_tab_index.has_value() || !app_restore_data->urls.has_value()) { - LOG(WARNING) << "Corrupted data for the Lacros window found"; continue; } crosapi::BrowserManager::Get()->CreateBrowserWithRestoredData( app_restore_data->urls.value(), app_restore_data->current_bounds.value_or(gfx::Rect()), + app_restore_data->tab_group_infos.value_or( + std::vector<tab_groups::TabGroupInfo>()), chromeos::ToWindowShowState( app_restore_data->window_state_type.value_or( chromeos::WindowStateType::kDefault)), app_restore_data->active_tab_index.value(), + // Values of 0 will be ignored, other type constraints are + // enforced on the browser side. + app_restore_data->first_non_pinned_tab_index.value_or(0), GetBrowserAppName(app_restore_data, app_id), restore_window_id); } }
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc index 07484280..34acce1 100644 --- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc +++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -30,14 +30,14 @@ #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Internal builds add an extra accelerator for the Feedback app. // The total number of Chrome accelerators (available on Chrome OS). -constexpr int kChromeAcceleratorsTotalNum = 102; +constexpr int kChromeAcceleratorsTotalNum = 103; // The hash of Chrome accelerators (available on Chrome OS). -constexpr char kChromeAcceleratorsHash[] = "672b2d00632c66337b6323da9c75e3a2"; +constexpr char kChromeAcceleratorsHash[] = "e9e2edcc3a1a7332c960f7b3a00ee8cc"; #else // The total number of Chrome accelerators (available on Chrome OS). -constexpr int kChromeAcceleratorsTotalNum = 101; +constexpr int kChromeAcceleratorsTotalNum = 102; // The hash of Chrome accelerators (available on Chrome OS). -constexpr char kChromeAcceleratorsHash[] = "7143dc8ef5efe3fc6047e864f589386f"; +constexpr char kChromeAcceleratorsHash[] = "253127d58865152a7e549bf2caa24027"; #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) const char* BooleanToString(bool value) {
diff --git a/chrome/browser/ui/autofill/autofill_bubble_handler.h b/chrome/browser/ui/autofill/autofill_bubble_handler.h index ce4cac09..1a618bf1 100644 --- a/chrome/browser/ui/autofill/autofill_bubble_handler.h +++ b/chrome/browser/ui/autofill/autofill_bubble_handler.h
@@ -16,6 +16,7 @@ class SaveUpdateAddressProfileBubbleController; class EditAddressProfileDialogController; class SaveCardBubbleController; +class SaveIbanBubbleController; class SaveUPIBubble; class SaveUPIBubbleController; class VirtualCardManualFallbackBubbleController; @@ -46,6 +47,11 @@ LocalCardMigrationBubbleController* controller, bool is_user_gesture) = 0; + virtual AutofillBubbleBase* ShowSaveIbanBubble( + content::WebContents* web_contents, + SaveIbanBubbleController* controller, + bool is_user_gesture) = 0; + virtual AutofillBubbleBase* ShowOfferNotificationBubble( content::WebContents* web_contents, OfferNotificationBubbleController* controller,
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 1bd597f4..dfd708a3 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -40,6 +40,7 @@ #include "chrome/browser/ui/autofill/payments/card_unmask_otp_input_dialog_controller_impl.h" #include "chrome/browser/ui/autofill/payments/create_card_unmask_prompt_view.h" #include "chrome/browser/ui/autofill/payments/credit_card_scanner_controller.h" +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h" #include "chrome/browser/ui/autofill/payments/virtual_card_enroll_bubble_controller_impl.h" #include "chrome/browser/ui/autofill/risk_util.h" #include "chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.h" @@ -92,7 +93,6 @@ #include "content/public/browser/ssl_status.h" #include "content/public/browser/storage_partition.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/geometry/rect.h" #include "url/origin.h" @@ -227,10 +227,23 @@ } FormDataImporter* ChromeAutofillClient::GetFormDataImporter() { + if (!form_data_importer_) { + form_data_importer_ = std::make_unique<FormDataImporter>( + this, GetPaymentsClient(), GetPersonalDataManager(), + GetPersonalDataManager()->app_locale()); + } return form_data_importer_.get(); } payments::PaymentsClient* ChromeAutofillClient::GetPaymentsClient() { + if (!payments_client_) { + payments_client_ = std::make_unique<payments::PaymentsClient>( + Profile::FromBrowserContext(web_contents()->GetBrowserContext()) + ->GetURLLoaderFactory(), + GetIdentityManager(), GetPersonalDataManager(), + Profile::FromBrowserContext(web_contents()->GetBrowserContext()) + ->IsOffTheRecord()); + } return payments_client_.get(); } @@ -524,9 +537,10 @@ const IBAN& iban, bool should_show_prompt, LocalSaveIBANPromptCallback callback) { - NOTIMPLEMENTED(); - // TODO(crbug.com/1349109): Implement SaveIBANBubbleController to show - // prompt bubble for local save. + // Do lazy initialization of SaveIbanBubbleControllerImpl. + SaveIbanBubbleControllerImpl::CreateForWebContents(web_contents()); + SaveIbanBubbleControllerImpl::FromWebContents(web_contents()) + ->OfferLocalSave(iban, should_show_prompt, std::move(callback)); } void ChromeAutofillClient::ShowWebauthnOfferDialog( @@ -612,11 +626,8 @@ DCHECK(options.show_prompt); infobars::ContentInfoBarManager::FromWebContents(web_contents()) ->AddInfoBar(CreateSaveCardInfoBarMobile( - std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/false, options, card, LegalMessageLines(), - AutofillClient::UploadSaveCardPromptCallback(), - /*local_save_card_callback=*/std::move(callback), - AccountInfo()))); + AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( + options, card, std::move(callback)))); #else // Do lazy initialization of SaveCardBubbleControllerImpl. SaveCardBubbleControllerImpl::CreateForWebContents(web_contents()); @@ -640,10 +651,9 @@ identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)); infobars::ContentInfoBarManager::FromWebContents(web_contents()) ->AddInfoBar(CreateSaveCardInfoBarMobile( - std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/true, options, card, legal_message_lines, - /*upload_save_card_callback=*/std::move(callback), - AutofillClient::LocalSaveCardPromptCallback(), account_info))); + AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( + options, card, std::move(callback), legal_message_lines, + account_info))); #else // Do lazy initialization of SaveCardBubbleControllerImpl. SaveCardBubbleControllerImpl::CreateForWebContents(web_contents()); @@ -1086,6 +1096,10 @@ } #if !BUILDFLAG(IS_ANDROID) +void ChromeAutofillClient::OnZoomControllerDestroyed() { + zoom_observation_.Reset(); +} + void ChromeAutofillClient::OnZoomChanged( const zoom::ZoomController::ZoomChangedEventData& data) { HideAutofillPopup(PopupHidingReason::kContentAreaMoved); @@ -1096,18 +1110,6 @@ ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents) : content::WebContentsUserData<ChromeAutofillClient>(*web_contents), content::WebContentsObserver(web_contents), - payments_client_(std::make_unique<payments::PaymentsClient>( - Profile::FromBrowserContext(web_contents->GetBrowserContext()) - ->GetURLLoaderFactory(), - GetIdentityManager(), - GetPersonalDataManager(), - Profile::FromBrowserContext(web_contents->GetBrowserContext()) - ->IsOffTheRecord())), - form_data_importer_(std::make_unique<FormDataImporter>( - this, - payments_client_.get(), - GetPersonalDataManager(), - GetPersonalDataManager()->app_locale())), log_manager_( // TODO(crbug.com/928595): Replace the closure with a callback to the // renderer that indicates if log messages should be sent from the @@ -1126,16 +1128,11 @@ GetStrikeDatabase(); #if !BUILDFLAG(IS_ANDROID) - // Since ZoomController is also a WebContentsObserver, we need to be careful - // about disconnecting from it since the relative order of destruction of - // WebContentsObservers is not guaranteed. ZoomController silently clears - // its ZoomObserver list during WebContentsDestroyed() so there's no need - // to explicitly remove ourselves on destruction. - zoom::ZoomController* zoom_controller = - zoom::ZoomController::FromWebContents(web_contents); // There may not always be a ZoomController, e.g. in tests. - if (zoom_controller) - zoom_controller->AddObserver(this); + if (auto* zoom_controller = + zoom::ZoomController::FromWebContents(web_contents)) { + zoom_observation_.Observe(zoom_controller); + } #endif }
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index b24f3ef..9d29096 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -12,6 +12,7 @@ #include "base/functional/callback.h" #include "base/i18n/rtl.h" #include "base/memory/weak_ptr.h" +#include "base/scoped_observation.h" #include "build/build_config.h" #include "chrome/browser/autofill/autofill_gstatic_reader.h" #include "chrome/browser/profiles/profile.h" @@ -253,10 +254,11 @@ } #if !BUILDFLAG(IS_ANDROID) - // ZoomObserver implementation. + // ZoomObserver: + void OnZoomControllerDestroyed() override; void OnZoomChanged( const zoom::ZoomController::ZoomChangedEventData& data) override; -#endif // !BUILDFLAG(IS_ANDROID) +#endif private: friend class content::WebContentsUserData<ChromeAutofillClient>; @@ -269,10 +271,13 @@ std::u16string GetAccountHolderEmail(); bool SupportsConsentlessExecution(const url::Origin& origin); + // These members are initialized lazily in their respective getters. + // Therefore, do not access the members directly. std::unique_ptr<payments::PaymentsClient> payments_client_; std::unique_ptr<CreditCardCVCAuthenticator> cvc_authenticator_; std::unique_ptr<CreditCardOtpAuthenticator> otp_authenticator_; std::unique_ptr<FormDataImporter> form_data_importer_; + base::WeakPtr<AutofillPopupControllerImpl> popup_controller_; std::unique_ptr<LogManager> log_manager_; FormInteractionsFlowId flow_id_{}; @@ -292,6 +297,11 @@ std::unique_ptr<AutofillProgressDialogControllerImpl> autofill_progress_dialog_controller_; +#if !BUILDFLAG(IS_ANDROID) + base::ScopedObservation<zoom::ZoomController, zoom::ZoomObserver> + zoom_observation_{this}; +#endif + // True if and only if the associated web_contents() is currently focused. bool has_focus_ = false;
diff --git a/chrome/browser/ui/autofill/payments/save_iban_bubble_controller.h b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller.h new file mode 100644 index 0000000..524d778b --- /dev/null +++ b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller.h
@@ -0,0 +1,54 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_H_ +#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_H_ + +#include <string> + +#include "components/autofill/core/browser/autofill_client.h" +#include "components/autofill/core/browser/ui/payments/payments_bubble_closed_reasons.h" +#include "content/public/browser/web_contents.h" + +namespace autofill { + +class AutofillBubbleBase; +class IBAN; +enum class IBANBubbleType; + +// Interface that exposes controller functionality to save IBAN bubbles. +class SaveIbanBubbleController { + public: + SaveIbanBubbleController() = default; + SaveIbanBubbleController(const SaveIbanBubbleController&) = delete; + SaveIbanBubbleController& operator=(const SaveIbanBubbleController&) = delete; + virtual ~SaveIbanBubbleController() = default; + + // Returns a reference to the SaveIbanBubbleController associated with the + // given `web_contents`. If controller does not exist, this will create the + // controller from the `web_contents` then return the reference. + static SaveIbanBubbleController* GetOrCreate( + content::WebContents* web_contents); + + // Returns the title that should be displayed in the bubble. + virtual std::u16string GetWindowTitle() const = 0; + + // Returns the button label text for IBAN save bubbles. + virtual std::u16string GetAcceptButtonText() const = 0; + virtual std::u16string GetDeclineButtonText() const = 0; + + // Returns the IBAN that will be saved if the user accepts. + virtual const IBAN& GetIBAN() const = 0; + + virtual AutofillBubbleBase* GetSaveBubbleView() const = 0; + + // Interaction. + virtual void OnSaveButton(const std::u16string& nickname) = 0; + virtual void OnCancelButton() = 0; + virtual void OnBubbleClosed(PaymentsBubbleClosedReason closed_reason) = 0; +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.cc new file mode 100644 index 0000000..81ce6b01 --- /dev/null +++ b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.cc
@@ -0,0 +1,161 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h" + +#include <string> + +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/autofill/autofill_bubble_base.h" +#include "chrome/browser/ui/autofill/autofill_bubble_handler.h" +#include "chrome/browser/ui/autofill/payments/save_iban_ui.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/page_action/page_action_icon_type.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill { + +// static +SaveIbanBubbleController* SaveIbanBubbleController::GetOrCreate( + content::WebContents* web_contents) { + if (!web_contents) { + return nullptr; + } + + SaveIbanBubbleControllerImpl::CreateForWebContents(web_contents); + return SaveIbanBubbleControllerImpl::FromWebContents(web_contents); +} + +SaveIbanBubbleControllerImpl::~SaveIbanBubbleControllerImpl() = default; + +void SaveIbanBubbleControllerImpl::OfferLocalSave( + const IBAN& iban, + bool should_show_prompt, + AutofillClient::LocalSaveIBANPromptCallback save_iban_prompt_callback) { + // Don't show the bubble if it's already visible. + if (bubble_view()) { + return; + } + + iban_ = iban; + local_save_iban_prompt_callback_ = std::move(save_iban_prompt_callback); + current_bubble_type_ = IbanBubbleType::kLocalSave; + + if (should_show_prompt) { + ShowBubble(); + } + // TODO(crbug.com/1349109): Add else block for show Icon only. +} + +std::u16string SaveIbanBubbleControllerImpl::GetWindowTitle() const { + switch (current_bubble_type_) { + case IbanBubbleType::kLocalSave: + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_IBAN_PROMPT_TITLE_LOCAL); + case IbanBubbleType::kInactive: + NOTREACHED(); + return std::u16string(); + } +} + +std::u16string SaveIbanBubbleControllerImpl::GetAcceptButtonText() const { + switch (current_bubble_type_) { + case IbanBubbleType::kLocalSave: + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_ACCEPT); + case IbanBubbleType::kInactive: + return std::u16string(); + } +} + +std::u16string SaveIbanBubbleControllerImpl::GetDeclineButtonText() const { + switch (current_bubble_type_) { + case IbanBubbleType::kLocalSave: + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS); + case IbanBubbleType::kInactive: + return std::u16string(); + } +} + +const IBAN& SaveIbanBubbleControllerImpl::GetIBAN() const { + return iban_; +} + +AutofillBubbleBase* SaveIbanBubbleControllerImpl::GetSaveBubbleView() const { + return bubble_view(); +} + +void SaveIbanBubbleControllerImpl::OnSaveButton( + const std::u16string& nickname) { + switch (current_bubble_type_) { + case IbanBubbleType::kLocalSave: + DCHECK(!local_save_iban_prompt_callback_.is_null()); + std::move(local_save_iban_prompt_callback_) + .Run(AutofillClient::SaveIBANOfferUserDecision::kAccepted, nickname); + break; + case IbanBubbleType::kInactive: + NOTREACHED(); + } +} + +void SaveIbanBubbleControllerImpl::OnCancelButton() { + if (current_bubble_type_ == IbanBubbleType::kLocalSave) { + std::move(local_save_iban_prompt_callback_) + .Run(AutofillClient::SaveIBANOfferUserDecision::kDeclined, + absl::nullopt); + } +} + +void SaveIbanBubbleControllerImpl::OnBubbleClosed( + PaymentsBubbleClosedReason closed_reason) { + set_bubble_view(nullptr); + + current_bubble_type_ = IbanBubbleType::kInactive; + + UpdatePageActionIcon(); +} + +SaveIbanBubbleControllerImpl::SaveIbanBubbleControllerImpl( + content::WebContents* web_contents) + : AutofillBubbleControllerBase(web_contents), + content::WebContentsUserData<SaveIbanBubbleControllerImpl>(*web_contents), + personal_data_manager_( + PersonalDataManagerFactory::GetInstance()->GetForProfile( + Profile::FromBrowserContext(web_contents->GetBrowserContext()))) { +} + +PageActionIconType SaveIbanBubbleControllerImpl::GetPageActionIconType() { + return PageActionIconType::kSaveIban; +} + +void SaveIbanBubbleControllerImpl::DoShowBubble() { + Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); + set_bubble_view( + browser->window()->GetAutofillBubbleHandler()->ShowSaveIbanBubble( + web_contents(), this, /*is_user_gesture=*/false)); + DCHECK(bubble_view()); + + if (observer_for_testing_) { + observer_for_testing_->OnBubbleShown(); + } +} + +void SaveIbanBubbleControllerImpl::ShowBubble() { + DCHECK(current_bubble_type_ != IbanBubbleType::kInactive); + // Local save callback should not be null for kLocalSave state. + DCHECK(!(local_save_iban_prompt_callback_.is_null() && + current_bubble_type_ == IbanBubbleType::kLocalSave)); + DCHECK(!bubble_view()); + Show(); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(SaveIbanBubbleControllerImpl); + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h new file mode 100644 index 0000000..09a2776 --- /dev/null +++ b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h
@@ -0,0 +1,99 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_IMPL_H_ + +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/autofill/autofill_bubble_controller_base.h" +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller.h" +#include "chrome/browser/ui/autofill/payments/save_iban_ui.h" +#include "components/autofill/core/browser/autofill_client.h" +#include "components/autofill/core/browser/data_model/iban.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace autofill { + +enum class IbanBubbleType; + +// Implementation of per-tab class to control the IBAN save bubble and +// Omnibox icon. +class SaveIbanBubbleControllerImpl + : public AutofillBubbleControllerBase, + public SaveIbanBubbleController, + public content::WebContentsUserData<SaveIbanBubbleControllerImpl> { + public: + // An observer class used by browsertests that gets notified whenever + // particular actions occur. + class ObserverForTest { + public: + virtual void OnBubbleShown() = 0; + }; + + SaveIbanBubbleControllerImpl(const SaveIbanBubbleControllerImpl&) = delete; + SaveIbanBubbleControllerImpl& operator=(const SaveIbanBubbleControllerImpl&) = + delete; + ~SaveIbanBubbleControllerImpl() override; + + // Sets up the controller and offers to save the `iban` locally. + // `save_iban_prompt_callback` will be invoked once the user makes a decision + // with respect to the offer-to-save prompt. + void OfferLocalSave( + const IBAN& iban, + bool should_show_prompt, + AutofillClient::LocalSaveIBANPromptCallback save_iban_prompt_callback); + + // SaveIbanBubbleController: + std::u16string GetWindowTitle() const override; + std::u16string GetAcceptButtonText() const override; + std::u16string GetDeclineButtonText() const override; + const IBAN& GetIBAN() const override; + AutofillBubbleBase* GetSaveBubbleView() const override; + void OnSaveButton(const std::u16string& nickname) override; + void OnCancelButton() override; + void OnBubbleClosed(PaymentsBubbleClosedReason closed_reason) override; + + // For testing. + void SetEventObserverForTesting(ObserverForTest* observer) { + observer_for_testing_ = observer; + } + + protected: + explicit SaveIbanBubbleControllerImpl(content::WebContents* web_contents); + + // AutofillBubbleControllerBase: + PageActionIconType GetPageActionIconType() override; + void DoShowBubble() override; + + private: + friend class content::WebContentsUserData<SaveIbanBubbleControllerImpl>; + + // Displays both the offer-to-save bubble and its associated omnibox icon. + void ShowBubble(); + + // Should outlive this object. + raw_ptr<PersonalDataManager> personal_data_manager_; + + // Observer for when a bubble is created. Initialized only during tests. + raw_ptr<ObserverForTest> observer_for_testing_ = nullptr; + + // Note: Below fields are set when IBAN save is offered. + // + // The type of bubble that is either currently being shown or would + // be shown when the IBAN save icon is clicked. + IbanBubbleType current_bubble_type_ = IbanBubbleType::kInactive; + + // Callback to run once the user makes a decision with respect to the local + // IBAN offer-to-save prompt. + AutofillClient::LocalSaveIBANPromptCallback local_save_iban_prompt_callback_; + + // Contains the details of the IBAN that will be saved if the user accepts. + IBAN iban_; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl_unittest.cc new file mode 100644 index 0000000..2e7748b --- /dev/null +++ b/chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl_unittest.cc
@@ -0,0 +1,85 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h" + +#include "chrome/browser/ui/autofill/autofill_bubble_base.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/data_model/iban.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +class TestSaveIbanBubbleControllerImpl : public SaveIbanBubbleControllerImpl { + public: + static void CreateForTesting(content::WebContents* web_contents) { + web_contents->SetUserData( + UserDataKey(), + std::make_unique<TestSaveIbanBubbleControllerImpl>(web_contents)); + } + + explicit TestSaveIbanBubbleControllerImpl(content::WebContents* web_contents) + : SaveIbanBubbleControllerImpl(web_contents) {} +}; + +class SaveIbanBubbleControllerImplTest : public BrowserWithTestWindowTest { + public: + SaveIbanBubbleControllerImplTest() = default; + SaveIbanBubbleControllerImplTest(SaveIbanBubbleControllerImplTest&) = delete; + SaveIbanBubbleControllerImplTest& operator=( + SaveIbanBubbleControllerImplTest&) = delete; + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + AddTab(browser(), GURL("about:blank")); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + TestSaveIbanBubbleControllerImpl::CreateForTesting(web_contents); + } + + void ShowLocalBubble(const IBAN& iban) { + controller()->OfferLocalSave( + iban, /*should_show_prompt=*/true, + base::BindOnce(&SaveIbanBubbleControllerImplTest::LocalSaveIBANCallback, + weak_ptr_factory_.GetWeakPtr())); + } + + void ClickSaveButton(const std::u16string& nickname) { + controller()->OnSaveButton(nickname); + controller()->OnBubbleClosed(PaymentsBubbleClosedReason::kAccepted); + } + + std::u16string saved_nickname() { return saved_nickname_; } + + protected: + TestSaveIbanBubbleControllerImpl* controller() { + return static_cast<TestSaveIbanBubbleControllerImpl*>( + TestSaveIbanBubbleControllerImpl::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents())); + } + + private: + void LocalSaveIBANCallback( + AutofillClient::SaveIBANOfferUserDecision user_decision, + const absl::optional<std::u16string>& nickname) { + saved_nickname_ = nickname.value_or(u""); + } + + std::u16string saved_nickname_; + base::WeakPtrFactory<SaveIbanBubbleControllerImplTest> weak_ptr_factory_{ + this}; +}; + +TEST_F(SaveIbanBubbleControllerImplTest, LocalIbanSavedSuccessfully) { + std::u16string nickname = u"My doctor's IBAN"; + IBAN iban = autofill::test::GetIBAN(); + ShowLocalBubble(iban); + ClickSaveButton(nickname); + + EXPECT_EQ(nickname, saved_nickname()); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/save_iban_ui.h b/chrome/browser/ui/autofill/payments/save_iban_ui.h new file mode 100644 index 0000000..d7f8a35 --- /dev/null +++ b/chrome/browser/ui/autofill/payments/save_iban_ui.h
@@ -0,0 +1,22 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_UI_H_ +#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_UI_H_ + +namespace autofill { + +// The type of save IBAN bubble to show. +enum class IbanBubbleType { + // Save prompt when the user is saving locally. + kLocalSave = 0, + + // There is no bubble to show anymore. This also indicates that the icon + // should not be visible. + kInactive = 1 +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_SAVE_IBAN_UI_H_
diff --git a/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.cc b/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.cc index f070447..119c231a 100644 --- a/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.cc +++ b/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.cc
@@ -18,6 +18,16 @@ return save_card_bubble_view_.get(); } +AutofillBubbleBase* TestAutofillBubbleHandler::ShowSaveIbanBubble( + content::WebContents* web_contents, + SaveIbanBubbleController* controller, + bool is_user_gesture) { + if (!save_iban_bubble_view_) { + save_iban_bubble_view_ = std::make_unique<TestAutofillBubble>(); + } + return save_iban_bubble_view_.get(); +} + AutofillBubbleBase* TestAutofillBubbleHandler::ShowLocalCardMigrationBubble( content::WebContents* web_contents, LocalCardMigrationBubbleController* controller,
diff --git a/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.h b/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.h index 1d9bb9b..0d77384 100644 --- a/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.h +++ b/chrome/browser/ui/autofill/test/test_autofill_bubble_handler.h
@@ -36,6 +36,9 @@ content::WebContents* web_contents, SaveCardBubbleController* controller, bool is_user_gesture) override; + AutofillBubbleBase* ShowSaveIbanBubble(content::WebContents* web_contents, + SaveIbanBubbleController* controller, + bool is_user_gesture) override; AutofillBubbleBase* ShowLocalCardMigrationBubble( content::WebContents* web_contents, LocalCardMigrationBubbleController* controller, @@ -72,6 +75,7 @@ std::unique_ptr<TestAutofillBubble> local_card_migration_bubble_view_; std::unique_ptr<TestAutofillBubble> offer_notification_bubble_view_; std::unique_ptr<TestAutofillBubble> save_card_bubble_view_; + std::unique_ptr<TestAutofillBubble> save_iban_bubble_view_; std::unique_ptr<TestSaveUPIBubble> save_upi_bubble_; std::unique_ptr<TestAutofillBubble> save_address_profile_bubble_view_; std::unique_ptr<TestAutofillBubble> update_address_profile_bubble_view_;
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index a60da3b..100baef 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -82,6 +82,10 @@ #include "ui/accessibility/accessibility_features.h" #endif +#if BUILDFLAG(IS_CHROMEOS) +#include "chromeos/ui/wm/features.h" +#endif + #if BUILDFLAG(IS_MAC) #include "chrome/browser/ui/browser_commands_mac.h" #endif @@ -385,8 +389,9 @@ // CommandUpdaterDelegate and CommandUpdater declare this function so we // choose to not implement CommandUpdaterDelegate inside this class and // therefore command_updater_ doesn't have the delegate set). - if (!SupportsCommand(id) || !IsCommandEnabled(id)) + if (!SupportsCommand(id) || !IsCommandEnabled(id)) { return false; + } // No commands are enabled if there is not yet any selected tab. // TODO(pkasting): It seems like we should not need this, because either @@ -524,6 +529,12 @@ PromptToNameWindow(browser_); break; +#if BUILDFLAG(IS_CHROMEOS) + case IDC_TOGGLE_MULTITASK_MENU: + ToggleMultitaskMenu(browser_); + break; +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) case IDC_VISIT_DESKTOP_OF_LRU_USER_2: case IDC_VISIT_DESKTOP_OF_LRU_USER_3: @@ -1067,6 +1078,11 @@ command_updater_.UpdateCommandEnabled(IDC_EXIT, true); command_updater_.UpdateCommandEnabled(IDC_DEBUG_FRAME_TOGGLE, true); command_updater_.UpdateCommandEnabled(IDC_NAME_WINDOW, true); +#if BUILDFLAG(IS_CHROMEOS) + command_updater_.UpdateCommandEnabled( + IDC_TOGGLE_MULTITASK_MENU, + chromeos::wm::features::IsFloatWindowEnabled()); +#endif #if BUILDFLAG(IS_CHROMEOS_ASH) command_updater_.UpdateCommandEnabled(IDC_MINIMIZE_WINDOW, true); // The VisitDesktop command is only supported for up to 5 logged in users
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index a17c84d..a2a1c5d 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -183,6 +183,7 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/apps/intent_helper/supported_links_infobar_delegate.h" +#include "chromeos/ui/wm/features.h" #endif #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) @@ -1846,6 +1847,13 @@ chrome::ShowWindowNamePrompt(browser); } +#if BUILDFLAG(IS_CHROMEOS) +void ToggleMultitaskMenu(Browser* browser) { + DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); + browser->window()->ToggleMultitaskMenu(); +} +#endif + void ToggleCommander(Browser* browser) { commander::Commander::Get()->ToggleForBrowser(browser); }
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h index 49a8648c..89f1e262 100644 --- a/chrome/browser/ui/browser_commands.h +++ b/chrome/browser/ui/browser_commands.h
@@ -244,6 +244,9 @@ bool CanToggleCaretBrowsing(Browser* browser); void ToggleCaretBrowsing(Browser* browser); void PromptToNameWindow(Browser* browser); +#if BUILDFLAG(IS_CHROMEOS) +void ToggleMultitaskMenu(Browser* browser); +#endif void ToggleCommander(Browser* browser); void ExecuteUIDebugCommand(int id, const Browser* browser);
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index 570a3a54..acfd1c6 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h
@@ -232,9 +232,6 @@ // frames may need to refresh their title bar. virtual void UpdateTitleBar() = 0; - // Inform the frame that its color has changed. - virtual void UpdateFrameColor() = 0; - // Invoked when the state of the bookmark bar changes. This is only invoked if // the state changes for the current tab, it is not sent when switching tabs. virtual void BookmarkBarStateChanged( @@ -442,6 +439,9 @@ #if BUILDFLAG(IS_CHROMEOS) // Returns the PageActionIconView for the Sharing Hub. virtual views::Button* GetSharingHubIconButton() = 0; + + // Toggles the multitask menu on the browser frame size button. + virtual void ToggleMultitaskMenu() const = 0; #else // Shows the Sharing Hub bubble. This must only be called as a direct result // of user action.
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index df9bad6e..1621274 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -587,6 +587,14 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) } +void ShowShortcutCustomizationApp(Profile* profile) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + ShowSystemAppInternal(profile, ash::SystemWebAppType::SHORTCUT_CUSTOMIZATION); +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + ShowSystemAppInternal(profile, GURL(kOsUIShortcutCustomizationAppURL)); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +} + #if BUILDFLAG(ENABLE_DICE_SUPPORT) // SigninViewController::ShowSignin is only available with DICE void ShowBrowserSignin(Browser* browser,
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h index 01bd705..bc77a22 100644 --- a/chrome/browser/ui/chrome_pages.h +++ b/chrome/browser/ui/chrome_pages.h
@@ -208,6 +208,8 @@ void ShowDiagnosticsApp(Profile* profile); void ShowFirmwareUpdatesApp(Profile* profile); + +void ShowShortcutCustomizationApp(Profile* profile); #endif #if BUILDFLAG(ENABLE_DICE_SUPPORT)
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc index 2904afcb..54bbe0c 100644 --- a/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc +++ b/chrome/browser/ui/extensions/extension_action_view_controller_unittest.cc
@@ -9,15 +9,12 @@ #include <memory> #include "base/command_line.h" -#include "base/functional/bind.h" #include "base/functional/callback_helpers.h" -#include "base/json/json_reader.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" -#include "chrome/browser/extensions/chrome_extensions_browser_client.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/extension_action_runner.h" #include "chrome/browser/extensions/extension_action_test_util.h" @@ -27,29 +24,25 @@ #include "chrome/browser/extensions/scripting_permissions_modifier.h" #include "chrome/browser/extensions/site_permissions_helper.h" #include "chrome/browser/extensions/test_extension_system.h" +#include "chrome/browser/extensions/user_script_listener.h" #include "chrome/browser/ui/extensions/extension_action_test_helper.h" #include "chrome/browser/ui/extensions/extensions_container.h" #include "chrome/browser/ui/extensions/icon_with_badge_image_source.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" -#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "components/sessions/content/session_tab_helper.h" -#include "content/public/browser/notification_service.h" #include "extensions/browser/extension_action.h" #include "extensions/browser/extension_action_manager.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" -#include "extensions/browser/notification_types.h" #include "extensions/browser/permissions_manager.h" #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/api/extension_action/action_info.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_features.h" #include "extensions/common/mojom/run_location.mojom-shared.h" -#include "extensions/common/user_script.h" -#include "extensions/test/permissions_manager_waiter.h" #include "extensions/test/test_extension_dir.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image_skia_rep.h" @@ -86,8 +79,11 @@ extension_service_ = extensions::ExtensionSystem::Get(profile())->extension_service(); - test_util_ = ExtensionActionTestHelper::Create(browser(), false); + // Create web contents before creating the test helper since the + // extensions menu needs them (e.g compute the string for current site). + AddTab(browser(), GURL(u"https://example.com")); + test_util_ = ExtensionActionTestHelper::Create(browser(), false); view_size_ = test_util_->GetToolbarActionSize(); } @@ -175,8 +171,6 @@ CreateAndAddExtension("extension", extensions::ActionInfo::TYPE_PAGE) ->id(); - AddTab(browser(), GURL("chrome://newtab")); - content::WebContents* web_contents = GetActiveWebContents(); ExtensionActionViewController* const action = GetViewControllerForId(id); ASSERT_TRUE(action);
diff --git a/chrome/browser/ui/hats/hats_helper.cc b/chrome/browser/ui/hats/hats_helper.cc index 88b3255..67e86fe 100644 --- a/chrome/browser/ui/hats/hats_helper.cc +++ b/chrome/browser/ui/hats/hats_helper.cc
@@ -22,7 +22,12 @@ HatsHelper::HatsHelper(content::WebContents* web_contents) : WebContentsObserver(web_contents), - content::WebContentsUserData<HatsHelper>(*web_contents) {} + content::WebContentsUserData<HatsHelper>(*web_contents) { + // Construct PerformanceControlsHatsService immediately to register pref + // listeners. + performance_controls_hats_service_ = + PerformanceControlsHatsServiceFactory::GetForProfile(profile()); +} void HatsHelper::PrimaryPageChanged(content::Page& page) { // Ignore everything except NTP opens. @@ -34,9 +39,8 @@ sentiment_service->OpenedNewTabPage(); } - if (auto* performance_service = - PerformanceControlsHatsServiceFactory::GetForProfile(profile())) { - performance_service->OpenedNewTabPage(); + if (performance_controls_hats_service_) { + performance_controls_hats_service_->OpenedNewTabPage(); } // If the demo HaTS feature is enabled display a test survey on every NTP
diff --git a/chrome/browser/ui/hats/hats_helper.h b/chrome/browser/ui/hats/hats_helper.h index efa058da..8558f33 100644 --- a/chrome/browser/ui/hats/hats_helper.h +++ b/chrome/browser/ui/hats/hats_helper.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_HATS_HATS_HELPER_H_ #define CHROME_BROWSER_UI_HATS_HATS_HELPER_H_ +#include "chrome/browser/ui/performance_controls/performance_controls_hats_service.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -29,6 +30,8 @@ explicit HatsHelper(content::WebContents* web_contents); + raw_ptr<PerformanceControlsHatsService> performance_controls_hats_service_; + // contents::WebContentsObserver: void PrimaryPageChanged(content::Page& page) override;
diff --git a/chrome/browser/ui/hats/hats_service.cc b/chrome/browser/ui/hats/hats_service.cc index 6edf5cf..d7f4a0a 100644 --- a/chrome/browser/ui/hats/hats_service.cc +++ b/chrome/browser/ui/hats/hats_service.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" -#include "components/history_clusters/core/features.h" #include "components/metrics_services_manager/metrics_services_manager.h" #include "components/performance_manager/public/features.h" #include "components/permissions/constants.h" @@ -43,10 +42,6 @@ constexpr char kHatsSurveyTriggerAutofillAddress[] = "autofill-address"; constexpr char kHatsSurveyTriggerAutofillCard[] = "autofill-card"; constexpr char kHatsSurveyTriggerAutofillPassword[] = "autofill-password"; -constexpr char kHatsSurveyTriggerJourneysHistoryEntrypoint[] = - "journeys-history-entrypoint"; -constexpr char kHatsSurveyTriggerJourneysOmniboxEntrypoint[] = - "journeys-omnibox-entrypoint"; constexpr char kHatsSurveyTriggerNtpModules[] = "ntp-modules"; constexpr char kHatsSurveyTriggerNtpPhotosModuleOptOut[] = "ntp-photos-module-opt-out"; @@ -188,14 +183,6 @@ "devtools-issues-csp", "c9fjDmwjb0ugnJ3q1cK0USeAJJ9C"); - // Journeys surveys. - survey_configs.emplace_back( - &history_clusters::kJourneysSurveyForHistoryEntrypoint, - kHatsSurveyTriggerJourneysHistoryEntrypoint); - survey_configs.emplace_back( - &history_clusters::kJourneysSurveyForOmniboxEntrypoint, - kHatsSurveyTriggerJourneysOmniboxEntrypoint); - // Settings surveys. survey_configs.emplace_back( &features::kHappinessTrackingSurveysForDesktopSettings,
diff --git a/chrome/browser/ui/hats/hats_service.h b/chrome/browser/ui/hats/hats_service.h index aa61c01..b2c5484 100644 --- a/chrome/browser/ui/hats/hats_service.h +++ b/chrome/browser/ui/hats/hats_service.h
@@ -41,8 +41,6 @@ extern const char kHatsSurveyTriggerDevToolsIssuesCookiesSameSite[]; extern const char kHatsSurveyTriggerDevToolsIssuesHeavyAd[]; extern const char kHatsSurveyTriggerDevToolsIssuesCSP[]; -extern const char kHatsSurveyTriggerJourneysHistoryEntrypoint[]; -extern const char kHatsSurveyTriggerJourneysOmniboxEntrypoint[]; extern const char kHatsSurveyTriggerNtpModules[]; extern const char kHatsSurveyTriggerNtpPhotosModuleOptOut[]; extern const char kHatsSurveyTriggerPerformanceControlsPerformance[];
diff --git a/chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h b/chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h index 57b7aec..b645874 100644 --- a/chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h +++ b/chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h
@@ -41,6 +41,10 @@ InteractedWithPrivacySandbox3, (FeatureArea feature_area), (override)); + MOCK_METHOD(void, + InteractedWithPrivacySandbox4, + (FeatureArea feature_area), + (override)); MOCK_METHOD(void, RanPasswordCheck, (), (override)); MOCK_METHOD(void, ClearedBrowsingData,
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service.cc b/chrome/browser/ui/hats/trust_safety_sentiment_service.cc index fede869..c1c22af 100644 --- a/chrome/browser/ui/hats/trust_safety_sentiment_service.cc +++ b/chrome/browser/ui/hats/trust_safety_sentiment_service.cc
@@ -66,96 +66,6 @@ : features::kTrustSafetySentimentSurveyNtpVisitsMaxRange.Get(); } -bool ProbabilityCheck(TrustSafetySentimentService::FeatureArea feature_area) { - if (!TrustSafetySentimentService::VersionCheck(feature_area)) { - return false; - } - - if (base::FeatureList::IsEnabled(features::kTrustSafetySentimentSurveyV2)) { - switch (feature_area) { - case (TrustSafetySentimentService::FeatureArea::kTrustedSurface): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2TrustedSurfaceProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kSafetyCheck): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2SafetyCheckProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kPasswordCheck): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2PasswordCheckProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kBrowsingData): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2BrowsingDataProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kPrivacyGuide): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2PrivacyGuideProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kControlGroup): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyV2ControlGroupProbability - .Get(); - default: - NOTREACHED(); - return false; - } - } - - switch (feature_area) { - case (TrustSafetySentimentService::FeatureArea::kPrivacySettings): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyPrivacySettingsProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kTrustedSurface): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyTrustedSurfaceProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kTransactions): - return base::RandDouble() < - features::kTrustSafetySentimentSurveyTransactionsProbability.Get(); - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentAccept): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3ConsentAcceptProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentDecline): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3ConsentDeclineProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeDismiss): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3NoticeDismissProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox3NoticeOk): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3NoticeOkProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeSettings): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3NoticeSettingsProbability - .Get(); - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeLearnMore): - return base::RandDouble() < - features:: - kTrustSafetySentimentSurveyPrivacySandbox3NoticeLearnMoreProbability - .Get(); - default: - NOTREACHED(); - return false; - } -} - bool HasNonDefaultPrivacySetting(Profile* profile) { auto* prefs = profile->GetPrefs(); @@ -474,7 +384,9 @@ } void TrustSafetySentimentService::InteractedWithPrivacySandbox4( - FeatureArea feature_area) {} + FeatureArea feature_area) { + TriggerOccurred(feature_area, {}); +} void TrustSafetySentimentService::OnOffTheRecordProfileCreated( Profile* off_the_record) { @@ -595,45 +507,36 @@ } // static -bool TrustSafetySentimentService::VersionCheck( - TrustSafetySentimentService::FeatureArea feature_area) { +bool TrustSafetySentimentService::VersionCheck(FeatureArea feature_area) { bool isV2 = base::FeatureList::IsEnabled(features::kTrustSafetySentimentSurveyV2); switch (feature_area) { // Version 1 only - case (TrustSafetySentimentService::FeatureArea::kPrivacySettings): - case (TrustSafetySentimentService::FeatureArea::kTransactions): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentAccept): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentDecline): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeDismiss): - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox3NoticeOk): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeSettings): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeLearnMore): + case (FeatureArea::kPrivacySettings): + case (FeatureArea::kTransactions): + case (FeatureArea::kPrivacySandbox3ConsentAccept): + case (FeatureArea::kPrivacySandbox3ConsentDecline): + case (FeatureArea::kPrivacySandbox3NoticeDismiss): + case (FeatureArea::kPrivacySandbox3NoticeOk): + case (FeatureArea::kPrivacySandbox3NoticeSettings): + case (FeatureArea::kPrivacySandbox3NoticeLearnMore): return isV2 == false; // Version 2 only - case (TrustSafetySentimentService::FeatureArea::kSafetyCheck): - case (TrustSafetySentimentService::FeatureArea::kPasswordCheck): - case (TrustSafetySentimentService::FeatureArea::kBrowsingData): - case (TrustSafetySentimentService::FeatureArea::kPrivacyGuide): - case (TrustSafetySentimentService::FeatureArea::kControlGroup): + case (FeatureArea::kSafetyCheck): + case (FeatureArea::kPasswordCheck): + case (FeatureArea::kBrowsingData): + case (FeatureArea::kPrivacyGuide): + case (FeatureArea::kControlGroup): return isV2 == true; // Both Versions - case (TrustSafetySentimentService::FeatureArea::kTrustedSurface): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentAccept): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentDecline): - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk): - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4NoticeSettings): + case (FeatureArea::kTrustedSurface): + case (FeatureArea::kPrivacySandbox4ConsentAccept): + case (FeatureArea::kPrivacySandbox4ConsentDecline): + case (FeatureArea::kPrivacySandbox4NoticeOk): + case (FeatureArea::kPrivacySandbox4NoticeSettings): return true; // None - case (TrustSafetySentimentService::FeatureArea::kIneligible): + case (FeatureArea::kIneligible): return false; default: NOTREACHED(); @@ -643,31 +546,28 @@ // static std::string TrustSafetySentimentService::GetHatsTriggerForFeatureArea( - TrustSafetySentimentService::FeatureArea feature_area) { + FeatureArea feature_area) { if (base::FeatureList::IsEnabled(features::kTrustSafetySentimentSurveyV2)) { switch (feature_area) { - case (TrustSafetySentimentService::FeatureArea::kTrustedSurface): + case (FeatureArea::kTrustedSurface): return kHatsSurveyTriggerTrustSafetyV2TrustedSurface; - case (TrustSafetySentimentService::FeatureArea::kSafetyCheck): + case (FeatureArea::kSafetyCheck): return kHatsSurveyTriggerTrustSafetyV2SafetyCheck; - case (TrustSafetySentimentService::FeatureArea::kPasswordCheck): + case (FeatureArea::kPasswordCheck): return kHatsSurveyTriggerTrustSafetyV2PasswordCheck; - case (TrustSafetySentimentService::FeatureArea::kBrowsingData): + case (FeatureArea::kBrowsingData): return kHatsSurveyTriggerTrustSafetyV2BrowsingData; - case (TrustSafetySentimentService::FeatureArea::kPrivacyGuide): + case (FeatureArea::kPrivacyGuide): return kHatsSurveyTriggerTrustSafetyV2PrivacyGuide; - case (TrustSafetySentimentService::FeatureArea::kControlGroup): + case (FeatureArea::kControlGroup): return kHatsSurveyTriggerTrustSafetyV2ControlGroup; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentAccept): + case (FeatureArea::kPrivacySandbox4ConsentAccept): return kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4ConsentAccept; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentDecline): + case (FeatureArea::kPrivacySandbox4ConsentDecline): return kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4ConsentDecline; - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk): + case (FeatureArea::kPrivacySandbox4NoticeOk): return kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4NoticeOk; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4NoticeSettings): + case (FeatureArea::kPrivacySandbox4NoticeSettings): return kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4NoticeSettings; default: NOTREACHED(); @@ -675,42 +575,160 @@ } } switch (feature_area) { - case (TrustSafetySentimentService::FeatureArea::kPrivacySettings): + case (FeatureArea::kPrivacySettings): return kHatsSurveyTriggerTrustSafetyPrivacySettings; - case (TrustSafetySentimentService::FeatureArea::kTrustedSurface): + case (FeatureArea::kTrustedSurface): return kHatsSurveyTriggerTrustSafetyTrustedSurface; - case (TrustSafetySentimentService::FeatureArea::kTransactions): + case (FeatureArea::kTransactions): return kHatsSurveyTriggerTrustSafetyTransactions; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentAccept): + case (FeatureArea::kPrivacySandbox3ConsentAccept): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3ConsentAccept; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3ConsentDecline): + case (FeatureArea::kPrivacySandbox3ConsentDecline): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3ConsentDecline; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeDismiss): + case (FeatureArea::kPrivacySandbox3NoticeDismiss): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3NoticeDismiss; - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox3NoticeOk): + case (FeatureArea::kPrivacySandbox3NoticeOk): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3NoticeOk; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeSettings): + case (FeatureArea::kPrivacySandbox3NoticeSettings): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3NoticeSettings; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox3NoticeLearnMore): + case (FeatureArea::kPrivacySandbox3NoticeLearnMore): return kHatsSurveyTriggerTrustSafetyPrivacySandbox3NoticeLearnMore; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentAccept): + case (FeatureArea::kPrivacySandbox4ConsentAccept): return kHatsSurveyTriggerTrustSafetyPrivacySandbox4ConsentAccept; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4ConsentDecline): + case (FeatureArea::kPrivacySandbox4ConsentDecline): return kHatsSurveyTriggerTrustSafetyPrivacySandbox4ConsentDecline; - case (TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk): + case (FeatureArea::kPrivacySandbox4NoticeOk): return kHatsSurveyTriggerTrustSafetyPrivacySandbox4NoticeOk; - case (TrustSafetySentimentService::FeatureArea:: - kPrivacySandbox4NoticeSettings): + case (FeatureArea::kPrivacySandbox4NoticeSettings): return kHatsSurveyTriggerTrustSafetyPrivacySandbox4NoticeSettings; default: NOTREACHED(); return ""; } } + +// static +bool TrustSafetySentimentService::ProbabilityCheck(FeatureArea feature_area) { + if (!TrustSafetySentimentService::VersionCheck(feature_area)) { + return false; + } + + if (base::FeatureList::IsEnabled(features::kTrustSafetySentimentSurveyV2)) { + switch (feature_area) { + case (FeatureArea::kTrustedSurface): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2TrustedSurfaceProbability + .Get(); + case (FeatureArea::kSafetyCheck): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2SafetyCheckProbability + .Get(); + case (FeatureArea::kPasswordCheck): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2PasswordCheckProbability + .Get(); + case (FeatureArea::kBrowsingData): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2BrowsingDataProbability + .Get(); + case (FeatureArea::kPrivacyGuide): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2PrivacyGuideProbability + .Get(); + case (FeatureArea::kControlGroup): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyV2ControlGroupProbability + .Get(); + case (FeatureArea::kPrivacySandbox4ConsentAccept): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyV2PrivacySandbox4ConsentAcceptProbability + .Get(); + case (FeatureArea::kPrivacySandbox4ConsentDecline): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyV2PrivacySandbox4ConsentDeclineProbability + .Get(); + case (FeatureArea::kPrivacySandbox4NoticeOk): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyV2PrivacySandbox4NoticeOkProbability + .Get(); + case (FeatureArea::kPrivacySandbox4NoticeSettings): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyV2PrivacySandbox4NoticeSettingsProbability + .Get(); + default: + NOTREACHED(); + return false; + } + } + + switch (feature_area) { + case (FeatureArea::kPrivacySettings): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyPrivacySettingsProbability + .Get(); + case (FeatureArea::kTrustedSurface): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyTrustedSurfaceProbability + .Get(); + case (FeatureArea::kTransactions): + return base::RandDouble() < + features::kTrustSafetySentimentSurveyTransactionsProbability.Get(); + case (FeatureArea::kPrivacySandbox3ConsentAccept): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3ConsentAcceptProbability + .Get(); + case (FeatureArea::kPrivacySandbox3ConsentDecline): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3ConsentDeclineProbability + .Get(); + case (FeatureArea::kPrivacySandbox3NoticeDismiss): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3NoticeDismissProbability + .Get(); + case (FeatureArea::kPrivacySandbox3NoticeOk): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3NoticeOkProbability + .Get(); + case (FeatureArea::kPrivacySandbox3NoticeSettings): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3NoticeSettingsProbability + .Get(); + case (FeatureArea::kPrivacySandbox3NoticeLearnMore): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox3NoticeLearnMoreProbability + .Get(); + case (FeatureArea::kPrivacySandbox4ConsentAccept): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox4ConsentAcceptProbability + .Get(); + case (FeatureArea::kPrivacySandbox4ConsentDecline): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox4ConsentDeclineProbability + .Get(); + case (FeatureArea::kPrivacySandbox4NoticeOk): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox4NoticeOkProbability + .Get(); + case (FeatureArea::kPrivacySandbox4NoticeSettings): + return base::RandDouble() < + features:: + kTrustSafetySentimentSurveyPrivacySandbox4NoticeSettingsProbability + .Get(); + default: + NOTREACHED(); + return false; + } +}
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service.h b/chrome/browser/ui/hats/trust_safety_sentiment_service.h index c698208b..94387e51 100644 --- a/chrome/browser/ui/hats/trust_safety_sentiment_service.h +++ b/chrome/browser/ui/hats/trust_safety_sentiment_service.h
@@ -130,12 +130,14 @@ virtual void InteractedWithPrivacySandbox4(FeatureArea feature_area); // Checks that this feature area is valid for the current version. - static bool VersionCheck( - TrustSafetySentimentService::FeatureArea feature_area); + static bool VersionCheck(FeatureArea feature_area); // Gets the HaTS trigger for a feature area. - static std::string GetHatsTriggerForFeatureArea( - TrustSafetySentimentService::FeatureArea feature_area); + static std::string GetHatsTriggerForFeatureArea(FeatureArea feature_area); + + // Performs a FeatureArea and Version-specific dice roll. + // Returns true if succeeds, else false. + static bool ProbabilityCheck(FeatureArea feature_area); private: friend class TrustSafetySentimentServiceTest;
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service_unittest.cc b/chrome/browser/ui/hats/trust_safety_sentiment_service_unittest.cc index a5cdf49a..2dbd1ea 100644 --- a/chrome/browser/ui/hats/trust_safety_sentiment_service_unittest.cc +++ b/chrome/browser/ui/hats/trust_safety_sentiment_service_unittest.cc
@@ -69,6 +69,7 @@ std::string privacy_sandbox_3_notice_dismiss_probability = "0.1"; std::string privacy_sandbox_3_notice_ok_probability = "0.4"; std::string privacy_sandbox_3_notice_settings_probability = "0.7"; + std::string privacy_sandbox_3_learn_more_probability = "0.2"; std::string privacy_sandbox_4_consent_accept_probability = "0.01"; std::string privacy_sandbox_4_consent_decline_probability = "0.1"; std::string privacy_sandbox_4_notice_ok_probability = "0.1"; @@ -120,6 +121,8 @@ params.privacy_sandbox_3_notice_ok_probability}, {"privacy-sandbox-3-notice-settings-probability", params.privacy_sandbox_3_notice_settings_probability}, + {"privacy-sandbox-3-notice-learn-more-probability", + params.privacy_sandbox_3_learn_more_probability}, {"privacy-sandbox-4-consent-accept-probability", params.privacy_sandbox_4_consent_accept_probability}, {"privacy-sandbox-4-consent-decline-probability", @@ -688,6 +691,84 @@ service()->OpenedNewTabPage(); } +TEST_F(TrustSafetySentimentServiceTest, + InteractedWithPrivacySandbox4ConsentAccept) { + // Accepting Privacy Sandbox 4 consent is considered a trigger, and should + // make a user eligible to receive a survey. + FeatureParams params; + params.privacy_sandbox_4_consent_accept_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParameters(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyPrivacySandbox4ConsentAccept, _, + _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentAccept); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, + InteractedWithPrivacySandbox4ConsentDecline) { + // Declining Privacy Sandbox 4 consent is considered a trigger, and should + // make a user eligible to receive a survey. + FeatureParams params; + params.privacy_sandbox_4_consent_decline_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParameters(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyPrivacySandbox4ConsentDecline, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentDecline); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, InteractedWithPrivacySandbox4NoticeOk) { + // Acknowledging the Privacy Sandbox 4 notice is considered a trigger, and + // should make a user eligible to receive a survey. + FeatureParams params; + params.privacy_sandbox_4_notice_ok_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParameters(params); + + EXPECT_CALL(*mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyPrivacySandbox4NoticeOk, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, + InteractedWithPrivacySandbox4NoticeSettings) { + // Going to settings from the Privacy Sandbox 4 notice is considered a + // trigger, and should make a user eligible to receive a survey. + FeatureParams params; + params.privacy_sandbox_4_notice_settings_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParameters(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyPrivacySandbox4NoticeSettings, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeSettings); + service()->OpenedNewTabPage(); +} + TEST_F(TrustSafetySentimentServiceTest, PrivacySettingsProductSpecificData) { // Check the product specific data accompanying surveys for the Privacy // Settings feature area correctly records whether the user has a non default @@ -877,7 +958,7 @@ {TrustSafetySentimentService::FeatureArea::kPrivacySettings}); } -TEST_F(TrustSafetySentimentServiceTest, AllFeatureAreasCorrectVersions) { +TEST_F(TrustSafetySentimentServiceTest, AllFeatureAreasHaveTriggers) { // Assert that for every feature area there is the correct version(s) and // survey trigger id. FeatureParams paramsv1; @@ -893,7 +974,11 @@ feature_area)); } } - feature_list()->Reset(); +} + +TEST_F(TrustSafetySentimentServiceTest, V2_AllFeatureAreasHaveTriggers) { + // Assert that for every feature area there is the correct version(s) and + // survey trigger id. FeatureParamsV2 paramsv2; SetupFeatureParametersV2(paramsv2); for (int enum_value = 0; @@ -909,6 +994,67 @@ } } +TEST_F(TrustSafetySentimentServiceTest, AllFeatureAreasHaveProbabilities) { + // Check that for every feature with a probability of 1 and the correct + // version, the dice roll always succeeds. + FeatureParams params; + params.privacy_settings_probability = "1.0"; + params.trusted_surface_probability = "1.0"; + params.transactions_probability = "1.0"; + params.privacy_sandbox_3_consent_accept_probability = "1.0"; + params.privacy_sandbox_3_consent_decline_probability = "1.0"; + params.privacy_sandbox_3_notice_dismiss_probability = "1.0"; + params.privacy_sandbox_3_notice_ok_probability = "1.0"; + params.privacy_sandbox_3_notice_settings_probability = "1.0"; + params.privacy_sandbox_3_learn_more_probability = "1.0"; + params.privacy_sandbox_4_consent_accept_probability = "1.0"; + params.privacy_sandbox_4_consent_decline_probability = "1.0"; + params.privacy_sandbox_4_notice_ok_probability = "1.0"; + params.privacy_sandbox_4_notice_settings_probability = "1.0"; + + SetupFeatureParameters(params); + for (int enum_value = 0; + enum_value <= + static_cast<int>(TrustSafetySentimentService::FeatureArea::kMaxValue); + ++enum_value) { + auto feature_area = + static_cast<TrustSafetySentimentService::FeatureArea>(enum_value); + if (TrustSafetySentimentService::VersionCheck(feature_area)) { + EXPECT_TRUE(TrustSafetySentimentService::ProbabilityCheck(feature_area)) + << "Feature area: " << static_cast<int>(feature_area); + } + } +} + +TEST_F(TrustSafetySentimentServiceTest, V2_AllFeatureAreasHaveProbabilities) { + // Check that for every feature with a probability of 1 and the correct + // version, the dice roll always succeeds. + FeatureParamsV2 params; + params.browsing_data_probability = "1.0"; + params.control_group_probability = "1.0"; + params.password_check_probability = "1.0"; + params.safety_check_probability = "1.0"; + params.trusted_surface_probability = "1.0"; + params.privacy_guide_probability = "1.0"; + params.privacy_sandbox_4_consent_accept_probability = "1.0"; + params.privacy_sandbox_4_consent_decline_probability = "1.0"; + params.privacy_sandbox_4_notice_ok_probability = "1.0"; + params.privacy_sandbox_4_notice_settings_probability = "1.0"; + + SetupFeatureParametersV2(params); + for (int enum_value = 0; + enum_value <= + static_cast<int>(TrustSafetySentimentService::FeatureArea::kMaxValue); + ++enum_value) { + auto feature_area = + static_cast<TrustSafetySentimentService::FeatureArea>(enum_value); + if (TrustSafetySentimentService::VersionCheck(feature_area)) { + EXPECT_TRUE(TrustSafetySentimentService::ProbabilityCheck(feature_area)) + << "Feature area: " << static_cast<int>(feature_area); + } + } +} + TEST_F(TrustSafetySentimentServiceTest, Eligibility_V1FeatureWhileV2Enabled) { // A survey from V1 only is not shown because V2 is enabled. FeatureParams params; @@ -1157,3 +1303,79 @@ service()->OnSessionEnded(session_end - session_start, session_end); service()->OpenedNewTabPage(); } + +TEST_F(TrustSafetySentimentServiceTest, V2_PrivacySandbox4ConsentAccept) { + // Accepting Privacy Sandbox 4 consent is considered a trigger, and should + // make a user eligible to receive a survey. + FeatureParamsV2 params; + params.privacy_sandbox_4_consent_accept_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParametersV2(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4ConsentAccept, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentAccept); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, V2_PrivacySandbox4ConsentDecline) { + // Declining Privacy Sandbox 4 consent is considered a trigger, and should + // make a user eligible to receive a survey. + FeatureParamsV2 params; + params.privacy_sandbox_4_consent_decline_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParametersV2(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4ConsentDecline, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentDecline); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, V2_PrivacySandbox4NoticeOk) { + // Acknowledging the Privacy Sandbox 4 notice is considered a trigger, and + // should make a user eligible to receive a survey. + FeatureParamsV2 params; + params.privacy_sandbox_4_notice_ok_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParametersV2(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4NoticeOk, _, _, + _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk); + service()->OpenedNewTabPage(); +} + +TEST_F(TrustSafetySentimentServiceTest, V2_PrivacySandbox4NoticeSettings) { + // Going to settings from the Privacy Sandbox 4 notice is considered a + // trigger, and should make a user eligible to receive a survey. + FeatureParamsV2 params; + params.privacy_sandbox_4_notice_settings_probability = "1.0"; + params.min_time_to_prompt = "0s"; + params.ntp_visits_min_range = "0"; + params.ntp_visits_max_range = "0"; + SetupFeatureParametersV2(params); + + EXPECT_CALL( + *mock_hats_service(), + LaunchSurvey(kHatsSurveyTriggerTrustSafetyV2PrivacySandbox4NoticeSettings, + _, _, _, _)); + service()->InteractedWithPrivacySandbox4( + TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeSettings); + service()->OpenedNewTabPage(); +}
diff --git a/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc b/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc index ca272fd..845e94e 100644 --- a/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc +++ b/chrome/browser/ui/omnibox/omnibox_pedal_implementations.cc
@@ -1943,7 +1943,7 @@ // Note: shell_integration::CanSetAsDefaultBrowser() uses this call too, // and if permission is SET_DEFAULT_NOT_ALLOWED, this method returns false. const shell_integration::DefaultWebClientSetPermission permission = - shell_integration::GetDefaultWebClientSetPermission(); + shell_integration::GetDefaultBrowserSetPermission(); return (permission == shell_integration::SET_DEFAULT_INTERACTIVE && OmniboxFieldTrial::kDefaultBrowserPedalInteractive.Get()) || (permission == shell_integration::SET_DEFAULT_UNATTENDED &&
diff --git a/chrome/browser/ui/page_action/page_action_icon_type.h b/chrome/browser/ui/page_action/page_action_icon_type.h index 52cffc9d..b77a9d3 100644 --- a/chrome/browser/ui/page_action/page_action_icon_type.h +++ b/chrome/browser/ui/page_action/page_action_icon_type.h
@@ -34,7 +34,8 @@ kVirtualCardEnroll, kVirtualCardManualFallback, kZoom, - kMaxValue = kZoom, + kSaveIban, + kMaxValue = kSaveIban, }; static_assert(static_cast<int>(PageActionIconType::kBookmarkStar) == 0); @@ -63,4 +64,5 @@ static_assert( static_cast<int>(PageActionIconType::kVirtualCardManualFallback) == 22); static_assert(static_cast<int>(PageActionIconType::kZoom) == 23); +static_assert(static_cast<int>(PageActionIconType::kSaveIban) == 24); #endif // CHROME_BROWSER_UI_PAGE_ACTION_PAGE_ACTION_ICON_TYPE_H_
diff --git a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc index 9ad324e..dbe9ff3 100644 --- a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc +++ b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/password_manager/password_manager_uitest_util.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h" #include "chrome/browser/ui/passwords/password_generation_popup_view_tester.h" @@ -17,11 +18,44 @@ #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" #include "components/password_manager/core/common/password_manager_features.h" +#include "content/public/browser/browser_accessibility_state.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/accessibility/ax_enums.mojom-shared.h" +#include "ui/accessibility/platform/ax_platform_node.h" +#include "ui/accessibility/platform/ax_platform_node_delegate.h" +#include "ui/accessibility/platform/child_iterator_base.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/views/widget/any_widget_observer.h" +#include "ui/views/widget/widget.h" namespace autofill { +namespace { + +ui::AXPlatformNodeDelegate* FindNode(ui::AXPlatformNodeDelegate* root, + const std::string& class_name) { + if (!root) { + return nullptr; + } + + if (root->GetStringAttribute(ax::mojom::StringAttribute::kClassName) == + class_name) { + return root; + } + + for (auto it = root->ChildrenBegin(); *it != *root->ChildrenEnd(); ++(*it)) { + ui::AXPlatformNodeDelegate* child_found = FindNode(it->get(), class_name); + if (child_found) { + return child_found; + } + } + + return nullptr; +} + +} // namespace + class PasswordGenerationPopupViewTest : public InProcessBrowserTest {}; class PasswordGenerationPopupViewWithStrengthIndicatorTest @@ -352,4 +386,75 @@ web_contents->Close(); } +using PasswordGenerationPopupViewAxTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewAxTest, PopupInAxTree) { +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) + content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + auto container_bounds = web_contents->GetContainerBounds(); + password_generation::PasswordGenerationUIData ui_data( + gfx::RectF(container_bounds.x(), container_bounds.y(), 10, 10), + /*max_length=*/10, + /*generation_element=*/std::u16string(), + /*user_typed_password=*/std::u16string(), FieldRendererId(100), + /*is_generation_element_password_type=*/true, base::i18n::TextDirection(), + FormData()); + + TestGenerationPopupObserver observer; + base::WeakPtr<PasswordGenerationPopupControllerImpl> controller = + PasswordGenerationPopupControllerImpl::GetOrCreate( + /*previous=*/nullptr, ui_data.bounds, ui_data, + password_manager::ContentPasswordManagerDriverFactory:: + FromWebContents(web_contents) + ->GetDriverForFrame(web_contents->GetPrimaryMainFrame()) + ->AsWeakPtr(), + &observer, web_contents, web_contents->GetPrimaryMainFrame()); + + views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, + "PasswordGenerationPopupViewViews"); + controller->Show(GenerationUIState::kOfferGeneration); + + gfx::NativeWindow window = gfx::kNullNativeWindow; +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + // On Mac and Linux the whole ax tree grows from the main root windows + // and the popup node can be found there. This gives more confidence + // that it is in the right place than on Windows (see below) where + // the popup subtree lives separately. + waiter.WaitIfNeededAndGet(); + window = chrome::FindLastActive()->window()->GetNativeWindow(); +#elif BUILDFLAG(IS_WIN) + views::Widget* dialog_widget = waiter.WaitIfNeededAndGet(); + window = dialog_widget->GetNativeWindow(); +#endif + + ui::AXPlatformNode* root_node = ui::AXPlatformNode::FromNativeWindow(window); + ui::AXPlatformNodeDelegate* root_node_delegate = root_node->GetDelegate(); + ui::AXPlatformNodeDelegate* node_delegate = + FindNode(root_node_delegate, + "PasswordGenerationPopupViewViews::GeneratedPasswordBox"); + + ASSERT_THAT(node_delegate, ::testing::NotNull()); + EXPECT_FALSE( + node_delegate->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)); + + // Set the screen reader focus by calling a method on the controller directly, + // it normally is triggered by UI events when the screen reader is on, + // screen reader presence is hard/expensive to emulate. + static_cast<PasswordGenerationPopupController*>(controller.get()) + ->SetSelected(); + + EXPECT_TRUE( + node_delegate->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)); + + web_contents->Close(); + content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); +#else + GTEST_SKIP() << "Accessibility reflection is not supported on this platform."; +#endif +} + } // namespace autofill
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc b/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc index 71e0c90..808090c 100644 --- a/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc +++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service.cc
@@ -17,12 +17,82 @@ #include "components/prefs/pref_service.h" PerformanceControlsHatsService::PerformanceControlsHatsService(Profile* profile) - : profile_(profile) {} + : profile_(profile) { + PrefService* local_state = g_browser_process->local_state(); + if (local_state) { + local_pref_registrar_.Init(local_state); + if (base::FeatureList::IsEnabled( + performance_manager::features::kHighEfficiencyModeAvailable) && + base::FeatureList::IsEnabled( + performance_manager::features:: + kPerformanceControlsHighEfficiencyOptOutSurvey)) { + local_pref_registrar_.Add( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled, + base::BindRepeating( + &PerformanceControlsHatsService::OnHighEfficiencyModeChange, + base::Unretained(this))); + } + + if (base::FeatureList::IsEnabled( + performance_manager::features::kBatterySaverModeAvailable) && + base::FeatureList::IsEnabled( + performance_manager::features:: + kPerformanceControlsBatterySaverOptOutSurvey)) { + local_pref_registrar_.Add( + performance_manager::user_tuning::prefs::kBatterySaverModeState, + base::BindRepeating( + &PerformanceControlsHatsService::OnBatterySaverModeChange, + base::Unretained(this))); + } + } +} + +PerformanceControlsHatsService::~PerformanceControlsHatsService() { + local_pref_registrar_.RemoveAll(); +} + +void PerformanceControlsHatsService::OnHighEfficiencyModeChange() { + HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true); + if (!hats_service) { + return; + } + + PrefService* prefs = g_browser_process->local_state(); + // A survey for users who have turned off high efficiency mode. + if (!prefs->GetBoolean(performance_manager::user_tuning::prefs:: + kHighEfficiencyModeEnabled)) { + auto* pref = prefs->FindPreference( + performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); + if (!pref->IsManaged() && !pref->IsDefaultValue()) { + hats_service->LaunchDelayedSurvey( + kHatsSurveyTriggerPerformanceControlsHighEfficiencyOptOut, 10000); + } + } +} + +void PerformanceControlsHatsService::OnBatterySaverModeChange() { + HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true); + if (!hats_service) { + return; + } + + // A survey for users who have turned off battery saver. + PrefService* prefs = g_browser_process->local_state(); + if (prefs->GetInteger( + performance_manager::user_tuning::prefs::kBatterySaverModeState) == + static_cast<int>(performance_manager::user_tuning::prefs:: + BatterySaverModeState::kDisabled)) { + auto* pref = prefs->FindPreference( + performance_manager::user_tuning::prefs::kBatterySaverModeState); + if (!pref->IsManaged()) { + hats_service->LaunchDelayedSurvey( + kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut, 10000); + } + } +} void PerformanceControlsHatsService::OpenedNewTabPage() { HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true); - - // If none of the features are enabled, return early. if (!hats_service) { return; } @@ -32,12 +102,6 @@ const bool show_battery_survey = base::FeatureList::IsEnabled( performance_manager::features:: kPerformanceControlsBatteryPerformanceSurvey); - const bool show_high_efficiency_opt_out_survey = base::FeatureList::IsEnabled( - performance_manager::features:: - kPerformanceControlsHighEfficiencyOptOutSurvey); - const bool show_battery_saver_opt_out_survey = base::FeatureList::IsEnabled( - performance_manager::features:: - kPerformanceControlsBatterySaverOptOutSurvey); PrefService* prefs = g_browser_process->local_state(); const int battery_saver_mode = prefs->GetInteger( @@ -63,31 +127,4 @@ {{"high_efficiency_mode", high_efficiency_mode}}, {{"battery_saver_mode", base::NumberToString(battery_saver_mode)}}); } - - // A survey for users who have turned off high efficiency mode. - if (show_high_efficiency_opt_out_survey && !high_efficiency_mode && - base::FeatureList::IsEnabled( - performance_manager::features::kHighEfficiencyModeAvailable)) { - auto* pref = prefs->FindPreference( - performance_manager::user_tuning::prefs::kHighEfficiencyModeEnabled); - if (!pref->IsManaged() && !pref->IsDefaultValue()) { - hats_service->LaunchSurvey( - kHatsSurveyTriggerPerformanceControlsHighEfficiencyOptOut); - } - } - - // A survey for users who have turned off battery saver. - if (show_battery_saver_opt_out_survey && - base::FeatureList::IsEnabled( - performance_manager::features::kBatterySaverModeAvailable) && - battery_saver_mode == - static_cast<int>(performance_manager::user_tuning::prefs:: - BatterySaverModeState::kDisabled)) { - auto* pref = prefs->FindPreference( - performance_manager::user_tuning::prefs::kBatterySaverModeState); - if (!pref->IsManaged()) { - hats_service->LaunchSurvey( - kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut); - } - } }
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service.h b/chrome/browser/ui/performance_controls/performance_controls_hats_service.h index f4c44ce..707d98a 100644 --- a/chrome/browser/ui/performance_controls/performance_controls_hats_service.h +++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service.h
@@ -7,11 +7,20 @@ #include "chrome/browser/profiles/profile.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/prefs/pref_change_registrar.h" class PerformanceControlsHatsService : public KeyedService { public: explicit PerformanceControlsHatsService(Profile* profile); - ~PerformanceControlsHatsService() override = default; + ~PerformanceControlsHatsService() override; + + // Called in response to a change in the high efficiency mode pref to check + // whether a HaTS survey should be shown. + void OnHighEfficiencyModeChange(); + + // Called in response to a change in the battery saver mode pref to check + // whether a HaTS survey should be shown. + void OnBatterySaverModeChange(); // Called when the user opens an NTP. This allows the service to check if one // of the performance controls surveys should be shown. @@ -19,6 +28,7 @@ private: raw_ptr<Profile> profile_; + PrefChangeRegistrar local_pref_registrar_; }; #endif // CHROME_BROWSER_UI_PERFORMANCE_CONTROLS_PERFORMANCE_CONTROLS_HATS_SERVICE_H_
diff --git a/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc b/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc index 7df3c07..e8f5e04 100644 --- a/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc +++ b/chrome/browser/ui/performance_controls/performance_controls_hats_service_unittest.cc
@@ -53,9 +53,8 @@ } void TearDown() override { - environment_.TearDown(); - profile_manager_.reset(); testing::Test::TearDown(); + environment_.TearDown(); } void SetBatterySaverMode( @@ -121,7 +120,7 @@ } }; -class PerformanceControlsHatsServiceMemoryOptOutTest +class PerformanceControlsHatsServiceHighEfficiencyOptOutTest : public PerformanceControlsHatsServiceTest { protected: const std::vector<base::test::FeatureRefAndParams> GetFeatures() override { @@ -134,7 +133,7 @@ } }; -class PerformanceControlsHatsServiceBatteryOptOutTest +class PerformanceControlsHatsServiceBatterySaverOptOutTest : public PerformanceControlsHatsServiceTest { protected: const std::vector<base::test::FeatureRefAndParams> GetFeatures() override { @@ -173,23 +172,21 @@ performance_controls_hats_service()->OpenedNewTabPage(); } -TEST_F(PerformanceControlsHatsServiceMemoryOptOutTest, - LaunchesMemoryOptOutSurvey) { +TEST_F(PerformanceControlsHatsServiceHighEfficiencyOptOutTest, + LaunchesHighEfficiencyOptOutSurvey) { + EXPECT_CALL(*mock_hats_service(), + LaunchDelayedSurvey( + kHatsSurveyTriggerPerformanceControlsHighEfficiencyOptOut, + 10000, _, _)); SetHighEfficiencyEnabled(false); - EXPECT_CALL( - *mock_hats_service(), - LaunchSurvey(kHatsSurveyTriggerPerformanceControlsHighEfficiencyOptOut, _, - _, _, _)); - performance_controls_hats_service()->OpenedNewTabPage(); } -TEST_F(PerformanceControlsHatsServiceBatteryOptOutTest, - LaunchesBatteryOptOutSurvey) { +TEST_F(PerformanceControlsHatsServiceBatterySaverOptOutTest, + LaunchesBatterySaverOptOutSurvey) { + EXPECT_CALL(*mock_hats_service(), + LaunchDelayedSurvey( + kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut, + 10000, _, _)); SetBatterySaverMode(performance_manager::user_tuning::prefs:: BatterySaverModeState::kDisabled); - EXPECT_CALL( - *mock_hats_service(), - LaunchSurvey(kHatsSurveyTriggerPerformanceControlsBatterySaverOptOut, _, - _, _, _)); - performance_controls_hats_service()->OpenedNewTabPage(); }
diff --git a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc b/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc index 59fc4eb..e11fad4 100644 --- a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc +++ b/chrome/browser/ui/performance_controls/tab_discard_tab_helper.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/performance_controls/tab_discard_tab_helper.h" #include "chrome/browser/performance_manager/public/user_tuning/user_performance_tuning_manager.h" +#include "content/public/common/url_constants.h" namespace { // Conversion constant for bytes to kilobytes. @@ -17,8 +18,8 @@ : content::WebContentsObserver(contents), content::WebContentsUserData<TabDiscardTabHelper>(*contents) {} -bool TabDiscardTabHelper::IsChipVisible() const { - return was_discarded_; +bool TabDiscardTabHelper::ShouldChipBeVisible() const { + return was_discarded_ && is_page_supported_; } bool TabDiscardTabHelper::ShouldIconAnimate() const { @@ -64,6 +65,11 @@ was_discarded_ = navigation_handle->ExistingDocumentWasDiscarded(); was_animated_ = false; was_chip_hidden_ = false; + is_page_supported_ = DoesChipSupportPage(navigation_handle->GetURL()); +} + +bool TabDiscardTabHelper::DoesChipSupportPage(const GURL& url) const { + return !url.SchemeIs(content::kChromeUIScheme); } WEB_CONTENTS_USER_DATA_KEY_IMPL(TabDiscardTabHelper);
diff --git a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h b/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h index 87fccdc..0df95c7 100644 --- a/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h +++ b/chrome/browser/ui/performance_controls/tab_discard_tab_helper.h
@@ -24,7 +24,7 @@ ~TabDiscardTabHelper() override; // Returns whether the chip associated with a discarded tab should be shown. - bool IsChipVisible() const; + bool ShouldChipBeVisible() const; // Returns whether the chip associated with a discarded tab should animate in. bool ShouldIconAnimate() const; @@ -53,9 +53,15 @@ private: friend class content::WebContentsUserData<TabDiscardTabHelper>; explicit TabDiscardTabHelper(content::WebContents* contents); + + // Returns whether the high efficiency chip should be supported for the + // given URL + bool DoesChipSupportPage(const GURL& url) const; + bool was_discarded_ = false; bool was_animated_ = false; bool was_chip_hidden_ = false; + bool is_page_supported_ = false; WEB_CONTENTS_USER_DATA_KEY_DECL(); };
diff --git a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt.h b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt.h index 3d504e9..e40076b 100644 --- a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt.h +++ b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt.h
@@ -24,4 +24,8 @@ // notice the user. void ShowPrivacySandboxNoticeBubble(Browser* browser); +// Returns whether a Privacy Sandbox prompt can be shown in the |browser|. +// Checks if the maximum dialog size fits the prompt. +bool CanWindowFitPrivacySandboxPrompt(Browser* browser); + #endif // CHROME_BROWSER_UI_PRIVACY_SANDBOX_PRIVACY_SANDBOX_PROMPT_H_
diff --git a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc index f930074f..d4a5290 100644 --- a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc +++ b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc
@@ -132,6 +132,16 @@ return; } + const bool is_window_too_small = !CanWindowFitPrivacySandboxPrompt(browser); + base::UmaHistogramBoolean("Settings.PrivacySandbox.DialogWindowTooSmall", + is_window_too_small); + // If the windows size is too small, it is difficult to read or interrupt with + // the dialog. The dialog is blocking modal, that is why we want to prevent it + // from showing if there isn't enough space. + if (is_window_too_small) { + return; + } + // Record the URL that the prompt was displayed over. uint32_t host_hash = base::Hash(navigation_handle->GetURL().IsAboutBlank() ? "about:blank"
diff --git a/chrome/browser/ui/side_search/side_search_metrics.cc b/chrome/browser/ui/side_search/side_search_metrics.cc index ef5dda7..0c5ec46 100644 --- a/chrome/browser/ui/side_search/side_search_metrics.cc +++ b/chrome/browser/ui/side_search/side_search_metrics.cc
@@ -17,14 +17,6 @@ "SideSearch.PageActionIcon.LabelVisibleWhenToggled", label_visibility); } -void RecordSideSearchOpenAction(SideSearchOpenActionType action) { - base::UmaHistogramEnumeration("SideSearch.OpenAction", action); -} - -void RecordSideSearchCloseAction(SideSearchCloseActionType action) { - base::UmaHistogramEnumeration("SideSearch.CloseAction", action); -} - void RecordSideSearchNavigation(SideSearchNavigationType type) { base::UmaHistogramEnumeration("SideSearch.Navigation", type); } @@ -63,14 +55,6 @@ count); } -void RecordSideSearchSidePanelTimeShown(bool shown_via_entrypoint, - base::TimeDelta sample) { - base::UmaHistogramMediumTimes( - shown_via_entrypoint ? "SideSearch.SidePanel.TimeShownOpenedViaEntrypoint" - : "SideSearch.SidePanel.TimeShownOpenedViaTabSwitch", - sample); -} - void RecordSideSearchNumTimesReturnedBackToSRP(int count) { base::UmaHistogramCounts100("SideSearch.TimesReturnedBackToSRP", count); }
diff --git a/chrome/browser/ui/side_search/side_search_metrics.h b/chrome/browser/ui/side_search/side_search_metrics.h index c118a56..6935dd14 100644 --- a/chrome/browser/ui/side_search/side_search_metrics.h +++ b/chrome/browser/ui/side_search/side_search_metrics.h
@@ -5,10 +5,6 @@ #ifndef CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_METRICS_H_ #define CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_METRICS_H_ -namespace base { -class TimeDelta; -} // namespace base - // Enums for histograms: // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -24,17 +20,6 @@ kMaxValue = kVisible }; -enum class SideSearchOpenActionType { - kTapOnSideSearchToolbarButton = 0, - kMaxValue = kTapOnSideSearchToolbarButton -}; - -enum class SideSearchCloseActionType { - kTapOnSideSearchToolbarButton = 0, - kTapOnSideSearchCloseButton = 1, - kMaxValue = kTapOnSideSearchCloseButton -}; - enum class SideSearchNavigationType { kNavigationCommittedWithinSideSearch = 0, kRedirectionToTab = 1, @@ -45,8 +30,6 @@ void RecordSideSearchAvailabilityChanged(SideSearchAvailabilityChangeType type); void RecordSideSearchPageActionLabelVisibilityOnToggle( SideSearchPageActionLabelVisibility label_visibility); -void RecordSideSearchOpenAction(SideSearchOpenActionType action); -void RecordSideSearchCloseAction(SideSearchCloseActionType action); void RecordSideSearchNavigation(SideSearchNavigationType type); void RecordNavigationCommittedWithinSideSearchCountPerJourney( bool is_side_contents_helper_created_from_menu_option, @@ -56,8 +39,6 @@ bool is_side_contents_helper_created_from_menu_option, int count, bool was_auto_triggered); -void RecordSideSearchSidePanelTimeShown(bool shown_via_entrypoint, - base::TimeDelta sample); void RecordSideSearchNumTimesReturnedBackToSRP(int count); #endif // CHROME_BROWSER_UI_SIDE_SEARCH_SIDE_SEARCH_METRICS_H_
diff --git a/chrome/browser/ui/side_search/side_search_utils.cc b/chrome/browser/ui/side_search/side_search_utils.cc index 1734ba0..952ca34 100644 --- a/chrome/browser/ui/side_search/side_search_utils.cc +++ b/chrome/browser/ui/side_search/side_search_utils.cc
@@ -40,16 +40,6 @@ return side_search_tab_data.SerializeAsString(); } -void MaybeAddSideSearchTabRestoreData( - content::WebContents* web_contents, - std::map<std::string, std::string>& extra_data) { - SideSearchTabContentsHelper* helper = - SideSearchTabContentsHelper::FromWebContents(web_contents); - if (helper && helper->last_search_url().has_value()) - extra_data[kSideSearchExtraDataKey] = - SerializeSideSearchTabDataAsString(helper); -} - absl::optional<std::pair<std::string, std::string>> MaybeGetSideSearchTabRestoreData(content::WebContents* web_contents) { SideSearchTabContentsHelper* helper =
diff --git a/chrome/browser/ui/side_search/side_search_utils.h b/chrome/browser/ui/side_search/side_search_utils.h index 434c2db..16afb2a 100644 --- a/chrome/browser/ui/side_search/side_search_utils.h +++ b/chrome/browser/ui/side_search/side_search_utils.h
@@ -21,11 +21,6 @@ namespace side_search { -// Adds side search state data to a tab's state restore data if applicable. -void MaybeAddSideSearchTabRestoreData( - content::WebContents* web_contents, - std::map<std::string, std::string>& extra_data); - // Returns side search tab restore state data if applicable or empty. absl::optional<std::pair<std::string, std::string>> MaybeGetSideSearchTabRestoreData(content::WebContents* web_contents);
diff --git a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc index 7b59634..f5809cc 100644 --- a/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc +++ b/chrome/browser/ui/startup/obsolete_system_infobar_delegate.cc
@@ -21,9 +21,7 @@ new ObsoleteSystemInfoBarDelegate()))); } -ObsoleteSystemInfoBarDelegate::ObsoleteSystemInfoBarDelegate() - : ConfirmInfoBarDelegate() { -} +ObsoleteSystemInfoBarDelegate::ObsoleteSystemInfoBarDelegate() = default; infobars::InfoBarDelegate::InfoBarIdentifier ObsoleteSystemInfoBarDelegate::GetIdentifier() const {
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index dabea8e..cb825e9 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -168,10 +168,10 @@ #endif // !BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif #if BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 1583416..56716f7 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -101,13 +101,6 @@ "SearchWebInSidePanel", base::FEATURE_DISABLED_BY_DEFAULT); -// Whether to clobber all side search side panels in the current browser window -// or only the side search in the current tab before read later or lens side -// panel is open. -BASE_FEATURE(kClobberAllSideSearchSidePanels, - "ClobberAllSideSearchSidePanels", - base::FEATURE_ENABLED_BY_DEFAULT); - // Feature that controls whether or not feature engagement configurations can be // used to control automatic triggering for side search. BASE_FEATURE(kSideSearchAutoTriggering,
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index e1e1534..9abc69d7 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -78,7 +78,6 @@ BASE_DECLARE_FEATURE(kSideSearchFeedback); BASE_DECLARE_FEATURE(kSearchWebInSidePanel); -BASE_DECLARE_FEATURE(kClobberAllSideSearchSidePanels); BASE_DECLARE_FEATURE(kSideSearchAutoTriggering); extern const base::FeatureParam<int> kSideSearchAutoTriggeringReturnCount;
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc index bec06e55..1b67136 100644 --- a/chrome/browser/ui/views/accelerator_table.cc +++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -179,6 +179,7 @@ {ui::VKEY_BROWSER_STOP, ui::EF_NONE, IDC_STOP}, // On Chrome OS, Search + Esc is used to call out task manager. {ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, IDC_TASK_MANAGER}, + {ui::VKEY_Z, ui::EF_COMMAND_DOWN, IDC_TOGGLE_MULTITASK_MENU}, #else // BUILDFLAG(IS_CHROMEOS) {ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, IDC_TASK_MANAGER}, {ui::VKEY_LMENU, ui::EF_NONE, IDC_FOCUS_MENU_BAR},
diff --git a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc index b818b4c..28e7ef8d 100644 --- a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc +++ b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/autofill/autofill_bubble_base.h" #include "chrome/browser/ui/autofill/payments/save_card_ui.h" +#include "chrome/browser/ui/autofill/payments/save_iban_ui.h" #include "chrome/browser/ui/autofill/payments/save_upi_bubble.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/views/autofill/edit_address_profile_view.h" @@ -20,6 +21,7 @@ #include "chrome/browser/ui/views/autofill/payments/save_card_failure_bubble_views.h" #include "chrome/browser/ui/views/autofill/payments/save_card_manage_cards_bubble_views.h" #include "chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h" +#include "chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h" #include "chrome/browser/ui/views/autofill/payments/save_upi_offer_bubble_views.h" #include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.h" #include "chrome/browser/ui/views/autofill/payments/virtual_card_enroll_icon_view.h" @@ -103,6 +105,23 @@ return bubble; } +AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowSaveIbanBubble( + content::WebContents* web_contents, + SaveIbanBubbleController* controller, + bool is_user_gesture) { + // TODO(crbug.com/1349109): Add page action icon view for IBAN. + views::View* anchor_view = + toolbar_button_provider_->GetAnchorView(PageActionIconType::kSaveIban); + + SaveIbanBubbleView* bubble = + new SaveIbanBubbleView(anchor_view, web_contents, controller); + + views::BubbleDialogDelegateView::CreateBubble(bubble); + bubble->Show(is_user_gesture ? LocationBarBubbleDelegateView::USER_GESTURE + : LocationBarBubbleDelegateView::AUTOMATIC); + return bubble; +} + AutofillBubbleBase* AutofillBubbleHandlerImpl::ShowLocalCardMigrationBubble( content::WebContents* web_contents, LocalCardMigrationBubbleController* controller,
diff --git a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h index f8aaed7e..304cac8 100644 --- a/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h +++ b/chrome/browser/ui/views/autofill/autofill_bubble_handler_impl.h
@@ -23,6 +23,7 @@ class AutofillBubbleBase; class LocalCardMigrationBubbleController; class SaveCardBubbleController; +class SaveIbanBubbleController; class SaveUPIBubble; class AutofillBubbleHandlerImpl : public AutofillBubbleHandler, @@ -43,6 +44,9 @@ content::WebContents* web_contents, SaveCardBubbleController* controller, bool is_user_gesture) override; + AutofillBubbleBase* ShowSaveIbanBubble(content::WebContents* web_contents, + SaveIbanBubbleController* controller, + bool is_user_gesture) override; AutofillBubbleBase* ShowLocalCardMigrationBubble( content::WebContents* web_contents, LocalCardMigrationBubbleController* controller,
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc index 1c25be2..0aa2370 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -244,7 +244,8 @@ constexpr auto kDerivedClasses = base::MakeFixedFlatSet<base::StringPiece>( {"AutofillPopupSuggestionView", "PasswordPopupSuggestionView", "AutofillPopupFooterView", "AutofillPopupSeparatorView", - "AutofillPopupWarningView", "AutofillPopupBaseView"}); + "AutofillPopupWarningView", "AutofillPopupBaseView", + "PasswordGenerationPopupViewViews::GeneratedPasswordBox"}); DCHECK(kDerivedClasses.contains(selected_view->GetClassName())) << "If you add a new derived class from AutofillPopupRowView, add it " "here and to onSelection(evt) in "
diff --git a/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.cc b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.cc new file mode 100644 index 0000000..c40e934 --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.cc
@@ -0,0 +1,174 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h" + +#include "chrome/browser/ui/views/accessibility/theme_tracking_non_accessible_image_view.h" +#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h" +#include "chrome/browser/ui/views/autofill/payments/payments_view_util.h" +#include "chrome/browser/ui/views/chrome_layout_provider.h" +#include "chrome/grit/theme_resources.h" +#include "components/autofill/core/browser/data_model/iban.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/color_palette.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/box_layout_view.h" + +namespace autofill { + +SaveIbanBubbleView::SaveIbanBubbleView(views::View* anchor_view, + content::WebContents* web_contents, + SaveIbanBubbleController* controller) + : LocationBarBubbleDelegateView(anchor_view, web_contents), + controller_(controller) { + DCHECK(controller); + SetButtonLabel(ui::DIALOG_BUTTON_OK, controller->GetAcceptButtonText()); + SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, controller->GetDeclineButtonText()); + SetCancelCallback(base::BindOnce(&SaveIbanBubbleView::OnDialogCancelled, + base::Unretained(this))); + SetAcceptCallback(base::BindOnce(&SaveIbanBubbleView::OnDialogAccepted, + base::Unretained(this))); + + SetShowCloseButton(true); + set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); +} + +void SaveIbanBubbleView::Show(DisplayReason reason) { + ShowForReason(reason); + AssignIdsToDialogButtonsForTesting(); // IN-TEST +} + +std::u16string SaveIbanBubbleView::GetIBANIdentifierString() { + return controller_->GetIBAN().GetIdentifierStringForAutofillDisplay(); +} + +void SaveIbanBubbleView::Hide() { + CloseBubble(); + + // If `controller_` is null, WindowClosing() won't invoke OnBubbleClosed(), so + // do that here. This will clear out `controller_`'s reference to `this`. Note + // that WindowClosing() happens only after the _asynchronous_ Close() task + // posted in CloseBubble() completes, but we need to fix references sooner. + if (controller_) { + controller_->OnBubbleClosed( + GetPaymentsBubbleClosedReasonFromWidget(GetWidget())); + } + controller_ = nullptr; +} + +void SaveIbanBubbleView::AddedToWidget() { + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + + GetBubbleFrameView()->SetHeaderView( + std::make_unique<ThemeTrackingNonAccessibleImageView>( + *bundle.GetImageSkiaNamed(IDR_SAVE_CARD_SECURELY), + *bundle.GetImageSkiaNamed(IDR_SAVE_CARD_SECURELY_DARK), + base::BindRepeating(&views::BubbleDialogDelegate::GetBackgroundColor, + base::Unretained(this)))); + + auto title_label = std::make_unique<views::Label>( + GetWindowTitle(), views::style::CONTEXT_DIALOG_TITLE); + title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + title_label->SetMultiLine(true); + + // TODO(crbug.com/1352606): Add Chrome icon and separator. + GetBubbleFrameView()->SetTitleView(std::move(title_label)); +} + +std::u16string SaveIbanBubbleView::GetWindowTitle() const { + return controller_ ? controller_->GetWindowTitle() : std::u16string(); +} + +void SaveIbanBubbleView::WindowClosing() { + if (controller_) { + controller_->OnBubbleClosed( + GetPaymentsBubbleClosedReasonFromWidget(GetWidget())); + controller_ = nullptr; + } +} + +SaveIbanBubbleView::~SaveIbanBubbleView() = default; + +void SaveIbanBubbleView::CreateMainContentView() { + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + ChromeLayoutProvider* const provider = ChromeLayoutProvider::Get(); + + auto* iban_view = AddChildView(std::make_unique<views::BoxLayoutView>()); + iban_view->SetID(DialogViewId::MAIN_CONTENT_VIEW_LOCAL); + views::TableLayout* layout = + iban_view->SetLayoutManager(std::make_unique<views::TableLayout>()); + layout + ->AddColumn(views::LayoutAlignment::kStart, + views::LayoutAlignment::kCenter, + views::TableLayout::kFixedSize, + views::TableLayout::ColumnSize::kUsePreferred, 0, 0) + .AddPaddingColumn( + views::TableLayout::kFixedSize, + provider->GetDistanceMetric(views::DISTANCE_RELATED_LABEL_HORIZONTAL)) + .AddColumn(views::LayoutAlignment::kStretch, + views::LayoutAlignment::kStretch, 1.0, + views::TableLayout::ColumnSize::kFixed, 0, 0) + // Add a row for IBAN label and the value of IBAN. + .AddRows(1, views::TableLayout::kFixedSize) + .AddPaddingRow(views::TableLayout::kFixedSize, + ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_CONTROL_LIST_VERTICAL)) + // Add a row for nickname label and the input text field. + .AddRows(1, views::TableLayout::kFixedSize); + + iban_view->AddChildView(std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_IBAN_LABEL), + views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY)); + iban_view + ->AddChildView(std::make_unique<views::Label>( + GetIBANIdentifierString(), views::style::CONTEXT_LABEL, + views::style::STYLE_SECONDARY)) + ->SetHorizontalAlignment(gfx::ALIGN_LEFT); + iban_view->AddChildView(std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME), + views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY)); + nickname_textfield_ = + iban_view->AddChildView(std::make_unique<views::Textfield>()); + nickname_textfield_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME)); + nickname_textfield_->SetTextInputType( + ui::TextInputType::TEXT_INPUT_TYPE_TEXT); + nickname_textfield_->SetPlaceholderText( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_IBAN_PLACEHOLDER)); +} + +void SaveIbanBubbleView::AssignIdsToDialogButtonsForTesting() { + auto* ok_button = GetOkButton(); + if (ok_button) { + ok_button->SetID(DialogViewId::OK_BUTTON); + } + auto* cancel_button = GetCancelButton(); + if (cancel_button) { + cancel_button->SetID(DialogViewId::CANCEL_BUTTON); + } +} + +void SaveIbanBubbleView::OnDialogAccepted() { + if (controller_) { + DCHECK(nickname_textfield_); + controller_->OnSaveButton(nickname_textfield_->GetText()); + } +} + +void SaveIbanBubbleView::OnDialogCancelled() { + if (controller_) { + controller_->OnCancelButton(); + } +} + +void SaveIbanBubbleView::Init() { + CreateMainContentView(); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h new file mode 100644 index 0000000..40155192 --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h
@@ -0,0 +1,75 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_VIEW_H_ + +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/autofill/autofill_bubble_base.h" +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller.h" +#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" +#include "ui/views/controls/textfield/textfield.h" + +namespace content { +class WebContents; +} + +namespace autofill { + +// This class serves as a base view to any of the bubble views that are part of +// the flow for when the user submits a form with an IBAN (International Bank +// Account Number) value that Autofill has not previously saved. +class SaveIbanBubbleView : public AutofillBubbleBase, + public LocationBarBubbleDelegateView { + public: + // Bubble will be anchored to `anchor_view`. + SaveIbanBubbleView(views::View* anchor_view, + content::WebContents* web_contents, + SaveIbanBubbleController* controller); + + SaveIbanBubbleView(const SaveIbanBubbleView&) = delete; + SaveIbanBubbleView& operator=(const SaveIbanBubbleView&) = delete; + + void Show(DisplayReason reason); + + // Gets the masked IBAN value to be displayed to the user (e.g., + // CH56 **** **** **** *800 9). + std::u16string GetIBANIdentifierString(); + + // AutofillBubbleBase: + void Hide() override; + + // LocationBarBubbleDelegateView: + void AddedToWidget() override; + std::u16string GetWindowTitle() const override; + void WindowClosing() override; + + protected: + ~SaveIbanBubbleView() override; + + virtual void CreateMainContentView(); + + SaveIbanBubbleController* controller() const { return controller_; } + + // Attributes IDs to the dialog's DialogDelegate-supplied buttons. This is for + // testing purposes, which is needed when the browser tries to find the view + // by ID and clicks on it. + void AssignIdsToDialogButtonsForTesting(); + + void OnDialogAccepted(); + void OnDialogCancelled(); + + // LocationBarBubbleDelegateView: + void Init() override; + + private: + friend class SaveIbanBubbleViewFullFormBrowserTest; + + raw_ptr<views::Textfield> nickname_textfield_ = nullptr; + raw_ptr<SaveIbanBubbleController> controller_; +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_SAVE_IBAN_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view_uitest.cc b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view_uitest.cc new file mode 100644 index 0000000..b4439880 --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/save_iban_bubble_view_uitest.cc
@@ -0,0 +1,374 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_feature_list.h" +#include "build/build_config.h" +#include "chrome/browser/autofill/autofill_uitest_util.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/ui/autofill/payments/save_iban_bubble_controller_impl.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h" +#include "chrome/browser/ui/views/autofill/payments/save_iban_bubble_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/test_autofill_manager_injector.h" +#include "components/autofill/core/browser/browser_autofill_manager.h" +#include "components/autofill/core/browser/form_data_importer.h" +#include "components/autofill/core/browser/payments/iban_save_manager.h" +#include "components/autofill/core/browser/payments/iban_save_strike_database.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/strike_database_integrator_base.h" +#include "components/autofill/core/browser/test_autofill_manager_waiter.h" +#include "components/autofill/core/browser/test_event_waiter.h" +#include "components/autofill/core/common/autofill_payments_features.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/test_navigation_observer.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/events/base_event_utils.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/widget.h" + +namespace { +const char kIbanForm[] = "/autofill_iban_form.html"; +constexpr char kIbanValue[] = "DE91 1000 0000 0123 4567 89"; +} // namespace + +namespace autofill { + +class SaveIbanBubbleViewFullFormBrowserTest + : public SyncTest, + public IBANSaveManager::ObserverForTest, + public SaveIbanBubbleControllerImpl::ObserverForTest { + protected: + SaveIbanBubbleViewFullFormBrowserTest() : SyncTest(SINGLE_CLIENT) { + feature_list_.InitWithFeatures( + /*enabled_features=*/{autofill::features::kAutofillFillIbanFields, + autofill::features::kAutofillParseIBANFields}, + /*disabled_features=*/{}); + } + + public: + SaveIbanBubbleViewFullFormBrowserTest( + const SaveIbanBubbleViewFullFormBrowserTest&) = delete; + SaveIbanBubbleViewFullFormBrowserTest& operator=( + const SaveIbanBubbleViewFullFormBrowserTest&) = delete; + ~SaveIbanBubbleViewFullFormBrowserTest() override = default; + + protected: + class TestAutofillManager : public BrowserAutofillManager { + public: + TestAutofillManager(ContentAutofillDriver* driver, AutofillClient* client) + : BrowserAutofillManager(driver, + client, + "en-US", + EnableDownloadManager(false)) {} + + testing::AssertionResult WaitForFormsSeen(int min_num_awaited_calls) { + return forms_seen_waiter_.Wait(min_num_awaited_calls); + } + + private: + TestAutofillManagerWaiter forms_seen_waiter_{ + *this, + {&AutofillManager::Observer::OnAfterFormsSeen}}; + }; + + // Various events that can be waited on by the DialogEventWaiter. + enum DialogEvent : int { + OFFERED_LOCAL_SAVE, + ACCEPT_SAVE_IBAN_COMPLETE, + DECLINE_SAVE_IBAN_COMPLETE, + BUBBLE_SHOWN, + }; + + // SyncTest::SetUpOnMainThread: + void SetUpOnMainThread() override { + SyncTest::SetUpOnMainThread(); + + // Set up the HTTPS server (uses the embedded_test_server). + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + embedded_test_server()->ServeFilesFromSourceDirectory( + "components/test/data/autofill"); + embedded_test_server()->StartAcceptingConnections(); + + ASSERT_TRUE(SetupClients()); + + // It's important to use the blank tab here and not some arbitrary page. + // This causes the RenderFrameHost to stay the same when navigating to the + // HTML pages in tests. Since ContentAutofillDriver is per RFH, the driver + // that this method starts observing will also be the one to notify later. + AddBlankTabAndShow(GetBrowser(0)); + autofill_manager_injector_ = + std::make_unique<TestAutofillManagerInjector<TestAutofillManager>>( + GetActiveWebContents()); + + // Wait for Personal Data Manager to be fully loaded to prevent that + // spurious notifications deceive the tests. + WaitForPersonalDataManagerToBeLoaded(GetProfile(0)); + + // Set up this class as the ObserverForTest implementation. + iban_save_manager_ = ContentAutofillDriver::GetForRenderFrameHost( + GetActiveWebContents()->GetPrimaryMainFrame()) + ->autofill_manager() + ->client() + ->GetFormDataImporter() + ->iban_save_manager_for_testing(); + iban_save_manager_->SetEventObserverForTesting(this); + AddEventObserverToController(); + } + + // The primary main frame's AutofillManager. + TestAutofillManager* GetAutofillManager() { + DCHECK(autofill_manager_injector_); + return autofill_manager_injector_->GetForPrimaryMainFrame(); + } + + // IBANSaveManager::ObserverForTest: + void OnOfferLocalSave() override { + if (event_waiter_) { + event_waiter_->OnEvent(DialogEvent::OFFERED_LOCAL_SAVE); + } + } + + // IBANSaveManager::ObserverForTest: + void OnAcceptSaveIbanComplete() override { + if (event_waiter_) { + event_waiter_->OnEvent(DialogEvent::ACCEPT_SAVE_IBAN_COMPLETE); + } + } + + // IBANSaveManager::ObserverForTest: + void OnDeclineSaveIbanComplete() override { + if (event_waiter_) { + event_waiter_->OnEvent(DialogEvent::DECLINE_SAVE_IBAN_COMPLETE); + } + } + + // SaveIbanBubbleControllerImpl::ObserverForTest: + void OnBubbleShown() override { + if (event_waiter_) { + event_waiter_->OnEvent(DialogEvent::BUBBLE_SHOWN); + } + } + + void NavigateToAndWaitForForm(const std::string& file_path) { + ASSERT_TRUE(ui_test_utils::NavigateToURL( + GetBrowser(0), embedded_test_server()->GetURL(file_path))); + ASSERT_TRUE(GetAutofillManager()->WaitForFormsSeen(1)); + } + + void SubmitFormAndWaitForIbanLocalSaveBubble() { + ResetEventWaiterForSequence( + {DialogEvent::OFFERED_LOCAL_SAVE, DialogEvent::BUBBLE_SHOWN}); + SubmitForm(); + WaitForObservedEvent(); + EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL) + ->GetVisible()); + } + + void SubmitForm() { + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_submit_button_js = + "(function() { document.getElementById('submit').click(); })();"; + content::TestNavigationObserver nav_observer(web_contents); + ASSERT_TRUE(content::ExecuteScript(web_contents, click_submit_button_js)); + nav_observer.Wait(); + } + + // Should be called for autofill_iban_form.html. + void FillForm(absl::optional<std::string> iban_value = absl::nullopt) { + NavigateToAndWaitForForm(kIbanForm); + content::WebContents* web_contents = GetActiveWebContents(); + const std::string click_fill_button_js = + "(function() { document.getElementById('fill_form').click(); })();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, click_fill_button_js)); + + if (iban_value.has_value()) { + std::string set_value_js = + "(function() { document.getElementById('iban').value ='" + + iban_value.value() + "';})();"; + ASSERT_TRUE(content::ExecuteScript(web_contents, set_value_js)); + } + } + + views::View* FindViewInBubbleById(DialogViewId view_id) { + SaveIbanBubbleView* save_iban_bubble_views = GetSaveIbanBubbleView(); + CHECK(save_iban_bubble_views); + + views::View* specified_view = + save_iban_bubble_views->GetViewByID(static_cast<int>(view_id)); + + if (!specified_view) { + // Many of the save IBAN bubble's inner Views are not child views but + // rather contained by the dialog. If we didn't find what we were looking + // for, check there as well. + specified_view = + save_iban_bubble_views->GetWidget()->GetRootView()->GetViewByID( + static_cast<int>(view_id)); + } + + return specified_view; + } + + void ClickOnSaveButton() { + SaveIbanBubbleView* save_iban_bubble_views = GetSaveIbanBubbleView(); + CHECK(save_iban_bubble_views); + ClickOnDialogViewAndWaitForWidgetDestruction( + FindViewInBubbleById(DialogViewId::OK_BUTTON)); + } + + void ClickOnCancelButton() { + SaveIbanBubbleView* save_iban_bubble_views = GetSaveIbanBubbleView(); + CHECK(save_iban_bubble_views); + ClickOnDialogViewAndWaitForWidgetDestruction( + FindViewInBubbleById(DialogViewId::CANCEL_BUTTON)); + } + + SaveIbanBubbleView* GetSaveIbanBubbleView() { + SaveIbanBubbleController* save_iban_bubble_controller = + SaveIbanBubbleController::GetOrCreate(GetActiveWebContents()); + if (!save_iban_bubble_controller) { + return nullptr; + } + + AutofillBubbleBase* save_iban_bubble_view = + save_iban_bubble_controller->GetSaveBubbleView(); + if (!save_iban_bubble_view) { + return nullptr; + } + + return static_cast<SaveIbanBubbleView*>(save_iban_bubble_view); + } + + content::WebContents* GetActiveWebContents() { + return GetBrowser(0)->tab_strip_model()->GetActiveWebContents(); + } + + void AddEventObserverToController() { + SaveIbanBubbleControllerImpl* save_iban_bubble_controller_impl = + static_cast<SaveIbanBubbleControllerImpl*>( + SaveIbanBubbleController::GetOrCreate(GetActiveWebContents())); + CHECK(save_iban_bubble_controller_impl); + save_iban_bubble_controller_impl->SetEventObserverForTesting(this); + } + + void ResetEventWaiterForSequence(std::list<DialogEvent> event_sequence) { + event_waiter_ = + std::make_unique<EventWaiter<DialogEvent>>(std::move(event_sequence)); + } + + void ClickOnView(views::View* view) { + CHECK(view); + ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + view->OnMousePressed(pressed); + ui::MouseEvent released_event = + ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + view->OnMouseReleased(released_event); + } + + void ClickOnDialogView(views::View* view) { + GetSaveIbanBubbleView()->ResetViewShownTimeStampForTesting(); + views::BubbleFrameView* bubble_frame_view = + static_cast<views::BubbleFrameView*>(GetSaveIbanBubbleView() + ->GetWidget() + ->non_client_view() + ->frame_view()); + bubble_frame_view->ResetViewShownTimeStampForTesting(); + ClickOnView(view); + } + + void ClickOnDialogViewAndWaitForWidgetDestruction(views::View* view) { + EXPECT_TRUE(GetSaveIbanBubbleView()); + views::test::WidgetDestroyedWaiter destroyed_waiter( + GetSaveIbanBubbleView()->GetWidget()); + ClickOnDialogView(view); + destroyed_waiter.Wait(); + EXPECT_FALSE(GetSaveIbanBubbleView()); + } + + void WaitForObservedEvent() { event_waiter_->Wait(); } + + raw_ptr<IBANSaveManager, DanglingUntriaged> iban_save_manager_ = nullptr; + + private: + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<autofill::EventWaiter<DialogEvent>> event_waiter_; + std::unique_ptr<TestAutofillManagerInjector<TestAutofillManager>> + autofill_manager_injector_; +}; + +// Tests the local save bubble. Ensures that clicking the 'No thanks' button +// successfully causes the bubble to go away, and causes a strike to be added. +IN_PROC_BROWSER_TEST_F(SaveIbanBubbleViewFullFormBrowserTest, + Local_ClickingNoThanksClosesBubble) { + FillForm(kIbanValue); + SubmitFormAndWaitForIbanLocalSaveBubble(); + + // Clicking 'No thanks' should cancel and close it. + ResetEventWaiterForSequence({DialogEvent::DECLINE_SAVE_IBAN_COMPLETE}); + ClickOnCancelButton(); + WaitForObservedEvent(); + + EXPECT_FALSE(GetSaveIbanBubbleView()); + EXPECT_EQ( + 1, iban_save_manager_->GetIBANSaveStrikeDatabaseForTesting()->GetStrikes( + kIbanValue)); +} + +// Tests overall StrikeDatabase interaction with the local save bubble. Runs an +// example of declining the prompt max times and ensuring that the +// offer-to-save bubble does not appear on the next try. Then, ensures that no +// strikes are added if the IBAN already has max strikes. +IN_PROC_BROWSER_TEST_F(SaveIbanBubbleViewFullFormBrowserTest, + StrikeDatabase_Local_FullFlowTest) { + // Show and ignore the bubble enough times in order to accrue maximum strikes. + for (int i = 0; i < iban_save_manager_->GetIBANSaveStrikeDatabaseForTesting() + ->GetMaxStrikesLimit(); + ++i) { + FillForm(kIbanValue); + SubmitFormAndWaitForIbanLocalSaveBubble(); + + ResetEventWaiterForSequence({DialogEvent::DECLINE_SAVE_IBAN_COMPLETE}); + ClickOnCancelButton(); + WaitForObservedEvent(); + } + EXPECT_EQ( + iban_save_manager_->GetIBANSaveStrikeDatabaseForTesting()->GetStrikes( + kIbanValue), + iban_save_manager_->GetIBANSaveStrikeDatabaseForTesting() + ->GetMaxStrikesLimit()); + // Submit the form a fourth time. Since the IBAN now has maximum strikes, + // the bubble should not be shown. + FillForm(kIbanValue); + ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE}); + SubmitForm(); + WaitForObservedEvent(); + + EXPECT_TRUE(iban_save_manager_->GetIBANSaveStrikeDatabaseForTesting() + ->ShouldBlockFeature(kIbanValue)); + EXPECT_FALSE(GetSaveIbanBubbleView()); +} + +// Tests the local save bubble. Ensures that clicking the 'Save' button +// successfully causes the bubble to go away. +IN_PROC_BROWSER_TEST_F(SaveIbanBubbleViewFullFormBrowserTest, + Local_ClickingSaveClosesBubble) { + FillForm(); + SubmitFormAndWaitForIbanLocalSaveBubble(); + + ResetEventWaiterForSequence({DialogEvent::ACCEPT_SAVE_IBAN_COMPLETE}); + ClickOnSaveButton(); + WaitForObservedEvent(); + + EXPECT_FALSE(GetSaveIbanBubbleView()); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_coordinator.cc b/chrome/browser/ui/views/extensions/extensions_menu_coordinator.cc index 15c1cc2f..8395034 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_coordinator.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_coordinator.cc
@@ -26,25 +26,9 @@ ExtensionsContainer* extensions_container) { DCHECK(base::FeatureList::IsEnabled( extensions_features::kExtensionsMenuAccessControl)); - auto bubble_delegate = std::make_unique<views::BubbleDialogDelegate>( - anchor_view, views::BubbleBorder::TOP_RIGHT); - bubble_delegate->set_margins(gfx::Insets(0)); - bubble_delegate->set_fixed_width( - views::LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); - // Let anchor view's MenuButtonController handle the highlight. - bubble_delegate->set_highlight_button_when_shown(false); - bubble_delegate->SetButtons(ui::DIALOG_BUTTON_NONE); - bubble_delegate->SetEnableArrowKeyTraversal(true); - - auto* bubble_contents = bubble_delegate->SetContentsView( - views::Builder<views::View>().SetUseDefaultFillLayout(true).Build()); - bubble_contents->View::AddObserver(this); - bubble_tracker_.SetView(bubble_contents); - - controller_ = std::make_unique<ExtensionsMenuViewController>( - browser_, extensions_container, bubble_contents, bubble_delegate.get()); - controller_->OpenMainPage(); + std::unique_ptr<views::BubbleDialogDelegate> bubble_delegate = + CreateExtensionsMenuBubbleDialogDelegate(anchor_view, + extensions_container); views::BubbleDialogDelegate::CreateBubble(std::move(bubble_delegate))->Show(); } @@ -69,6 +53,43 @@ return IsShowing() ? bubble_tracker_.view()->GetWidget() : nullptr; } +std::unique_ptr<views::BubbleDialogDelegate> +ExtensionsMenuCoordinator::CreateExtensionsMenuBubbleDialogDelegateForTesting( + views::View* anchor_view, + ExtensionsContainer* extensions_container) { + return CreateExtensionsMenuBubbleDialogDelegate(anchor_view, + extensions_container); +} + +std::unique_ptr<views::BubbleDialogDelegate> +ExtensionsMenuCoordinator::CreateExtensionsMenuBubbleDialogDelegate( + views::View* anchor_view, + ExtensionsContainer* extensions_container) { + DCHECK(base::FeatureList::IsEnabled( + extensions_features::kExtensionsMenuAccessControl)); + auto bubble_delegate = std::make_unique<views::BubbleDialogDelegate>( + anchor_view, views::BubbleBorder::TOP_RIGHT); + bubble_delegate->set_margins(gfx::Insets(0)); + bubble_delegate->set_fixed_width( + views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); + // Let anchor view's MenuButtonController handle the highlight. + bubble_delegate->set_highlight_button_when_shown(false); + bubble_delegate->SetButtons(ui::DIALOG_BUTTON_NONE); + bubble_delegate->SetEnableArrowKeyTraversal(true); + + auto* bubble_contents = bubble_delegate->SetContentsView( + views::Builder<views::View>().SetUseDefaultFillLayout(true).Build()); + bubble_contents->View::AddObserver(this); + bubble_tracker_.SetView(bubble_contents); + + controller_ = std::make_unique<ExtensionsMenuViewController>( + browser_, extensions_container, bubble_contents, bubble_delegate.get()); + controller_->OpenMainPage(); + + return bubble_delegate; +} + void ExtensionsMenuCoordinator::OnViewIsDeleting(views::View* observed_view) { // Reset the controller to keep 1:1 lifetime with the view. controller_.reset();
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_coordinator.h b/chrome/browser/ui/views/extensions/extensions_menu_coordinator.h index 11a36a7..4b2a7c0 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_coordinator.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_coordinator.h
@@ -12,6 +12,10 @@ class ExtensionsMenuViewController; class ExtensionsContainer; +namespace views { +class BubbleDialogDelegate; +} + // Handles the lifetime and showing/hidden state of the extensions menu bubble. class ExtensionsMenuCoordinator : public views::ViewObserver { public: @@ -38,8 +42,18 @@ ExtensionsMenuViewController* GetControllerForTesting() { return controller_.get(); } + std::unique_ptr<views::BubbleDialogDelegate> + CreateExtensionsMenuBubbleDialogDelegateForTesting( + views::View* anchor_view, + ExtensionsContainer* extensions_container); private: + // Creates the bubble contents and returns its delegate. + std::unique_ptr<views::BubbleDialogDelegate> + CreateExtensionsMenuBubbleDialogDelegate( + views::View* anchor_view, + ExtensionsContainer* extensions_container); + // views::ViewObserver void OnViewIsDeleting(views::View* observed_view) override;
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc b/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc index 15ea6534..c49ffd78 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_test_util.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/ui/views/extensions/extensions_menu_test_util.h" +#include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/numerics/safe_conversions.h" @@ -13,12 +14,17 @@ #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" #include "chrome/browser/ui/views/extensions/extension_popup.h" #include "chrome/browser/ui/views/extensions/extensions_menu_button.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_coordinator.h" #include "chrome/browser/ui/views/extensions/extensions_menu_item_view.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_page_view.h" #include "chrome/browser/ui/views/extensions/extensions_menu_view.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_view_controller.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "extensions/common/extension_features.h" #include "ui/events/base_event_utils.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -30,6 +36,7 @@ #include "ui/views/test/button_test_api.h" #include "ui/views/view.h" #include "ui/views/view_observer.h" +#include "ui/views/view_utils.h" class ExtensionsMenuTestUtil::MenuViewObserver : public views::ViewObserver { public: @@ -74,8 +81,7 @@ bool is_real_window) : scoped_allow_extensions_menu_instances_( ExtensionsMenuView::AllowInstancesForTesting()), - browser_(browser), - menu_view_observer_(std::make_unique<MenuViewObserver>(&menu_view_)) { + browser_(browser) { if (is_real_window) { extensions_container_ = BrowserView::GetBrowserViewForBrowser(browser_) ->toolbar() @@ -84,27 +90,43 @@ wrapper_ = std::make_unique<Wrapper>(browser); extensions_container_ = wrapper_->extensions_container(); } - owned_menu_view_ = std::make_unique<ExtensionsMenuView>( - extensions_container_->GetExtensionsButton(), browser_, - extensions_container_); - menu_view_ = owned_menu_view_.get(); - // The static_cast is needed to disambiguate between View::AddObserver and - // DialogDelegate::AddObserver. - static_cast<views::View*>(menu_view_)->AddObserver(menu_view_observer_.get()); - if (is_real_window) - views::BubbleDialogDelegateView::CreateBubble(std::move(owned_menu_view_)); -} -ExtensionsMenuTestUtil::~ExtensionsMenuTestUtil() { - if (!owned_menu_view_ && menu_view_) { - // If we don't own menu_view_, a widget owns menu_view_. - menu_view_->GetWidget()->CloseNow(); - DCHECK_EQ(menu_view_, nullptr); + std::unique_ptr<views::BubbleDialogDelegate> bubble_dialog; + if (base::FeatureList::IsEnabled( + extensions_features::kExtensionsMenuAccessControl)) { + bubble_dialog = + extensions_container_->GetExtensionsMenuCoordinatorForTesting() + ->CreateExtensionsMenuBubbleDialogDelegateForTesting( + extensions_container_->GetExtensionsButton(), + extensions_container_); + } else { + bubble_dialog = std::make_unique<ExtensionsMenuView>( + extensions_container_->GetExtensionsButton(), browser_, + extensions_container_); + menu_view_ = views::AsViewClass<ExtensionsMenuView>( + bubble_dialog->GetContentsView()); + + menu_view_observer_ = std::make_unique<MenuViewObserver>(&menu_view_); + static_cast<views::View*>(menu_view_) + ->AddObserver(menu_view_observer_.get()); + } + + if (is_real_window) { + views::BubbleDialogDelegate::CreateBubble(std::move(bubble_dialog)); } } +ExtensionsMenuTestUtil::~ExtensionsMenuTestUtil() { + if (!menu_view_) { + return; + } + + // Close the menu if when we own the menu view. + menu_view_->GetWidget()->CloseNow(); +} + int ExtensionsMenuTestUtil::NumberOfBrowserActions() { - return menu_view_->extensions_menu_items_for_testing().size(); + return extensions_container_->GetNumberOfActionsForTesting(); } int ExtensionsMenuTestUtil::VisibleBrowserActions() { @@ -121,10 +143,10 @@ } void ExtensionsMenuTestUtil::InspectPopup(const extensions::ExtensionId& id) { - InstalledExtensionMenuItemView* view = GetMenuItemViewForId(id); - DCHECK(view); - static_cast<ExtensionActionViewController*>(view->view_controller()) - ->InspectPopup(); + auto* view_controller = static_cast<ExtensionActionViewController*>( + extensions_container_->GetActionForId(id)); + DCHECK(view_controller); + view_controller->InspectPopup(); } bool ExtensionsMenuTestUtil::HasIcon(const extensions::ExtensionId& id) { @@ -215,14 +237,25 @@ InstalledExtensionMenuItemView* ExtensionsMenuTestUtil::GetMenuItemViewForId( const extensions::ExtensionId& id) { - auto menu_items = menu_view_->extensions_menu_items_for_testing(); + base::flat_set<InstalledExtensionMenuItemView*> menu_items; + if (base::FeatureList::IsEnabled( + extensions_features::kExtensionsMenuAccessControl)) { + ExtensionsMenuMainPageView* main_page = + extensions_container_->GetExtensionsMenuCoordinatorForTesting() + ->GetControllerForTesting() + ->GetMainPageViewForTesting(); + DCHECK(main_page); + menu_items = main_page->GetMenuItemsForTesting(); + + } else { + menu_items = menu_view_->extensions_menu_items_for_testing(); + } + auto iter = base::ranges::find(menu_items, id, [](InstalledExtensionMenuItemView* view) { return view->view_controller()->GetId(); }); - if (iter == menu_items.end()) - return nullptr; - return *iter; + return (iter == menu_items.end()) ? nullptr : *iter; } // static
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_test_util.h b/chrome/browser/ui/views/extensions/extensions_menu_test_util.h index 8797d3de..2e6467e 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_test_util.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_test_util.h
@@ -66,14 +66,10 @@ raw_ptr<ExtensionsToolbarContainer, DanglingUntriaged> extensions_container_ = nullptr; - // Helps make sure that |menu_view_| set to null when destroyed by the widget - // or via manual means. + // Helps make sure that `menu_view_`, if existent, is set to null when + // destroyed by the widget or via manual means. std::unique_ptr<MenuViewObserver> menu_view_observer_; - // The owned version of |menu_view_|. Strongly prefer using |menu_view_|. May - // be null when ownership is conditionally transferred to the bubble. - std::unique_ptr<ExtensionsMenuView> owned_menu_view_; - // The actual pointer to an ExtensionsMenuView, non-null if alive. // This field is not a raw_ptr<> because it was filtered by the rewriter for: // #addr-of
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h index a3de7d3..8d61cb7b 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.h +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.h
@@ -120,6 +120,8 @@ return extension_with_open_context_menu_id_; } + int GetNumberOfActionsForTesting() { return actions_.size(); } + // Updates the flex layout rules for the extension toolbar container to have // views::MinimumFlexSizeRule::kPreferred when WindowControlsOverlay (WCO) is // toggled on for PWAs. Otherwise the extensions icon does not stay visible as
diff --git a/chrome/browser/ui/views/file_system_access/file_system_access_browsertest.cc b/chrome/browser/ui/views/file_system_access/file_system_access_browsertest.cc index cf51d279..451d51a 100644 --- a/chrome/browser/ui/views/file_system_access/file_system_access_browsertest.cc +++ b/chrome/browser/ui/views/file_system_access/file_system_access_browsertest.cc
@@ -964,8 +964,9 @@ BackForwardCacheFileSystemAccessBrowserTest() { // Enable BackForwardCache. feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index 82a7a7e..f278692 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -169,13 +169,6 @@ : ui::kColorFrameInactive); } -void BrowserNonClientFrameView::UpdateFrameColor() { - // Only web-app windows support dynamic frame colors set by HTML meta tags. - if (web_app_frame_toolbar_) - web_app_frame_toolbar_->UpdateCaptionColors(); - SchedulePaint(); -} - absl::optional<int> BrowserNonClientFrameView::GetCustomBackgroundId( BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); @@ -203,16 +196,6 @@ void BrowserNonClientFrameView::UpdateMinimumSize() {} -void BrowserNonClientFrameView::SetWindowControlsOverlayToggleVisible( - bool visible) { - DCHECK(browser_view_->AppUsesWindowControlsOverlay()); - web_app_frame_toolbar_->SetWindowControlsOverlayToggleVisible(visible); -} - -void BrowserNonClientFrameView::UpdateBorderlessModeEnabled() { - web_app_frame_toolbar_->UpdateBorderlessModeEnabled(); -} - void BrowserNonClientFrameView::Layout() { // BrowserView updates most UI visibility on layout based on fullscreen // state. However, it doesn't have access to |web_app_frame_toolbar_|. Do @@ -245,11 +228,6 @@ return HTNOWHERE; } -void BrowserNonClientFrameView::ResetWindowControls() { - if (web_app_frame_toolbar_) - web_app_frame_toolbar_->UpdateStatusIconsVisibility(); -} - TabSearchBubbleHost* BrowserNonClientFrameView::GetTabSearchBubbleHost() { return nullptr; } @@ -274,9 +252,6 @@ } void BrowserNonClientFrameView::PaintAsActiveChanged() { - if (web_app_frame_toolbar_) - web_app_frame_toolbar_->SetPaintAsActive(ShouldPaintAsActive()); - // Changing the activation state may change the visible frame color. SchedulePaint(); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index d3279ce..3795946 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -105,10 +105,6 @@ // tabstrip background. virtual SkColor GetFrameColor(BrowserFrameActiveState active_state) const; - // Called by BrowserView to signal the frame color has changed and needs - // to be repainted. - virtual void UpdateFrameColor(); - // For non-transparent windows, returns the background tab image resource ID // if the image has been customized, directly or indirectly, by the theme. absl::optional<int> GetCustomBackgroundId( @@ -124,24 +120,27 @@ // or disabled. virtual void WindowControlsOverlayEnabledChanged() {} - // Set the visibility of the window controls overlay toggle button. - void SetWindowControlsOverlayToggleVisible(bool visible); - - // Updates the visibility of the title bar based on the visibility of the - // borderless mode. - void UpdateBorderlessModeEnabled(); - // views::NonClientFrameView: using views::NonClientFrameView::ShouldPaintAsActive; void Layout() override; void VisibilityChanged(views::View* starting_from, bool is_visible) override; int NonClientHitTest(const gfx::Point& point) override; - void ResetWindowControls() override; WebAppFrameToolbarView* web_app_frame_toolbar_for_testing() { return web_app_frame_toolbar_; } + // TODO(https://crbug.com/1407240): Remove these methods (and all other + // WebAppFrameToolbarView access/usage) from this class once work to refactor + // ownership has been completed. + WebAppFrameToolbarView* web_app_frame_toolbar(base::PassKey<BrowserView>) { + return web_app_frame_toolbar_; + } + const WebAppFrameToolbarView* web_app_frame_toolbar( + base::PassKey<BrowserView>) const { + return web_app_frame_toolbar_; + } + // Gets the TabSearchBubbleHost if present in the NonClientFrameView. Can // return null. virtual TabSearchBubbleHost* GetTabSearchBubbleHost();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc index cff211a..db4dd88 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc
@@ -251,11 +251,6 @@ return BrowserFrameHeaderChromeOS::GetThemeBackgroundXInset(); } -void BrowserNonClientFrameViewChromeOS::UpdateFrameColor() { - OnUpdateFrameColor(); - BrowserNonClientFrameView::UpdateFrameColor(); -} - void BrowserNonClientFrameViewChromeOS::UpdateThrobber(bool running) { if (window_icon_) window_icon_->Update(); @@ -379,7 +374,6 @@ void BrowserNonClientFrameViewChromeOS::WindowControlsOverlayEnabledChanged() { bool enabled = browser_view()->IsWindowControlsOverlayEnabled(); - web_app_frame_toolbar()->OnWindowControlsOverlayEnabledChanged(); caption_button_container_->OnWindowControlsOverlayEnabledChanged( enabled, GetFrameHeaderColor(browser_view()->IsActive())); browser_view()->InvalidateLayout(); @@ -693,6 +687,11 @@ } if (key == chromeos::kWindowStateTypeKey) { + // Update window controls when window state changes as whether or not these + // are shown can depend on the window state (e.g. hiding the caption buttons + // in non-immersive full screen mode, see crbug.com/1336470). + ResetWindowControls(); + // Update the window controls if we are entering or exiting float state. const bool enter_floated = IsFloated(); const bool exit_floated = static_cast<chromeos::WindowStateType>(old) == @@ -702,7 +701,6 @@ if (frame_header_) frame_header_->OnFloatStateChanged(); - ResetWindowControls(); if (!chromeos::TabletState::Get()->InTabletMode()) return; @@ -819,17 +817,31 @@ } bool BrowserNonClientFrameViewChromeOS::GetShowCaptionButtons() const { - return GetShowCaptionButtonsWhenNotInOverview() && !GetOverviewMode() && - !GetHideCaptionButtonsForFullscreen() && !UseWebUITabStrip(); + if (GetOverviewMode()) { + return false; + } + + return GetShowCaptionButtonsWhenNotInOverview(); } bool BrowserNonClientFrameViewChromeOS::GetShowCaptionButtonsWhenNotInOverview() const { - if (UsePackagedAppHeaderStyle(browser_view()->browser())) + if (GetHideCaptionButtonsForFullscreen()) { + return false; + } + + // Show the caption buttons for packaged apps which support immersive mode. + if (UsePackagedAppHeaderStyle(browser_view()->browser())) { return true; - if (!chromeos::TabletState::Get()->InTabletMode()) - return true; - return IsFloated(); + } + + // Browsers in tablet mode still show their caption buttons in float state, + // even with the webUI tab strip. + if (chromeos::TabletState::Get()->InTabletMode()) { + return IsFloated(); + } + + return !UseWebUITabStrip(); } int BrowserNonClientFrameViewChromeOS::GetToolbarLeftInset() const {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h index e8ec2154..8aade78 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h
@@ -60,7 +60,6 @@ const gfx::Size& tabstrip_minimum_size) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; - void UpdateFrameColor() override; void UpdateThrobber(bool running) override; bool CanUserExitFullscreen() const override; SkColor GetCaptionColor(BrowserFrameActiveState active_state) const override; @@ -120,8 +119,7 @@ void OnImmersiveRevealEnded() override; void OnImmersiveFullscreenExited() override; - chromeos::FrameCaptionButtonContainerView* - caption_button_container_for_testing() { + chromeos::FrameCaptionButtonContainerView* caption_button_container() { return caption_button_container_; } @@ -155,7 +153,9 @@ FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewChromeOSTest, RestoreMinimizedBrowserUpdatesCaption); FRIEND_TEST_ALL_PREFIXES(FloatBrowserNonClientFrameViewChromeOSTest, - AppHeaderVisibilityInTabletModeTest); + BrowserHeaderVisibilityInTabletModeTest); + FRIEND_TEST_ALL_PREFIXES(FloatBrowserNonClientFrameViewChromeOSTest, + BrowserAppHeaderVisibilityInTabletModeTest); FRIEND_TEST_ALL_PREFIXES(ImmersiveModeControllerChromeosWebAppBrowserTest, FrameLayoutToggleTabletMode); FRIEND_TEST_ALL_PREFIXES(HomeLauncherBrowserNonClientFrameViewChromeOSTest, @@ -174,17 +174,14 @@ bool AppIsBorderlessPwa(); - // Returns true if GetShowCaptionButtonsWhenNotInOverview() returns true - // and this browser window is not showing in overview or in fullscreen mode. + // Returns true if `GetShowCaptionButtonsWhenNotInOverview()` returns true + // and this browser window is not showing in overview. bool GetShowCaptionButtons() const; - // In tablet mode, to prevent accidental taps of the window controls, and to - // give more horizontal space for tabs and the new tab button (especially in - // split view), we hide the window controls even when this browser window is - // not showing in overview. We only do this when the Home Launcher feature is - // enabled, because it gives the user the ability to minimize all windows when - // pressing the Launcher button on the shelf. So, this function returns true - // if the Home Launcher feature is disabled or we are in clamshell mode. + // Returns whether we should show caption buttons. False for fullscreen, + // tablet mode and webUI tab strip in most cases. The exceptions are if this + // is a packaged app, as they have immersive mode enabled, and floated windows + // in tablet mode. bool GetShowCaptionButtonsWhenNotInOverview() const; // Distance between the edge of the NonClientFrameView and the web app frame
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc index c4d80dfa..04528a8 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
@@ -25,6 +25,7 @@ #include "chromeos/constants/chromeos_features.h" #include "chromeos/ui/base/window_properties.h" #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h" +#include "chromeos/ui/frame/caption_buttons/frame_size_button.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" #include "content/public/test/browser_test.h" @@ -471,7 +472,6 @@ EXPECT_TRUE(frame_view->GetShouldPaint()); } -#if BUILDFLAG(IS_CHROMEOS_ASH) // Tests that caption buttons are hidden when entering tab fullscreen. IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTestNoWebUiTabStrip, CaptionButtonsHiddenNonImmersiveFullscreen) { @@ -494,6 +494,7 @@ EXPECT_TRUE(frame_view->caption_button_container_->GetVisible()); } +#if BUILDFLAG(IS_CHROMEOS_ASH) // Tests that Avatar icon should show on the top left corner of the teleported // browser window on ChromeOS. // TODO(http://crbug.com/1059514): This test should be made to work with the @@ -554,12 +555,10 @@ auto* frame_view = GetFrameViewChromeOS(browser_view); if (ui::TouchUiController::Get()->touch_ui()) { EXPECT_TRUE(browser_view->webui_tab_strip()); - EXPECT_FALSE( - frame_view->caption_button_container_for_testing()->GetVisible()); + EXPECT_FALSE(frame_view->caption_button_container()->GetVisible()); } else { EXPECT_FALSE(browser_view->webui_tab_strip()); - EXPECT_TRUE( - frame_view->caption_button_container_for_testing()->GetVisible()); + EXPECT_TRUE(frame_view->caption_button_container()->GetVisible()); } } @@ -1277,10 +1276,39 @@ chromeos::wm::features::kFloatWindow}; }; +IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, + BrowserHeaderVisibilityInTabletModeTest) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + BrowserNonClientFrameViewChromeOS* frame_view = + GetFrameViewChromeOS(browser_view); + + ASSERT_NO_FATAL_FAILURE( + ash::ShellTestApi().SetTabletModeEnabledForTest(true)); + EXPECT_FALSE(frame_view->caption_button_container_->GetVisible()); + + Widget* widget = browser_view->GetWidget(); + auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get( + views::Widget::GetWidgetForNativeView(widget->GetNativeWindow())); + + // Snap a window. No immersive mode from regular browsers. + ash::SplitViewTestApi().SnapWindow( + widget->GetNativeWindow(), ash::SplitViewTestApi::SnapPosition::RIGHT); + EXPECT_FALSE(frame_view->caption_button_container_->GetVisible()); + EXPECT_FALSE(immersive_controller->IsEnabled()); + + // Float the window; the title bar is visible. + ui::test::EventGenerator event_generator( + widget->GetNativeWindow()->GetRootWindow()); + event_generator.PressAndReleaseKey(ui::VKEY_F, + ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN); + EXPECT_TRUE(frame_view->caption_button_container_->GetVisible()); + EXPECT_FALSE(immersive_controller->IsEnabled()); +} + // Test that for a browser app window, its caption buttons may or may not hide // in tablet mode. IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, - AppHeaderVisibilityInTabletModeTest) { + BrowserAppHeaderVisibilityInTabletModeTest) { // Create a browser app window. Browser::CreateParams params = Browser::CreateParams::CreateForApp( "test_browser_app", /*trusted_source=*/true, gfx::Rect(), @@ -1296,6 +1324,7 @@ aura::client::kResizeBehaviorKey, aura::client::kResizeBehaviorCanMaximize | aura::client::kResizeBehaviorCanResize); + StartOverview(); EXPECT_FALSE(frame_view2->caption_button_container_->GetVisible()); EndOverview(); @@ -1327,6 +1356,31 @@ EXPECT_FALSE(immersive_controller->IsEnabled()); } +#if BUILDFLAG(IS_CHROMEOS) +// Tests that, with the float flag enabled, the accelerator toggles the +// multitask menu on a browser window. +IN_PROC_BROWSER_TEST_P(FloatBrowserNonClientFrameViewChromeOSTest, + ToggleMultitaskMenu) { + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_TOGGLE_MULTITASK_MENU)); + + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); + BrowserNonClientFrameViewChromeOS* frame_view = + GetFrameViewChromeOS(browser_view); + auto* size_button = static_cast<chromeos::FrameSizeButton*>( + frame_view->caption_button_container()->size_button()); + + // Pressing accelerator once should show the multitask menu. + ui::test::EventGenerator event_generator( + browser_view->GetWidget()->GetNativeWindow()->GetRootWindow()); + event_generator.PressAndReleaseKey(ui::VKEY_Z, ui::EF_COMMAND_DOWN); + ASSERT_TRUE(size_button->IsMultitaskMenuShown()); + + // Pressing accelerator a second time should close the menu. + event_generator.PressAndReleaseKey(ui::VKEY_Z, ui::EF_COMMAND_DOWN); + ASSERT_FALSE(size_button->IsMultitaskMenuShown()); +} +#endif + namespace { class HomeLauncherBrowserNonClientFrameViewChromeOSTest
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h index 9e68b488..9df6ea1 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
@@ -23,7 +23,6 @@ @class FullscreenToolbarController; class CaptionButtonPlaceholderContainer; -class WindowControlsOverlayInputRoutingMac; class BrowserNonClientFrameViewMac : public BrowserNonClientFrameView, public web_app::AppRegistrarObserver { @@ -48,7 +47,6 @@ bool ShouldHideTopUIForFullscreen() const override; void UpdateThrobber(bool running) override; void PaintAsActiveChanged() override; - void UpdateFrameColor() override; void OnThemeChanged() override; // views::NonClientFrameView: @@ -65,7 +63,6 @@ // views::View: gfx::Size GetMinimumSize() const override; - void AddedToWidget() override; void PaintChildren(const views::PaintInfo& info) override; // web_app::AppRegistrarObserver @@ -113,8 +110,6 @@ void UpdateCaptionButtonPlaceholderContainerBackground(); - void AddRoutingForWindowControlsOverlayViews(); - // Toggle the visibility of the web_app_frame_toolbar_view() for PWAs with // window controls overlay display override when entering full screen or when // toolbar style is changed. @@ -139,18 +134,6 @@ raw_ptr<CaptionButtonPlaceholderContainer> caption_button_placeholder_container_ = nullptr; - // PWAs with window controls overlay display override covers the browser - // window with WebContentsViewCocoa natively even if the views::view 'looks' - // right and so events end up in the client area. - // WindowControlsOverlayInputRoutingMac overlays a NSView the non client - // area so events can be routed to the right view in the non client area. Two - // separate WindowControlsOverlayInputRoutingMac instances are needed - // since there are two dis jointed areas of non client area. - std::unique_ptr<WindowControlsOverlayInputRoutingMac> - caption_buttons_overlay_input_routing_view_; - std::unique_ptr<WindowControlsOverlayInputRoutingMac> - web_app_frame_toolbar_overlay_routing_view_; - base::scoped_nsobject<FullscreenToolbarController> fullscreen_toolbar_controller_; };
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm index 856df00..49cde9a 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -24,7 +24,6 @@ #include "chrome/browser/ui/views/frame/browser_view_layout.h" #include "chrome/browser/ui/views/frame/caption_button_placeholder_container.h" #include "chrome/browser/ui/views/frame/tab_strip_region_view.h" -#include "chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_utils.h" @@ -92,8 +91,6 @@ if (browser_view->IsWindowControlsOverlayEnabled()) { caption_button_placeholder_container_ = AddChildView(std::make_unique<CaptionButtonPlaceholderContainer>()); - - AddRoutingForWindowControlsOverlayViews(); } } @@ -305,11 +302,6 @@ BrowserNonClientFrameView::PaintAsActiveChanged(); } -void BrowserNonClientFrameViewMac::UpdateFrameColor() { - UpdateCaptionButtonPlaceholderContainerBackground(); - BrowserNonClientFrameView::UpdateFrameColor(); -} - void BrowserNonClientFrameViewMac::OnThemeChanged() { UpdateCaptionButtonPlaceholderContainerBackground(); BrowserNonClientFrameView::OnThemeChanged(); @@ -390,23 +382,11 @@ caption_button_placeholder_container_ = AddChildView(std::make_unique<CaptionButtonPlaceholderContainer>()); UpdateCaptionButtonPlaceholderContainerBackground(); - - AddRoutingForWindowControlsOverlayViews(); - - caption_buttons_overlay_input_routing_view_->Enable(); - web_app_frame_toolbar_overlay_routing_view_->Enable(); } else { - caption_buttons_overlay_input_routing_view_->Disable(); - web_app_frame_toolbar_overlay_routing_view_->Disable(); - RemoveChildView(caption_button_placeholder_container_); caption_button_placeholder_container_ = nullptr; - - caption_buttons_overlay_input_routing_view_ = nullptr; - web_app_frame_toolbar_overlay_routing_view_ = nullptr; } - web_app_frame_toolbar()->OnWindowControlsOverlayEnabledChanged(); frame()->client_view()->InvalidateLayout(); } /////////////////////////////////////////////////////////////////////////////// @@ -427,13 +407,6 @@ return client_size; } -void BrowserNonClientFrameViewMac::AddedToWidget() { - if (browser_view()->IsWindowControlsOverlayEnabled()) { - caption_buttons_overlay_input_routing_view_->Enable(); - web_app_frame_toolbar_overlay_routing_view_->Enable(); - } -} - void BrowserNonClientFrameViewMac::PaintChildren(const views::PaintInfo& info) { // In immersive fullscreen, the browser view's top container relies on the // non-client frame view to paint the frame (see comment in @@ -648,20 +621,6 @@ } } -void BrowserNonClientFrameViewMac::AddRoutingForWindowControlsOverlayViews() { - caption_buttons_overlay_input_routing_view_ = - std::make_unique<WindowControlsOverlayInputRoutingMac>( - this, caption_button_placeholder_container_, - remote_cocoa::mojom::WindowControlsOverlayNSViewType:: - kCaptionButtonContainer); - - web_app_frame_toolbar_overlay_routing_view_ = - std::make_unique<WindowControlsOverlayInputRoutingMac>( - this, web_app_frame_toolbar(), - remote_cocoa::mojom::WindowControlsOverlayNSViewType:: - kWebAppFrameToolbar); -} - bool BrowserNonClientFrameViewMac::AlwaysShowToolbarInFullscreen() const { if (web_app::AppBrowserController::IsWebApp(browser_view()->browser())) { web_app::AppBrowserController* controller =
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 1e98bec..429dfc0 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -142,7 +142,6 @@ #include "chrome/browser/ui/views/side_panel/side_panel.h" #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_registry.h" -#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h" #include "chrome/browser/ui/views/status_bubble_views.h" #include "chrome/browser/ui/views/sync/one_click_signin_dialog_view.h" #include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h" @@ -173,6 +172,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" +#include "chromeos/ui/wm/features.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/feature_constants.h" @@ -255,7 +255,9 @@ #include "ui/views/window/dialog_delegate.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" #include "chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h" +#include "chromeos/ui/frame/caption_buttons/frame_size_button.h" #include "chromeos/ui/wm/desks/desks_helper.h" #endif @@ -1429,10 +1431,6 @@ frame_->UpdateWindowIcon(); } -void BrowserView::UpdateFrameColor() { - frame_->GetFrameView()->UpdateFrameColor(); -} - void BrowserView::BookmarkBarStateChanged( BookmarkBar::AnimateChangeType change_type) { if (bookmark_bar_view_.get()) { @@ -1578,16 +1576,6 @@ if (app_banner_manager) ObserveAppBannerManager(app_banner_manager); - // Update the side panel before performing a layout on the BrowserView so that - // the layout takes into account the presence (or absence) of the side panel. - // This avoids unnecessary resize events propagating to the WebContents if it - // was added first and the layout was adjusted to accommodate the side panel - // later on. - if (side_search_controller_) { - side_search_controller_->UpdateSidePanelForContents(new_contents, - old_contents); - } - UpdateUIForContents(new_contents); RevealTabStripIfNeeded(); @@ -1674,17 +1662,6 @@ infobar_container_->ChangeInfoBarManager(nullptr); app_banner_manager_observation_.Reset(); UpdateDevToolsForContents(nullptr, true); - - // We must ensure that we propagate an update to the side search controller - // so that it removes the now detached tab WebContents from the side panel's - // WebView. This is necessary as BrowserView::OnActiveTabChanged() will fire - // for the destination window before the source window is destroyed during a - // tab dragging operation which could lead to the dragged WebContents being - // added to the destination panel's WebView before it is removed from the - // source panel's WebView. Failing to so so can lead to visual artifacts - // (see crbug.com/1306793). - if (side_search_controller_) - side_search_controller_->UpdateSidePanelForContents(contents, nullptr); } void BrowserView::OnTabRestored(int command_id) { @@ -2089,17 +2066,24 @@ browser()->app_controller() && browser()->app_controller()->IsWindowControlsOverlayEnabled(); - if (enabled == window_controls_overlay_enabled_) + if (enabled == window_controls_overlay_enabled_) { return; + } window_controls_overlay_enabled_ = enabled; // Clear the title-bar-area rect when window controls overlay is disabled. - if (!window_controls_overlay_enabled_) + if (!window_controls_overlay_enabled_) { GetActiveWebContents()->UpdateWindowControlsOverlay(gfx::Rect()); + } - if (frame_ && frame_->GetFrameView()) + if (web_app_frame_toolbar()) { + web_app_frame_toolbar()->OnWindowControlsOverlayEnabledChanged(); + } + + if (frame_ && frame_->GetFrameView()) { frame_->GetFrameView()->WindowControlsOverlayEnabledChanged(); + } const std::u16string& state_change_text = IsWindowControlsOverlayEnabled() @@ -2130,22 +2114,25 @@ should_show = false; #if BUILDFLAG(IS_MAC) - // On macOS, when in fullscreen mode, window controls (the menu bar, tile bar, - // and toolbar) are attached to a separate NSView that slides down from the - // top of the screen, independent of, and overlapping the WebContents. Disable - // WCO when in fullscreen, because this space is inaccessible to WebContents. - // https://crbug.com/915110. - if (frame_ && IsFullscreen()) + // On macOS, when in fullscreen mode, window controls (the menu bar, title + // bar, and toolbar) are attached to a separate NSView that slides down from + // the top of the screen, independent of, and overlapping the WebContents. + // Disable WCO when in fullscreen, because this space is inaccessible to + // WebContents. https://crbug.com/915110. + if (frame_ && IsFullscreen()) { should_show = false; + } #endif if (should_show == should_show_window_controls_overlay_toggle_) return; + DCHECK(AppUsesWindowControlsOverlay()); should_show_window_controls_overlay_toggle_ = should_show; - if (frame_ && frame_->GetFrameView()) - frame_->GetFrameView()->SetWindowControlsOverlayToggleVisible(should_show); + if (web_app_frame_toolbar()) { + web_app_frame_toolbar()->SetWindowControlsOverlayToggleVisible(should_show); + } } void BrowserView::UpdateBorderlessModeEnabled() { @@ -2186,8 +2173,8 @@ return; borderless_mode_enabled_ = borderless_mode_enabled; - if (frame_ && frame_->GetFrameView()) { - frame_->GetFrameView()->UpdateBorderlessModeEnabled(); + if (web_app_frame_toolbar()) { + web_app_frame_toolbar()->UpdateBorderlessModeEnabled(); } } @@ -2613,6 +2600,20 @@ return toolbar_button_provider()->GetPageActionIconView( PageActionIconType::kSharingHub); } + +void BrowserView::ToggleMultitaskMenu() const { + DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); + auto* frame_view = + static_cast<BrowserNonClientFrameViewChromeOS*>(frame_->GetFrameView()); + if (!frame_view) { + return; + } + auto* size_button = static_cast<chromeos::FrameSizeButton*>( + frame_view->caption_button_container()->size_button()); + if (size_button && size_button->GetVisible()) { + size_button->ToggleMultitaskMenu(); + } +} #else sharing_hub::SharingHubBubbleView* BrowserView::ShowSharingHubBubble( share::ShareAttempt attempt) { @@ -3602,29 +3603,11 @@ return false; } - // Ensure all side panels are closed. Close contextual panels first. - - // Hide side search panel if it's right aligned. - if (!exclude_side_search && side_search_controller_) { - side_search_controller_->CloseSidePanel(); - } - toolbar()->side_panel_button()->HideSidePanel(); return true; } -void BrowserView::MaybeClobberAllSideSearchSidePanels() { - if (!base::FeatureList::IsEnabled( - features::kClobberAllSideSearchSidePanels)) { - return; - } - - if (side_search_controller_) { - side_search_controller_->ClobberAllInCurrentBrowser(); - } -} - void BrowserView::RevealTabStripIfNeeded() { if (!immersive_mode_controller_->IsEnabled()) return; @@ -4516,6 +4499,12 @@ kHistoryDisclaimerBubble); } +void BrowserView::UpdateWebAppStatusIconsVisiblity() { + if (web_app_frame_toolbar()) { + web_app_frame_toolbar()->UpdateStatusIconsVisibility(); + } +} + ExclusiveAccessContext* BrowserView::GetExclusiveAccessContext() { return this; } @@ -4778,6 +4767,28 @@ UpdatePageActionIcon(PageActionIconType::kPwaInstall); } +WebAppFrameToolbarView* BrowserView::web_app_frame_toolbar() { + if (frame_ && frame_->GetFrameView()) { + return frame_->GetFrameView()->web_app_frame_toolbar( + base::PassKey<BrowserView>()); + } + return nullptr; +} + +const WebAppFrameToolbarView* BrowserView::web_app_frame_toolbar() const { + if (frame_ && frame_->GetFrameView()) { + return frame_->GetFrameView()->web_app_frame_toolbar( + base::PassKey<BrowserView>()); + } + return nullptr; +} + +void BrowserView::PaintAsActiveChanged() { + if (web_app_frame_toolbar()) { + web_app_frame_toolbar()->SetPaintAsActive(frame_->ShouldPaintAsActive()); + } +} + BEGIN_METADATA(BrowserView, views::ClientView) ADD_READONLY_PROPERTY_METADATA(gfx::Rect, FindBarBoundingBox) ADD_READONLY_PROPERTY_METADATA(int, TabStripHeight)
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index ce96a02d..673e626 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -87,11 +87,10 @@ class TopContainerLoadingBar; class TopContainerView; class TopControlsSlideControllerTest; +class WebAppFrameToolbarView; class WebContentsCloseHandler; class WebUITabStripContainerView; -class SideSearchBrowserController; - namespace ui { class NativeTheme; } // namespace ui @@ -130,7 +129,12 @@ BrowserView& operator=(const BrowserView&) = delete; ~BrowserView() override; - void set_frame(BrowserFrame* frame) { frame_ = frame; } + void set_frame(BrowserFrame* frame) { + frame_ = frame; + paint_as_active_subscription_ = + frame_->RegisterPaintAsActiveChangedCallback(base::BindRepeating( + &BrowserView::PaintAsActiveChanged, base::Unretained(this))); + } BrowserFrame* frame() const { return frame_; } // Returns a pointer to the BrowserView* interface implementation (an @@ -208,10 +212,6 @@ return side_panel_coordinator_.get(); } - SideSearchBrowserController* side_search_controller() { - return side_search_controller_.get(); - } - void set_contents_border_widget(views::Widget* contents_border_widget) { GetBrowserViewLayout()->set_contents_border_widget(contents_border_widget); } @@ -420,6 +420,8 @@ // settings page. void UpdateSidePanelHorizontalAlignment(); + void UpdateWebAppStatusIconsVisiblity(); + // BrowserWindow: void Show() override; void ShowInactive() override; @@ -447,7 +449,6 @@ void SetTopControlsGestureScrollInProgress(bool in_progress) override; StatusBubble* GetStatusBubble() override; void UpdateTitleBar() override; - void UpdateFrameColor() override; void BookmarkBarStateChanged( BookmarkBar::AnimateChangeType change_type) override; void UpdateDevTools() override; @@ -541,6 +542,7 @@ bool show_signin_button) override; #if BUILDFLAG(IS_CHROMEOS) views::Button* GetSharingHubIconButton() override; + void ToggleMultitaskMenu() const override; #else sharing_hub::SharingHubBubbleView* ShowSharingHubBubble( share::ShareAttempt attempt) override; @@ -768,10 +770,6 @@ // side panel being closed. bool CloseOpenRightAlignedSidePanel(bool exclude_side_search = false); - // Clobbers all right aligned side search side panels if - // kClobberAllSideSearchSidePanels is enabled. - void MaybeClobberAllSideSearchSidePanels(); - bool should_show_window_controls_overlay_toggle() const { return should_show_window_controls_overlay_toggle_; } @@ -952,6 +950,11 @@ // Updates whether the web app is an isolated web app. void UpdateIsIsolatedWebApp(); + WebAppFrameToolbarView* web_app_frame_toolbar(); + const WebAppFrameToolbarView* web_app_frame_toolbar() const; + + void PaintAsActiveChanged(); + // The BrowserFrame that hosts this view. raw_ptr<BrowserFrame, DanglingUntriaged> frame_ = nullptr; @@ -1081,9 +1084,6 @@ std::unique_ptr<SidePanelVisibilityController> side_panel_visibility_controller_; - // Controls the browser window's side panel for the Side Search feature. - std::unique_ptr<SideSearchBrowserController> side_search_controller_; - // Provides access to the toolbar buttons this browser view uses. Buttons may // appear in a hosted app frame or in a tabbed UI toolbar. raw_ptr<ToolbarButtonProvider, DanglingUntriaged> toolbar_button_provider_ = @@ -1207,6 +1207,8 @@ absl::optional<content::PermissionController::SubscriptionId> window_management_subscription_id_; + base::CallbackListSubscription paint_as_active_subscription_; + mutable base::WeakPtrFactory<BrowserView> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index cb48c27..c8a6f00 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -199,7 +199,6 @@ void GlassBrowserFrameView::WindowControlsOverlayEnabledChanged() { caption_button_container_->OnWindowControlsOverlayEnabledChanged(); - web_app_frame_toolbar()->OnWindowControlsOverlayEnabledChanged(); InvalidateLayout(); }
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 405d00d..fcca38bb 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -274,7 +274,6 @@ UpdateCaptionButtonToolTipsForWindowControlsOverlay(); #endif - web_app_frame_toolbar()->OnWindowControlsOverlayEnabledChanged(); layout_->SetWindowControlsOverlayEnabled(enabled, this); InvalidateLayout(); } @@ -288,11 +287,6 @@ BrowserNonClientFrameView::PaintAsActiveChanged(); } -void OpaqueBrowserFrameView::UpdateFrameColor() { - UpdateCaptionButtonPlaceholderContainerBackground(); - BrowserNonClientFrameView::PaintAsActiveChanged(); -} - void OpaqueBrowserFrameView::OnThemeChanged() { UpdateCaptionButtonPlaceholderContainerBackground(); BrowserNonClientFrameView::OnThemeChanged();
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h index c4bd4c2d..39221a2 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -66,7 +66,6 @@ void WindowControlsOverlayEnabledChanged() override; gfx::Size GetMinimumSize() const override; void PaintAsActiveChanged() override; - void UpdateFrameColor() override; void OnThemeChanged() override; // views::NonClientFrameView:
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc index f872949..bd32c6d 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
@@ -18,7 +18,6 @@ #include "components/vector_icons/vector_icons.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_constants.h" -#include "third_party/skia/include/core/SkColor.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -26,6 +25,8 @@ #include "ui/compositor/layer.h" #include "ui/display/screen.h" #include "ui/events/event_observer.h" +#include "ui/gfx/animation/animation_container.h" +#include "ui/views/animation/compositor_animation_runner.h" #include "ui/views/event_monitor.h" #include "ui/views/layout/animating_layout_manager.h" #include "ui/views/layout/flex_layout_view.h" @@ -70,6 +71,25 @@ // The window has a smaller minimum size than normal Chrome windows. constexpr gfx::Size kMinWindowSize(300, 300); +// The time duration that the top bar animation will take in total. +constexpr base::TimeDelta kAnimationDuration = base::Milliseconds(250); + +// The animation durations for the top right buttons, which are separated into +// multiple parts because some changes need to be delayed. +constexpr std::array<base::TimeDelta, 2> + kMoveCameraButtonToRightAnimationDurations = {kAnimationDuration * 0.4, + kAnimationDuration * 0.6}; +constexpr std::array<base::TimeDelta, 3> + kShowBackToTabButtonAnimationDurations = {kAnimationDuration * 0.4, + kAnimationDuration * 0.4, + kAnimationDuration * 0.2}; +constexpr std::array<base::TimeDelta, 2> + kHideBackToTabButtonAnimationDurations = {kAnimationDuration * 0.4, + kAnimationDuration * 0.6}; +constexpr std::array<base::TimeDelta, 3> kCloseButtonAnimationDurations = { + kAnimationDuration * 0.2, kAnimationDuration * 0.4, + kAnimationDuration * 0.4}; + class BackToTabButton : public OverlayWindowImageButton { public: METADATA_HEADER(BackToTabButton); @@ -164,7 +184,69 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView( BrowserFrame* frame, BrowserView* browser_view) - : BrowserNonClientFrameView(frame, browser_view) { + : BrowserNonClientFrameView(frame, browser_view), + top_bar_color_animation_(this), + move_camera_button_to_left_animation_(this), + move_camera_button_to_right_animation_( + std::vector<gfx::MultiAnimation::Part>{ + gfx::MultiAnimation::Part( + kMoveCameraButtonToRightAnimationDurations[0], + gfx::Tween::Type::ZERO, + 1.0, + 1.0), + gfx::MultiAnimation::Part( + kMoveCameraButtonToRightAnimationDurations[1], + gfx::Tween::Type::EASE_OUT, + 1.0, + 0.0)}), + show_back_to_tab_button_animation_(std::vector<gfx::MultiAnimation::Part>{ + gfx::MultiAnimation::Part(kShowBackToTabButtonAnimationDurations[0], + gfx::Tween::Type::ZERO, + 0.0, + 0.0), + gfx::MultiAnimation::Part(kShowBackToTabButtonAnimationDurations[1], + gfx::Tween::Type::LINEAR, + 0.0, + 1.0), + gfx::MultiAnimation::Part(kShowBackToTabButtonAnimationDurations[2], + gfx::Tween::Type::ZERO, + 1.0, + 1.0)}), + hide_back_to_tab_button_animation_(std::vector<gfx::MultiAnimation::Part>{ + gfx::MultiAnimation::Part(kHideBackToTabButtonAnimationDurations[0], + gfx::Tween::Type::LINEAR, + 1.0, + 0.0), + gfx::MultiAnimation::Part(kHideBackToTabButtonAnimationDurations[1], + gfx::Tween::Type::ZERO, + 0.0, + 0.0)}), + show_close_button_animation_(std::vector<gfx::MultiAnimation::Part>{ + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[0], + gfx::Tween::Type::ZERO, + 0.0, + 0.0), + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[1], + gfx::Tween::Type::LINEAR, + 0.0, + 1.0), + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[2], + gfx::Tween::Type::ZERO, + 1.0, + 1.0)}), + hide_close_button_animation_(std::vector<gfx::MultiAnimation::Part>{ + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[0], + gfx::Tween::Type::ZERO, + 1.0, + 1.0), + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[1], + gfx::Tween::Type::LINEAR, + 1.0, + 0.0), + gfx::MultiAnimation::Part(kCloseButtonAnimationDurations[2], + gfx::Tween::Type::ZERO, + 0.0, + 0.0)}) { location_bar_model_ = std::make_unique<LocationBarModelImpl>( this, content::kMaxURLDisplayChars); @@ -194,35 +276,18 @@ views::MaximumFlexSizeRule::kUnbounded)) .Build()); - // Creates the content setting models. Currently we only support geo location - // and camera and microphone settings. + // Creates the content setting models. Currently we only support camera and + // microphone settings. constexpr ContentSettingImageModel::ImageType kContentSettingImageOrder[] = { - ContentSettingImageModel::ImageType::GEOLOCATION, ContentSettingImageModel::ImageType::MEDIASTREAM}; std::vector<std::unique_ptr<ContentSettingImageModel>> models; for (auto type : kContentSettingImageOrder) models.push_back(ContentSettingImageModel::CreateForContentType(type)); - // Creates a container view for the top right buttons with an animating layout - // to handle the button animations. - button_container_view_ = - top_bar_container_view_->AddChildView(std::make_unique<views::View>()); - button_container_animating_layout_ = button_container_view_->SetLayoutManager( - std::make_unique<views::AnimatingLayoutManager>()); - button_container_animating_layout_ - ->SetBoundsAnimationMode( - views::AnimatingLayoutManager::BoundsAnimationMode::kAnimateBothAxes) - .SetDefaultFadeMode( - views::AnimatingLayoutManager::FadeInOutMode::kSlideFromTrailingEdge); - auto* flex_layout = - button_container_animating_layout_->SetTargetLayoutManager( - std::make_unique<views::FlexLayout>()); - flex_layout->SetOrientation(views::LayoutOrientation::kHorizontal) - .SetCrossAxisAlignment(views::LayoutAlignment::kCenter); - button_container_view_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification( - button_container_animating_layout_->GetDefaultFlexRule())); + // Creates a container view for the top right buttons to handle the button + // animations. + button_container_view_ = top_bar_container_view_->AddChildView( + std::make_unique<views::FlexLayoutView>()); // Creates the content setting views. for (auto& model : models) { @@ -251,6 +316,33 @@ }, base::Unretained(this)))); + // Enable button layer rendering to set opacity for animation. + back_to_tab_button_->SetPaintToLayer(); + back_to_tab_button_->layer()->SetFillsBoundsOpaquely(false); + close_image_button_->SetPaintToLayer(); + close_image_button_->layer()->SetFillsBoundsOpaquely(false); + + // Creates the top bar title color and camera icon color animation. Set the + // initial state to 1.0 because the window is active when first shown. + top_bar_color_animation_.SetSlideDuration(kAnimationDuration); + top_bar_color_animation_.SetTweenType(gfx::Tween::LINEAR); + top_bar_color_animation_.Reset(1.0); + + // Creates the camera icon movement animations with the default EASE_OUT type. + move_camera_button_to_left_animation_.SetSlideDuration(kAnimationDuration); + move_camera_button_to_right_animation_.set_continuous(false); + move_camera_button_to_right_animation_.set_delegate(this); + + // Creates the button animations. + show_back_to_tab_button_animation_.set_continuous(false); + show_back_to_tab_button_animation_.set_delegate(this); + hide_back_to_tab_button_animation_.set_continuous(false); + hide_back_to_tab_button_animation_.set_delegate(this); + show_close_button_animation_.set_continuous(false); + show_close_button_animation_.set_delegate(this); + hide_close_button_animation_.set_continuous(false); + hide_close_button_animation_.set_delegate(this); + #if BUILDFLAG(IS_LINUX) frame_background_ = std::make_unique<views::FrameBackground>(); #endif @@ -392,6 +484,19 @@ widget_observation_.Observe(GetWidget()); window_event_observer_ = std::make_unique<WindowEventObserver>(this); + // Creates an animation container to ensure all the animations update at the + // same time. + gfx::AnimationContainer* animation_container = new gfx::AnimationContainer(); + animation_container->SetAnimationRunner( + std::make_unique<views::CompositorAnimationRunner>(GetWidget())); + top_bar_color_animation_.SetContainer(animation_container); + move_camera_button_to_left_animation_.SetContainer(animation_container); + move_camera_button_to_right_animation_.SetContainer(animation_container); + show_back_to_tab_button_animation_.SetContainer(animation_container); + hide_back_to_tab_button_animation_.SetContainer(animation_container); + show_close_button_animation_.SetContainer(animation_container); + hide_close_button_animation_.SetContainer(animation_container); + BrowserNonClientFrameView::AddedToWidget(); } @@ -542,18 +647,9 @@ return browser->content_setting_bubble_model_delegate(); } -#if BUILDFLAG(IS_MAC) -/////////////////////////////////////////////////////////////////////////////// -// GeolocationManager::PermissionObserver implementations: -void PictureInPictureBrowserFrameView::OnSystemPermissionUpdated( - device::LocationSystemPermissionStatus new_status) { - // Update icons if the macOS location permission is updated. - UpdateContentSettingsIcons(); -} -#endif - /////////////////////////////////////////////////////////////////////////////// // views::WidgetObserver implementations: + void PictureInPictureBrowserFrameView::OnWidgetActivationChanged( views::Widget* widget, bool active) { @@ -571,7 +667,50 @@ } /////////////////////////////////////////////////////////////////////////////// +// gfx::AnimationDelegate implementations: + +void PictureInPictureBrowserFrameView::AnimationProgressed( + const gfx::Animation* animation) { + if (animation == &top_bar_color_animation_) { + SkColor color = gfx::Tween::ColorValueBetween( + animation->GetCurrentValue(), + GetColorProvider()->GetColor(kColorPipWindowForegroundInactive), + GetColorProvider()->GetColor(kColorPipWindowForeground)); + window_title_->SetEnabledColor(color); + for (ContentSettingImageView* view : content_setting_views_) { + view->SetIconColor(color); + } + return; + } + + if (animation == &move_camera_button_to_left_animation_ || + animation == &move_camera_button_to_right_animation_) { + for (ContentSettingImageView* view : content_setting_views_) { + // Set the position of camera icon relative to |button_container_view_|. + view->SetX(animation->CurrentValueBetween( + back_to_tab_button_->width() + close_image_button_->width(), 0)); + } + return; + } + + if (animation == &show_back_to_tab_button_animation_ || + animation == &hide_back_to_tab_button_animation_) { + back_to_tab_button_->layer()->SetOpacity(animation->GetCurrentValue()); + return; + } + + if (animation == &show_close_button_animation_ || + animation == &hide_close_button_animation_) { + close_image_button_->layer()->SetOpacity(animation->GetCurrentValue()); + return; + } + + NOTREACHED(); +} + +/////////////////////////////////////////////////////////////////////////////// // views::View implementations: + void PictureInPictureBrowserFrameView::OnPaint(gfx::Canvas* canvas) { #if BUILDFLAG(IS_LINUX) // Draw the PiP window frame borders and shadows, including the top bar @@ -602,6 +741,7 @@ /////////////////////////////////////////////////////////////////////////////// // PictureInPictureBrowserFrameView implementations: + gfx::Rect PictureInPictureBrowserFrameView::ConvertTopBarControlViewBounds( views::View* control_view, views::View* source_view) const { @@ -646,20 +786,38 @@ } void PictureInPictureBrowserFrameView::UpdateTopBarView(bool render_active) { - if (render_active) { - button_container_animating_layout_->FadeIn(back_to_tab_button_); - button_container_animating_layout_->FadeIn(close_image_button_); - } else { - button_container_animating_layout_->FadeOut(back_to_tab_button_); - button_container_animating_layout_->FadeOut(close_image_button_); + // Check if the update is needed to avoid redundant animations. + if (render_active_ == render_active) { + return; } - const SkColor color = GetColorProvider()->GetColor( - render_active ? kColorPipWindowForeground - : kColorPipWindowForegroundInactive); - window_title_->SetEnabledColor(color); - for (ContentSettingImageView* view : content_setting_views_) - view->SetIconColor(color); + render_active_ = render_active; + + // Stop the previous animations since if this function is called too soon, + // previous animations may override the new animations. + if (render_active_) { + move_camera_button_to_right_animation_.Stop(); + hide_back_to_tab_button_animation_.Stop(); + hide_close_button_animation_.Stop(); + + top_bar_color_animation_.Show(); + + // SlideAnimation needs to be reset if only Show() is called. + move_camera_button_to_left_animation_.Reset(0.0); + move_camera_button_to_left_animation_.Show(); + + show_back_to_tab_button_animation_.Start(); + show_close_button_animation_.Start(); + } else { + move_camera_button_to_left_animation_.Stop(); + show_back_to_tab_button_animation_.Stop(); + show_close_button_animation_.Stop(); + + top_bar_color_animation_.Hide(); + move_camera_button_to_right_animation_.Start(); + hide_back_to_tab_button_animation_.Start(); + hide_close_button_animation_.Start(); + } } gfx::Insets PictureInPictureBrowserFrameView::FrameBorderInsets() const { @@ -720,20 +878,30 @@ #endif // Helper functions for testing. -views::AnimatingLayoutManager* -PictureInPictureBrowserFrameView::GetAnimatingLayoutManagerForTesting() { - return button_container_animating_layout_; +std::vector<gfx::Animation*> +PictureInPictureBrowserFrameView::GetRenderActiveAnimationsForTesting() { + return std::vector<gfx::Animation*>( + {&top_bar_color_animation_, &move_camera_button_to_left_animation_, + &show_back_to_tab_button_animation_, &show_close_button_animation_}); +} + +std::vector<gfx::Animation*> +PictureInPictureBrowserFrameView::GetRenderInactiveAnimationsForTesting() { + return std::vector<gfx::Animation*>( + {&top_bar_color_animation_, &move_camera_button_to_right_animation_, + &hide_back_to_tab_button_animation_, &hide_close_button_animation_}); } views::View* PictureInPictureBrowserFrameView::GetBackToTabButtonForTesting() { return back_to_tab_button_; } +views::View* PictureInPictureBrowserFrameView::GetCloseButtonForTesting() { + return close_image_button_; +} + void PictureInPictureBrowserFrameView::OnMouseEnteredOrExitedWindow( bool entered) { - if (mouse_inside_window_ == entered) - return; - mouse_inside_window_ = entered; UpdateTopBarView(mouse_inside_window_); }
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h index b3aa9dee..6def6a7 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h
@@ -14,8 +14,9 @@ #include "chrome/browser/ui/views/overlay/close_image_button.h" #include "components/omnibox/browser/location_bar_model.h" #include "content/public/browser/web_contents.h" -#include "services/device/public/cpp/geolocation/geolocation_manager.h" #include "ui/base/metadata/metadata_header_macros.h" +#include "ui/gfx/animation/multi_animation.h" +#include "ui/gfx/animation/slide_animation.h" #include "ui/views/controls/image_view.h" #include "ui/views/widget/widget_observer.h" @@ -24,11 +25,10 @@ #endif namespace views { -class AnimatingLayoutManager; class FlexLayoutView; class FrameBackground; class Label; -} +} // namespace views namespace { class WindowEventObserver; @@ -40,10 +40,8 @@ public LocationIconView::Delegate, public IconLabelBubbleView::Delegate, public ContentSettingImageView::Delegate, -#if BUILDFLAG(IS_MAC) - public device::GeolocationManager::PermissionObserver, -#endif - public views::WidgetObserver { + public views::WidgetObserver, + public gfx::AnimationDelegate { public: METADATA_HEADER(PictureInPictureBrowserFrameView); @@ -108,16 +106,13 @@ ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate() override; -#if BUILDFLAG(IS_MAC) - // GeolocationManager::PermissionObserver: - void OnSystemPermissionUpdated( - device::LocationSystemPermissionStatus new_status) override; -#endif - // views::WidgetObserver: void OnWidgetActivationChanged(views::Widget* widget, bool active) override; void OnWidgetDestroying(views::Widget* widget) override; + // gfx::AnimationDelegate: + void AnimationProgressed(const gfx::Animation* animation) override; + // views::View: void OnPaint(gfx::Canvas* canvas) override; @@ -173,8 +168,10 @@ #endif // Helper functions for testing. - views::AnimatingLayoutManager* GetAnimatingLayoutManagerForTesting(); + std::vector<gfx::Animation*> GetRenderActiveAnimationsForTesting(); + std::vector<gfx::Animation*> GetRenderInactiveAnimationsForTesting(); views::View* GetBackToTabButtonForTesting(); + views::View* GetCloseButtonForTesting(); private: // A model required to use LocationIconView. @@ -190,9 +187,7 @@ raw_ptr<views::Label> window_title_ = nullptr; // A container view for the top right buttons. - raw_ptr<views::View> button_container_view_ = nullptr; - raw_ptr<views::AnimatingLayoutManager> button_container_animating_layout_ = - nullptr; + raw_ptr<views::FlexLayoutView> button_container_view_ = nullptr; // The content setting views for icons and bubbles. std::vector<ContentSettingImageView*> content_setting_views_; @@ -202,8 +197,27 @@ base::ScopedObservation<views::Widget, views::WidgetObserver> widget_observation_{this}; + + // When the window is created and shown for the first time, we show the active + // window state even if the mouse is not inside it. + bool render_active_ = true; + bool mouse_inside_window_ = false; + // Animations for the top bar title and buttons. When the mouse moves in or + // out of the window, the title color and camera icon color will highlight + // or dim, the back to tab button and close button will show or hide, and the + // camera icon will move left or right if present. We consider animation state + // 1.0 as the window active state (mouse in) and 0.0 as inactive state (mouse + // out). + gfx::SlideAnimation top_bar_color_animation_; + gfx::SlideAnimation move_camera_button_to_left_animation_; + gfx::MultiAnimation move_camera_button_to_right_animation_; + gfx::MultiAnimation show_back_to_tab_button_animation_; + gfx::MultiAnimation hide_back_to_tab_button_animation_; + gfx::MultiAnimation show_close_button_animation_; + gfx::MultiAnimation hide_close_button_animation_; + #if BUILDFLAG(IS_LINUX) // Used to draw window frame borders and shadow on Linux when GTK theme is // enabled. @@ -214,7 +228,7 @@ std::unique_ptr<views::FrameBackground> frame_background_; #endif - // Userd to monitor key and mouse event from native window. + // Used to monitor key and mouse events from native window. std::unique_ptr<WindowEventObserver> window_event_observer_; };
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc index 4869986..3097bf36 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc
@@ -17,10 +17,12 @@ #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" #include "third_party/blink/public/common/features.h" -#include "ui/views/layout/animating_layout_manager_test_util.h" +#include "ui/gfx/animation/animation_test_api.h" namespace { +constexpr base::TimeDelta kAnimationDuration = base::Milliseconds(250); + const base::FilePath::CharType kPictureInPictureDocumentPipPage[] = FILE_PATH_LITERAL("media/picture-in-picture/document-pip.html"); @@ -75,6 +77,23 @@ ASSERT_TRUE(pip_frame_view_); } + void WaitForTopBarAnimations(std::vector<gfx::Animation*> animations) { + base::TimeTicks now = base::TimeTicks::Now(); + for (auto* animation : animations) { + gfx::AnimationTestApi animation_api(animation); + animation_api.SetStartTime(now); + animation_api.Step(now + kAnimationDuration); + } + } + + bool IsButtonVisible(views::View* button_view) { + bool is_button_visible = button_view->GetVisible(); + if (button_view->layer() != nullptr) { + is_button_visible &= (button_view->layer()->opacity() > 0); + } + return is_button_visible; + } + bool IsPointInPIPFrameView(gfx::Point point_in_screen) { views::View::ConvertPointFromScreen(pip_frame_view_, &point_in_screen); return pip_frame_view_->GetLocalBounds().Contains(point_in_screen); @@ -106,9 +125,11 @@ gfx::Point center = pip_frame_view()->GetLocalBounds().CenterPoint(); views::View::ConvertPointToScreen(pip_frame_view(), ¢er); ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(center)); - views::test::WaitForAnimatingLayoutManager( - pip_frame_view()->GetAnimatingLayoutManagerForTesting()); - ASSERT_TRUE(pip_frame_view()->GetBackToTabButtonForTesting()->GetVisible()); + WaitForTopBarAnimations( + pip_frame_view()->GetRenderActiveAnimationsForTesting()); + ASSERT_TRUE( + IsButtonVisible(pip_frame_view()->GetBackToTabButtonForTesting())); + ASSERT_TRUE(IsButtonVisible(pip_frame_view()->GetCloseButtonForTesting())); // Move mouse to the top-left corner of the main browser window (out side of // the pip window) should deactivate the title. @@ -117,15 +138,19 @@ static_cast<BrowserView*>(browser()->window()), &outside); ASSERT_FALSE(IsPointInPIPFrameView(outside)); ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(outside)); - views::test::WaitForAnimatingLayoutManager( - pip_frame_view()->GetAnimatingLayoutManagerForTesting()); - ASSERT_FALSE(pip_frame_view()->GetBackToTabButtonForTesting()->GetVisible()); + WaitForTopBarAnimations( + pip_frame_view()->GetRenderInactiveAnimationsForTesting()); + ASSERT_FALSE( + IsButtonVisible(pip_frame_view()->GetBackToTabButtonForTesting())); + ASSERT_FALSE(IsButtonVisible(pip_frame_view()->GetCloseButtonForTesting())); // Move mouse back in pip window should activate title. ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(center)); - views::test::WaitForAnimatingLayoutManager( - pip_frame_view()->GetAnimatingLayoutManagerForTesting()); - ASSERT_TRUE(pip_frame_view()->GetBackToTabButtonForTesting()->GetVisible()); + WaitForTopBarAnimations( + pip_frame_view()->GetRenderActiveAnimationsForTesting()); + ASSERT_TRUE( + IsButtonVisible(pip_frame_view()->GetBackToTabButtonForTesting())); + ASSERT_TRUE(IsButtonVisible(pip_frame_view()->GetCloseButtonForTesting())); } } // namespace
diff --git a/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.h b/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.h deleted file mode 100644 index 62cd978..0000000 --- a/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.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 CHROME_BROWSER_UI_VIEWS_FRAME_WINDOW_CONTROLS_OVERLAY_INPUT_ROUTING_MAC_H_ -#define CHROME_BROWSER_UI_VIEWS_FRAME_WINDOW_CONTROLS_OVERLAY_INPUT_ROUTING_MAC_H_ - -#include "base/memory/raw_ptr.h" -#include "components/remote_cocoa/common/native_widget_ns_window.mojom.h" -#include "ui/views/view_observer.h" - -namespace views { -class View; -class NativeWidgetMacNSWindowHost; -} // namespace views - -class BrowserNonClientFrameViewMac; - -// WindowControlsOverlayInputRoutingMac is responsible for adding a remote -// NSView and positioning it correctly based on the position of the provided -// |overlay_view|. Intended for PWAs with window controls overlay display -// override. -class WindowControlsOverlayInputRoutingMac : public views::ViewObserver { - public: - WindowControlsOverlayInputRoutingMac( - BrowserNonClientFrameViewMac* browser_non_client_frame_view_mac, - views::View* overlay_view, - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type); - ~WindowControlsOverlayInputRoutingMac() override; - - void Enable(); - void Disable(); - - // views::ViewObserver: - void OnViewBoundsChanged(views::View* overlay_view) override; - - private: - void UpdateNSViewPosition(); - - raw_ptr<BrowserNonClientFrameViewMac> browser_non_client_frame_view_mac_ = - nullptr; // weak - raw_ptr<views::View> - overlay_view_; // weak. Owned by BrowserNonClientFrameViewMac. - raw_ptr<views::NativeWidgetMacNSWindowHost> - host_; // weak. Owned by NativeWidgetMac. - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_FRAME_WINDOW_CONTROLS_OVERLAY_INPUT_ROUTING_MAC_H_
diff --git a/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.mm b/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.mm deleted file mode 100644 index a54bed8..0000000 --- a/chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.mm +++ /dev/null
@@ -1,58 +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 "chrome/browser/ui/views/frame/window_controls_overlay_input_routing_mac.h" - -#include <AppKit/AppKit.h> - -#include "base/mac/scoped_nsobject.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h" -#include "ui/views/cocoa/native_widget_mac_ns_window_host.h" -#include "ui/views/widget/widget.h" - -WindowControlsOverlayInputRoutingMac::WindowControlsOverlayInputRoutingMac( - BrowserNonClientFrameViewMac* browser_non_client_frame_view_mac, - views::View* overlay_view, - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) - : browser_non_client_frame_view_mac_(browser_non_client_frame_view_mac), - overlay_view_(overlay_view), - overlay_type_(overlay_type) { - // WebAppOriginText animates and disappears during initial launch so we want - // to observe that and update the remote view accordingly. - overlay_view_->AddObserver(this); - browser_non_client_frame_view_mac_->AddObserver(this); -} - -WindowControlsOverlayInputRoutingMac::~WindowControlsOverlayInputRoutingMac() { - overlay_view_->RemoveObserver(this); - browser_non_client_frame_view_mac_->RemoveObserver(this); -} - -void WindowControlsOverlayInputRoutingMac::OnViewBoundsChanged( - views::View* overlay_view) { - UpdateNSViewPosition(); -} - -void WindowControlsOverlayInputRoutingMac::Enable() { - auto window = - browser_non_client_frame_view_mac_->GetWidget()->GetNativeWindow(); - host_ = views::NativeWidgetMacNSWindowHost::GetFromNativeWindow(window); - - host_->AddRemoteWindowControlsOverlayView(overlay_type_); - - UpdateNSViewPosition(); -} - -void WindowControlsOverlayInputRoutingMac::Disable() { - if (!host_) - return; - host_->RemoveRemoteWindowControlsOverlayView(overlay_type_); -} - -void WindowControlsOverlayInputRoutingMac::UpdateNSViewPosition() { - if (!host_) - return; - - host_->UpdateRemoteWindowControlsOverlayView( - overlay_view_->GetMirroredBounds(), overlay_type_); -}
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc index 84deabb..2be40e1 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc
@@ -7,7 +7,6 @@ #include <memory> #include "base/strings/utf_string_conversions.h" -#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/view_ids.h" @@ -20,6 +19,7 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/views/vector_icons.h" CookieControlsIconView::CookieControlsIconView( IconLabelBubbleView::Delegate* icon_label_bubble_delegate, @@ -116,9 +116,9 @@ } const gfx::VectorIcon& CookieControlsIconView::GetVectorIcon() const { - if (status_ == CookieControlsStatus::kDisabledForSite) - return kEyeIcon; - return kEyeCrossedIcon; + return status_ == CookieControlsStatus::kDisabledForSite + ? views::kEyeIcon + : views::kEyeCrossedIcon; } std::u16string CookieControlsIconView::GetTextForTooltipAndAccessibleName()
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index b564bca7..748416c6 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -329,6 +329,7 @@ // Add icons only when feature is not enabled. Otherwise icons will // be added to the ToolbarPageActionIconContainerView. params.types_enabled.push_back(PageActionIconType::kSaveCard); + params.types_enabled.push_back(PageActionIconType::kSaveIban); params.types_enabled.push_back(PageActionIconType::kLocalCardMigration); params.types_enabled.push_back( PageActionIconType::kVirtualCardManualFallback); @@ -1006,9 +1007,11 @@ bool LocationBarView::RefreshContentSettingViews() { if (web_app::AppBrowserController::IsWebApp(browser_)) { - // For hosted apps, the location bar is normally hidden and icons appear in + // For web apps, the location bar is normally hidden and icons appear in // the window frame instead. - GetWidget()->non_client_view()->ResetWindowControls(); + if (auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_)) { + browser_view->UpdateWebAppStatusIconsVisiblity(); + } } bool visibility_changed = false; @@ -1023,9 +1026,11 @@ void LocationBarView::RefreshPageActionIconViews() { if (web_app::AppBrowserController::IsWebApp(browser_)) { - // For hosted apps, the location bar is normally hidden and icons appear in + // For web apps, the location bar is normally hidden and icons appear in // the window frame instead. - GetWidget()->non_client_view()->ResetWindowControls(); + if (auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser_)) { + browser_view->UpdateWebAppStatusIconsVisiblity(); + } } page_action_icon_controller_->UpdateAll();
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc index fbff228c..b2298b51 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
@@ -250,8 +250,9 @@ LocationBarViewGeolocationBackForwardCacheBrowserTest() : geo_override_(0.0, 0.0) { feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}, {blink::features::kLoadingTasksUnfreezable, {}}, {features::kBackForwardCacheMemoryControls, {}}}, {});
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc index 41a4aa1..eb83019f9 100644 --- a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc +++ b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc
@@ -196,6 +196,9 @@ params.command_updater, params.icon_label_bubble_delegate, params.page_action_icon_delegate)); break; + case PageActionIconType::kSaveIban: + // TODO(crbug.com/1349109): Create SaveIBANIconView. + break; case PageActionIconType::kSendTabToSelf: add_page_action_icon( type, std::make_unique<send_tab_to_self::SendTabToSelfIconView>(
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.cc b/chrome/browser/ui/views/page_info/page_info_view_factory.cc index 03d3aab..3de6a59b 100644 --- a/chrome/browser/ui/views/page_info/page_info_view_factory.cc +++ b/chrome/browser/ui/views/page_info/page_info_view_factory.cc
@@ -481,7 +481,7 @@ // static const ui::ImageModel PageInfoViewFactory::GetBlockingThirdPartyCookiesIcon() { - return ui::ImageModel::FromVectorIcon(kEyeCrossedIcon, ui::kColorIcon, + return ui::ImageModel::FromVectorIcon(views::kEyeCrossedIcon, ui::kColorIcon, GetIconSize()); }
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_view.cc index 825e31b..aad95c6 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_view.cc
@@ -26,8 +26,10 @@ #include "components/password_manager/core/browser/password_ui_utils.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/vector_icons/vector_icons.h" +#include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/models/image_model.h" #include "ui/gfx/favicon_size.h" +#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/highlight_path_generator.h" @@ -53,6 +55,11 @@ constexpr int kDetailRowHeight = 44; constexpr int kMaxLinesVisibleFromPasswordNote = 3; +void WriteToClipboard(const std::u16string& text) { + ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); + scw.WriteText(text); +} + std::unique_ptr<views::View> CreateIconView( const gfx::VectorIcon& vector_icon) { auto icon = std::make_unique<NonAccessibleImageView>(); @@ -62,24 +69,26 @@ } // Creates a view of the same height as the height of the each row in the table, -// and vertically centers the icon inside it. This insures the icon is -// vertically aligned with the center of the first row in the text that lives -// inside labels in the same row even if the text spans multiple lines such as -// password notes. -std::unique_ptr<views::View> CreateWrappedIconView( - const gfx::VectorIcon& vector_icon) { +// and vertically centers the child view inside it. This is used to wrap icons +// and image buttons to ensure the icons are vertically aligned with the center +// of the first row in the text that lives inside labels in the same row even if +// the text spans multiple lines such as password notes. +std::unique_ptr<views::View> CreateWrappedView( + std::unique_ptr<views::View> child_view) { auto wrapper = std::make_unique<views::BoxLayoutView>(); wrapper->SetPreferredSize( gfx::Size(/*width=*/kIconSize, /*height=*/kDetailRowHeight)); wrapper->SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kCenter); - wrapper->AddChildView(CreateIconView(vector_icon)); + wrapper->AddChildView(std::move(child_view)); return wrapper; } std::unique_ptr<views::View> CreateDetailsRow( const gfx::VectorIcon& row_icon, std::unique_ptr<views::View> detail_view, - const gfx::VectorIcon& action_icon) { + const gfx::VectorIcon& action_icon, + const std::u16string& action_button_tooltip_text, + views::Button::PressedCallback action_button_callback) { auto row = std::make_unique<views::FlexLayoutView>(); row->SetCollapseMargins(true); row->SetDefault( @@ -88,7 +97,7 @@ views::DISTANCE_RELATED_CONTROL_HORIZONTAL))); row->SetCrossAxisAlignment(views::LayoutAlignment::kStart); - row->AddChildView(CreateWrappedIconView(row_icon)); + row->AddChildView(CreateWrappedView(CreateIconView(row_icon))); detail_view->SetProperty( views::kFlexBehaviorKey, @@ -96,7 +105,11 @@ views::MaximumFlexSizeRule::kUnbounded)); row->AddChildView(std::move(detail_view)); - row->AddChildView(CreateWrappedIconView(action_icon)); + std::unique_ptr<views::ImageButton> action_button = + CreateVectorImageButtonWithNativeTheme(std::move(action_button_callback), + action_icon, kIconSize); + action_button->SetTooltipText(action_button_tooltip_text); + row->AddChildView(CreateWrappedView(std::move(action_button))); return row; } @@ -303,24 +316,31 @@ auto container_view = std::make_unique<views::BoxLayoutView>(); container_view->SetOrientation(views::BoxLayout::Orientation::kVertical); - // TODO(crbug.com/1408790): Assign action to the username action button. + // TODO(crbug.com/1408790): Handle the empty username case. container_view->AddChildView(CreateDetailsRow( kAccountCircleIcon, CreateUsernameLabel(*currently_selected_password_), - vector_icons::kContentCopyIcon)); + vector_icons::kContentCopyIcon, + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UI_COPY_USERNAME), + base::BindRepeating(&WriteToClipboard, + currently_selected_password_->username_value))); - // TODO(crbug.com/1408790): Assign action to the password action button. // TODO(crbug.com/1408790): Add a key icon to the password field to reveal the // password. container_view->AddChildView(CreateDetailsRow( kKeyIcon, CreatePasswordLabel(*currently_selected_password_), - vector_icons::kContentCopyIcon)); + vector_icons::kContentCopyIcon, + l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_UI_COPY_PASSWORD), + base::BindRepeating(&WriteToClipboard, + currently_selected_password_->password_value))); // TODO(crbug.com/1408790): Use a different icon for the notes to match the // mocks. // TODO(crbug.com/1408790): Assign action to the note action button. + // TODO(crbug.com/1408790): use internationalized string for the note action + // button tooltip text. container_view->AddChildView(CreateDetailsRow( kAccountCircleIcon, CreateNoteLabel(*currently_selected_password_), - vector_icons::kEditIcon)); + vector_icons::kEditIcon, u"Edit Note", views::Button::PressedCallback())); return container_view; }
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc index 86639c8..d68bcd1 100644 --- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc +++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
@@ -29,6 +29,7 @@ #include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" #include "ui/native_theme/native_theme.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/image_view.h" @@ -108,6 +109,25 @@ GeneratedPasswordBox() = default; ~GeneratedPasswordBox() override = default; + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + if (!controller_) { + return; + } + + node_data->role = ax::mojom::Role::kListBoxOption; + node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, + controller_->password_selected()); + node_data->SetNameChecked(base::JoinString( + {controller_->SuggestedText(), controller_->password()}, u" ")); + const std::u16string help_text = l10n_util::GetStringFUTF16( + IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER, + l10n_util::GetStringUTF16( + IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SYNCED_TO_ACCOUNT), + controller_->GetPrimaryAccountEmail()); + + node_data->SetDescription(help_text); + } + // Fills the view with strings provided by |controller|. void Init(base::WeakPtr<PasswordGenerationPopupController> controller); @@ -270,7 +290,7 @@ DCHECK(FullPopupVisible()); if (controller_->password_selected()) - NotifyAXSelection(this); + NotifyAXSelection(this->password_view_); if (!GetWidget()) return; @@ -378,13 +398,18 @@ void PasswordGenerationPopupViewViews::GetAccessibleNodeData( ui::AXNodeData* node_data) { + // TODO(crbug.com/1404297): kListBox is used for the same reason as in + // AutofillPopupViewNativeViews. See crrev.com/c/2545285 for details. + // Consider using a more appropriate role (e.g. kMenuListPopup or similar). + node_data->role = ax::mojom::Role::kListBox; + if (!controller_) { + node_data->AddState(ax::mojom::State::kCollapsed); + node_data->AddState(ax::mojom::State::kInvisible); return; } - node_data->role = ax::mojom::Role::kMenuItem; - node_data->SetNameChecked(base::JoinString( - {controller_->SuggestedText(), controller_->password()}, u" ")); - node_data->SetDescription(controller_->HelpText()); + + node_data->AddState(ax::mojom::State::kExpanded); } gfx::Size PasswordGenerationPopupViewViews::CalculatePreferredSize() const { @@ -410,3 +435,7 @@ return new PasswordGenerationPopupViewViews(controller, observing_widget); } + +BEGIN_METADATA(PasswordGenerationPopupViewViews, + autofill::AutofillPopupBaseView) +END_METADATA
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.h b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.h index 5ff75f4..390b309 100644 --- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.h +++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.h
@@ -9,7 +9,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/passwords/password_generation_popup_view.h" #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h" - +#include "ui/base/metadata/metadata_header_macros.h" class PasswordGenerationPopupController; namespace views { @@ -19,6 +19,8 @@ class PasswordGenerationPopupViewViews : public autofill::AutofillPopupBaseView, public PasswordGenerationPopupView { public: + METADATA_HEADER(PasswordGenerationPopupViewViews); + PasswordGenerationPopupViewViews( base::WeakPtr<PasswordGenerationPopupController> controller, views::Widget* parent_widget);
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc index 98b24b5d..2e36fad 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_view.cc +++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -52,11 +52,10 @@ #include "ui/gfx/vector_icon_utils.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/bubble/bubble_frame_view.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/combobox/combobox.h" #include "ui/views/controls/editable_combobox/editable_combobox.h" +#include "ui/views/controls/editable_combobox/editable_password_combobox.h" #include "ui/views/controls/styled_label.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/interaction/element_tracker_views.h" @@ -93,13 +92,10 @@ // Builds a credential row, adds the given elements to the layout. // |destination_field| is nullptr if the destination field shouldn't be shown. -// |password_view_button| is an optional field. -void BuildCredentialRows( - views::View* parent_view, - std::unique_ptr<views::View> destination_field, - std::unique_ptr<views::View> username_field, - std::unique_ptr<views::View> password_field, - std::unique_ptr<views::ToggleImageButton> password_view_button) { +void BuildCredentialRows(views::View* parent_view, + std::unique_ptr<views::View> destination_field, + std::unique_ptr<views::View> username_field, + std::unique_ptr<views::View> password_field) { std::unique_ptr<views::Label> username_label(new views::Label( l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USERNAME_LABEL), views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY)); @@ -151,11 +147,6 @@ views::MaximumFlexSizeRule::kUnbounded)); password_row->AddChildView(std::move(password_field)); - // The eye icon is also added to the layout if it was passed. - if (password_view_button) { - password_row->AddChildView(std::move(password_view_button)); - } - parent_view->AddChildView(std::move(password_row)); } @@ -169,22 +160,6 @@ return passwords; } -std::unique_ptr<views::ToggleImageButton> CreatePasswordViewButton( - views::Button::PressedCallback callback, - bool are_passwords_revealed) { - auto button = std::make_unique<views::ToggleImageButton>(std::move(callback)); - button->SetInstallFocusRingOnFocus(true); - button->SetRequestFocusOnPress(true); - button->SetTooltipText( - l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_SHOW_PASSWORD)); - button->SetToggledTooltipText( - l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_HIDE_PASSWORD)); - button->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER); - button->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE); - button->SetToggled(are_passwords_revealed); - return button; -} - // Creates an EditableCombobox from |PasswordForm.all_possible_usernames| or // even just |PasswordForm.username_value|. std::unique_ptr<views::EditableCombobox> CreateUsernameEditableCombobox( @@ -204,8 +179,7 @@ std::vector<ui::SimpleComboboxModel::Item>(usernames.begin(), usernames.end())), /*filter_on_edit=*/false, /*show_on_empty=*/true, - views::EditableCombobox::Type::kRegular, views::style::CONTEXT_BUTTON, - views::style::STYLE_PRIMARY, display_arrow); + views::style::CONTEXT_BUTTON, views::style::STYLE_PRIMARY, display_arrow); combobox->SetText(form.username_value); combobox->SetAccessibleName( l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_USERNAME_LABEL)); @@ -214,11 +188,14 @@ return combobox; } -// Creates an EditableCombobox from |PasswordForm.all_possible_passwords| or -// even just |PasswordForm.password_value|. -std::unique_ptr<views::EditableCombobox> CreatePasswordEditableCombobox( +// Creates an EditablePasswordCombobox from +// `PasswordForm.all_possible_passwords` or even just +// `PasswordForm.password_value`. +std::unique_ptr<views::EditablePasswordCombobox> CreateEditablePasswordCombobox( const password_manager::PasswordForm& form, - bool are_passwords_revealed) { + bool are_passwords_revealed, + views::EditablePasswordCombobox::IsPasswordRevealPermittedCheck + reveal_permitted_check) { DCHECK(!form.IsFederatedCredential()); std::vector<std::u16string> passwords = form.all_possible_passwords.empty() @@ -228,14 +205,16 @@ return password.empty(); }); bool display_arrow = !passwords.empty(); - auto combobox = std::make_unique<views::EditableCombobox>( + auto combobox = std::make_unique<views::EditablePasswordCombobox>( std::make_unique<ui::SimpleComboboxModel>( std::vector<ui::SimpleComboboxModel::Item>(passwords.begin(), passwords.end())), - /*filter_on_edit=*/false, /*show_on_empty=*/true, - views::EditableCombobox::Type::kPassword, views::style::CONTEXT_BUTTON, - STYLE_PRIMARY_MONOSPACED, display_arrow); + views::style::CONTEXT_BUTTON, STYLE_PRIMARY_MONOSPACED, display_arrow); combobox->SetText(form.password_value); + combobox->SetPasswordIconTooltips( + l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_SHOW_PASSWORD), + l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_HIDE_PASSWORD)); + combobox->SetIsPasswordRevealPermittedCheck(std::move(reveal_permitted_check)); combobox->RevealPasswords(are_passwords_revealed); combobox->SetAccessibleName( l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_PASSWORD_LABEL)); @@ -311,9 +290,7 @@ ? PasswordBubbleControllerBase::DisplayReason::kAutomatic : PasswordBubbleControllerBase::DisplayReason::kUserAction), is_update_bubble_(controller_.state() == - password_manager::ui::PENDING_PASSWORD_UPDATE_STATE), - are_passwords_revealed_( - controller_.are_passwords_revealed_when_bubble_is_opened()) { + password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { DCHECK(controller_.state() == password_manager::ui::PENDING_PASSWORD_STATE || controller_.state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE); @@ -359,16 +336,12 @@ CreateUsernameEditableCombobox(password_form); username_dropdown->SetCallback(base::BindRepeating( &PasswordSaveUpdateView::OnContentChanged, base::Unretained(this))); - std::unique_ptr<views::EditableCombobox> password_dropdown = - CreatePasswordEditableCombobox(password_form, are_passwords_revealed_); - password_dropdown->SetCallback(base::BindRepeating( - &PasswordSaveUpdateView::OnContentChanged, base::Unretained(this))); - std::unique_ptr<views::ToggleImageButton> password_view_button = - CreatePasswordViewButton( - base::BindRepeating( - &PasswordSaveUpdateView::TogglePasswordVisibility, - base::Unretained(this)), - are_passwords_revealed_); + std::unique_ptr<views::EditablePasswordCombobox> password_dropdown = + CreateEditablePasswordCombobox( + password_form, + controller_.are_passwords_revealed_when_bubble_is_opened(), + base::BindRepeating(&SaveUpdateBubbleController::RevealPasswords, + base::Unretained(&controller_))); // Set up layout: SetLayoutManager(std::make_unique<AutoResizingLayout>()); views::View* root_view = AddChildView(std::make_unique<views::View>()); @@ -393,11 +366,9 @@ username_dropdown_ = username_dropdown.get(); password_dropdown_ = password_dropdown.get(); - password_view_button_ = password_view_button.get(); BuildCredentialRows(root_view, std::move(destination_dropdown), std::move(username_dropdown), - std::move(password_dropdown), - std::move(password_view_button)); + std::move(password_dropdown)); // The |username_dropdown_| should observe the animating layout manager to // close the dropdown menu when the animation starts. @@ -522,23 +493,6 @@ MaybeShowIPH(IPHType::kRegular); } -void PasswordSaveUpdateView::OnThemeChanged() { - PasswordBubbleViewBase::OnThemeChanged(); - if (password_view_button_) { - const auto* color_provider = GetColorProvider(); - const SkColor icon_color = color_provider->GetColor(ui::kColorIcon); - const SkColor disabled_icon_color = - color_provider->GetColor(ui::kColorIconDisabled); - views::SetImageFromVectorIconWithColor(password_view_button_, kEyeIcon, - GetDefaultSizeOfVectorIcon(kEyeIcon), - icon_color, disabled_icon_color); - views::SetToggledImageFromVectorIconWithColor( - password_view_button_, kEyeCrossedIcon, - GetDefaultSizeOfVectorIcon(kEyeCrossedIcon), icon_color, - disabled_icon_color); - } -} - void PasswordSaveUpdateView::OnLayoutIsAnimatingChanged( views::AnimatingLayoutManager* source, bool is_animating) { @@ -546,16 +500,6 @@ MaybeShowIPH(IPHType::kRegular); } -void PasswordSaveUpdateView::TogglePasswordVisibility() { - if (!are_passwords_revealed_ && !controller_.RevealPasswords()) - return; - - are_passwords_revealed_ = !are_passwords_revealed_; - password_view_button_->SetToggled(are_passwords_revealed_); - DCHECK(password_dropdown_); - password_dropdown_->RevealPasswords(are_passwords_revealed_); -} - void PasswordSaveUpdateView::UpdateUsernameAndPasswordInModel() { if (!username_dropdown_ && !password_dropdown_) return;
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.h b/chrome/browser/ui/views/passwords/password_save_update_view.h index ca5eff8..8f516b22 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_view.h +++ b/chrome/browser/ui/views/passwords/password_save_update_view.h
@@ -19,7 +19,7 @@ class AnimatingLayoutManager; class Combobox; class EditableCombobox; -class ToggleImageButton; +class EditablePasswordCombobox; } // namespace views // A view offering the user the ability to save or update credentials (depending @@ -64,13 +64,10 @@ // View: void AddedToWidget() override; - void OnThemeChanged() override; // views::AnimatingLayoutManager::Observer: void OnLayoutIsAnimatingChanged(views::AnimatingLayoutManager* source, bool is_animating) override; - - void TogglePasswordVisibility(); void UpdateUsernameAndPasswordInModel(); void UpdateBubbleUIElements(); std::unique_ptr<views::View> CreateFooterView(); @@ -105,12 +102,9 @@ raw_ptr<views::Combobox> destination_dropdown_ = nullptr; + // The views for the username and password dropdown elements. raw_ptr<views::EditableCombobox> username_dropdown_ = nullptr; - raw_ptr<views::ToggleImageButton> password_view_button_ = nullptr; - - // The view for the password value. - raw_ptr<views::EditableCombobox> password_dropdown_ = nullptr; - bool are_passwords_revealed_; + raw_ptr<views::EditablePasswordCombobox> password_dropdown_ = nullptr; // When showing kReauthFailure IPH, the promo controller gives back an // ID. This is used to close the bubble later.
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc index 707f99c..a30a693 100644 --- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc +++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view.cc
@@ -105,7 +105,7 @@ } TabDiscardTabHelper* const tab_helper = TabDiscardTabHelper::FromWebContents(web_contents); - if (tab_helper->IsChipVisible() && is_high_efficiency_mode_enabled_) { + if (tab_helper->ShouldChipBeVisible() && is_high_efficiency_mode_enabled_) { SetVisible(true); if (tab_helper->ShouldIconAnimate()) { // Only animate the chip to the expanded view the first 3 times it is
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc index 1c109589..39ec8fd 100644 --- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc +++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_browsertest.cc
@@ -1,4 +1,4 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. +// 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. @@ -23,6 +23,7 @@ #include "chrome/browser/ui/views/user_education/browser_feature_promo_controller.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/feature_list.h" #include "components/performance_manager/public/decorators/process_metrics_decorator.h" @@ -32,8 +33,9 @@ #include "components/user_education/views/help_bubble_factory_views.h" #include "components/user_education/views/help_bubble_view.h" #include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/mock_navigation_handle.h" -#include "content/public/test/test_navigation_observer.h" +#include "net/dns/mock_host_resolver.h" #include "ui/base/page_transition_types.h" #include "ui/base/text/bytes_formatting.h" #include "ui/views/animation/ink_drop.h" @@ -93,10 +95,16 @@ resource_coordinator::GetTabLifecycleUnitSource() ->SetFocusedTabStripModelForTesting(browser()->tab_strip_model()); - ASSERT_TRUE(AddTabAtIndex(0, GURL(chrome::kChromeUINewTabURL), - ui::PAGE_TRANSITION_TYPED)); - ASSERT_TRUE(AddTabAtIndex(1, GURL(chrome::kChromeUINewTabURL), - ui::PAGE_TRANSITION_TYPED)); + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + ui_test_utils::NavigateToURLWithDisposition( + browser(), test_url, WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + + ui_test_utils::NavigateToURLWithDisposition( + browser(), test_url, WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); } void TearDown() override { InProcessBrowserTest::TearDown(); } @@ -220,13 +228,13 @@ EXPECT_TRUE(GetFeaturePromoController()->IsPromoActive( feature_engagement::kIPHHighEfficiencyInfoModeFeature)); - content::TestNavigationObserver navigation_observer( - browser()->tab_strip_model()->GetWebContentsAt(0)); ClickIPHSettingsButton(); - navigation_observer.Wait(); - + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(3, tab_strip_model->count()); + content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(2); + WaitForLoadStop(web_contents); GURL expected(chrome::kChromeUIPerformanceSettingsURL); - EXPECT_EQ(expected.host(), navigation_observer.last_navigation_url().host()); + EXPECT_EQ(expected.host(), web_contents->GetLastCommittedURL().host()); } IN_PROC_BROWSER_TEST_F(HighEfficiencyChipViewBrowserTest, @@ -273,6 +281,7 @@ IN_PROC_BROWSER_TEST_F(HighEfficiencyChipViewBrowserTest, BubbleCorrectlyReportingMemorySaved) { + auto lock = BrowserFeaturePromoController::BlockActiveWindowCheckForTesting(); ForceRefreshMemoryMetricsForTesting(); DiscardTabAt(0); content::WebContents* web_contents = @@ -280,14 +289,14 @@ auto* pre_discard_resource_usage = performance_manager::user_tuning::UserPerformanceTuningManager:: PreDiscardResourceUsage::FromWebContents(web_contents); - int resident_set_kb = + int memory_footprint_estimate = pre_discard_resource_usage->memory_footprint_estimate_kb(); chrome::SelectNumberedTab(browser(), 0); - content::WaitForLoadStop( - browser()->tab_strip_model()->GetActiveWebContents()); + WaitForIPHToShow(); ClickHighEfficiencyChip(); views::StyledLabel* label = GetHighEfficiencyBubbleLabel(); - EXPECT_NE(label->GetText().find(ui::FormatBytes(resident_set_kb * 1024)), - std::string::npos); + EXPECT_NE( + label->GetText().find(ui::FormatBytes(memory_footprint_estimate * 1024)), + std::string::npos); }
diff --git a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_interactive_ui_test.cc b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_interactive_ui_test.cc index e765aaf..8b66d3b 100644 --- a/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_interactive_ui_test.cc +++ b/chrome/browser/ui/views/performance_controls/high_efficiency_chip_view_interactive_ui_test.cc
@@ -27,6 +27,7 @@ #include "components/user_education/views/help_bubble_view.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" #include "ui/base/interaction/element_identifier.h" #include "ui/views/controls/styled_label.h" #include "ui/views/interaction/element_tracker_views.h" @@ -62,7 +63,7 @@ void SetUpOnMainThread() override { InteractiveBrowserTest::SetUpOnMainThread(); - + host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(embedded_test_server()->Start()); tab_strip_model_ = browser()->tab_strip_model(); test_url_ = embedded_test_server()->GetURL("a.com", "/title1.html"); @@ -220,6 +221,23 @@ SelectTab(kTabStripElementId, 1), CheckChipIsCollapsedState()); } +// Page Action chip should only show on discarded non-chrome pages +IN_PROC_BROWSER_TEST_F(HighEfficiencyChipInteractiveTest, + ChipShowsOnNonChromeSites) { + RunTestSequence(InstrumentTab(kFirstTabContents, 0), + NavigateTab(test_url_, kFirstTabContents), + AddInstrumentedTab(kSecondTabContents, + GURL(chrome::kChromeUINewTabURL), 1), + // Discards tab on non-chrome page + SelectTab(kTabStripElementId, 1), + DiscardAndSelectTab(0, kFirstTabContents), + WaitForShow(kHighEfficiencyChipElementId), + + // Discards tab on chrome://newtab page + DiscardAndSelectTab(1, kSecondTabContents), + EnsureNotPresent(kHighEfficiencyChipElementId)); +} + // Clicking on the settings link in high efficiency dialog bubble should open // a new tab and navigate to the performance settings page IN_PROC_BROWSER_TEST_F(HighEfficiencyChipInteractiveTest,
diff --git a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view.cc b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view.cc index 59dd8044..bdb3bf66 100644 --- a/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view.cc +++ b/chrome/browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view.cc
@@ -31,7 +31,7 @@ constexpr int kM1DialogWidth = 600; constexpr int kDefaultConsentDialogHeight = 569; constexpr int kDefaultNoticeDialogHeight = 494; -constexpr int kMinDialogHeight = 300; +constexpr int kMinRequiredDialogHeight = 100; GURL GetDialogURL(PrivacySandboxService::PromptType prompt_type) { GURL base_url = GURL(chrome::kChromeUIPrivacySandboxDialogURL); @@ -101,6 +101,15 @@ } // namespace // static +bool CanWindowFitPrivacySandboxPrompt(Browser* browser) { + const int max_dialog_height = browser->window() + ->GetWebContentsModalDialogHost() + ->GetMaximumDialogSize() + .height(); + return max_dialog_height >= kMinRequiredDialogHeight; +} + +// static void ShowPrivacySandboxDialog(Browser* browser, PrivacySandboxService::PromptType prompt_type) { auto delegate = std::make_unique<PrivacySandboxDialogDelegate>(browser); @@ -133,13 +142,16 @@ zoom_map->SetTemporaryZoomLevel(rfh->GetGlobalId(), blink::PageZoomFactorToZoomLevel(1.0f)); - auto width = views::LayoutProvider::Get()->GetSnappedDialogWidth( + const int max_width = browser_->window() + ->GetWebContentsModalDialogHost() + ->GetMaximumDialogSize() + .width(); + const int width = views::LayoutProvider::Get()->GetSnappedDialogWidth( GetDialogWidth(prompt_type)); - // TODO(crbug.com/1378703): Adjust default values for new prompt types. - auto height = prompt_type == PrivacySandboxService::PromptType::kConsent - ? kDefaultConsentDialogHeight - : kDefaultNoticeDialogHeight; - web_view_->SetPreferredSize(gfx::Size(width, height)); + const int height = prompt_type == PrivacySandboxService::PromptType::kConsent + ? kDefaultConsentDialogHeight + : kDefaultNoticeDialogHeight; + web_view_->SetPreferredSize(gfx::Size(std::min(width, max_width), height)); PrivacySandboxDialogUI* web_ui = web_view_->GetWebContents() ->GetWebUI() @@ -172,8 +184,7 @@ .height(); const int target_height = std::min(height, max_height); web_view_->SetPreferredSize( - gfx::Size(web_view_->GetPreferredSize().width(), - std::max(kMinDialogHeight, target_height))); + gfx::Size(web_view_->GetPreferredSize().width(), target_height)); GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize()); }
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.cc b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.cc index 08a8c45..5b46401 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.cc +++ b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.cc
@@ -74,10 +74,15 @@ if (visible) { browser_view->side_panel_coordinator()->Show( SidePanelEntry::Id::kCustomizeChrome); + if (customize_chrome_ui_) { + customize_chrome_ui_->ScrollToSection(section); + section_.reset(); + } else { + section_ = section; + } } else { browser_view->side_panel_coordinator()->Close(); } - // TODO(crbug.com/1402251): Scroll to requested `section`. } bool CustomizeChromeSidePanelController::IsCustomizeChromeEntryShowing() const { @@ -122,6 +127,13 @@ /*webui_resizes_host=*/false, /*esc_closes_ui=*/false)); customize_chrome_web_view->ShowUI(); + customize_chrome_ui_ = customize_chrome_web_view->contents_wrapper() + ->GetWebUIController() + ->GetWeakPtr(); + if (section_.has_value()) { + customize_chrome_ui_->ScrollToSection(*section_); + section_.reset(); + } return customize_chrome_web_view; }
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.h b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.h index de37faf..a83f7db 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.h +++ b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_side_panel_controller.h
@@ -11,6 +11,8 @@ #include "chrome/browser/ui/views/side_panel/side_panel_entry_observer.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" +class CustomizeChromeUI; + namespace content { class WebContents; } // namespace content @@ -49,6 +51,10 @@ BrowserView* GetBrowserView() const; const raw_ptr<content::WebContents> web_contents_; + base::WeakPtr<CustomizeChromeUI> customize_chrome_ui_; + // Caches a request to scroll to a section in case the request happens before + // the front-end is ready to receive the request. + absl::optional<CustomizeChromeSection> section_; }; #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_SIDE_PANEL_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller_unittest.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller_unittest.cc index 5295bc7..98e69f83 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller_unittest.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_controller_unittest.cc
@@ -97,7 +97,7 @@ }; TEST_F(ReadAnythingControllerTest, ValidIndexUpdatesFontNamePref) { - std::string expected_font_name = "Avenir"; + std::string expected_font_name = "Arial"; MockOnFontChoiceChanged(3);
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc index a32afc3..fa2c8fb 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
@@ -177,14 +177,13 @@ /////////////////////////////////////////////////////////////////////////////// ReadAnythingFontModel::ReadAnythingFontModel() { - // TODO(1266555): i18n. + // TODO(1266555): i18n and replace temp fonts with finalized fonts. font_choices_.emplace_back(u"Standard font"); font_choices_.emplace_back(u"Sans-serif"); font_choices_.emplace_back(u"Serif"); - font_choices_.emplace_back(u"Avenir"); - font_choices_.emplace_back(u"Comic Neue"); + font_choices_.emplace_back(u"Arial"); font_choices_.emplace_back(u"Comic Sans MS"); - font_choices_.emplace_back(u"Poppins"); + font_choices_.emplace_back(u"Times New Roman"); font_choices_.shrink_to_fit(); }
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc index 00a7aa3..fbbafde4 100644 --- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc +++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model_unittest.cc
@@ -216,10 +216,9 @@ EXPECT_TRUE(GetFontModel()->IsValidFontName("Standard font")); EXPECT_TRUE(GetFontModel()->IsValidFontName("Sans-serif")); EXPECT_TRUE(GetFontModel()->IsValidFontName("Serif")); - EXPECT_TRUE(GetFontModel()->IsValidFontName("Avenir")); - EXPECT_TRUE(GetFontModel()->IsValidFontName("Comic Neue")); + EXPECT_TRUE(GetFontModel()->IsValidFontName("Arial")); EXPECT_TRUE(GetFontModel()->IsValidFontName("Comic Sans MS")); - EXPECT_TRUE(GetFontModel()->IsValidFontName("Poppins")); + EXPECT_TRUE(GetFontModel()->IsValidFontName("Times New Roman")); EXPECT_FALSE(GetFontModel()->IsValidFontName("xxyyzz")); } @@ -227,10 +226,9 @@ EXPECT_EQ("Standard font", GetFontModel()->GetFontNameAt(0)); EXPECT_EQ("Sans-serif", GetFontModel()->GetFontNameAt(1)); EXPECT_EQ("Serif", GetFontModel()->GetFontNameAt(2)); - EXPECT_EQ("Avenir", GetFontModel()->GetFontNameAt(3)); - EXPECT_EQ("Comic Neue", GetFontModel()->GetFontNameAt(4)); - EXPECT_EQ("Comic Sans MS", GetFontModel()->GetFontNameAt(5)); - EXPECT_EQ("Poppins", GetFontModel()->GetFontNameAt(6)); + EXPECT_EQ("Arial", GetFontModel()->GetFontNameAt(3)); + EXPECT_EQ("Comic Sans MS", GetFontModel()->GetFontNameAt(4)); + EXPECT_EQ("Times New Roman", GetFontModel()->GetFontNameAt(5)); } #endif // !defined(ADDRESS_SANITIZER)
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc b/chrome/browser/ui/views/side_search/side_search_browser_controller.cc deleted file mode 100644 index 208ea6f..0000000 --- a/chrome/browser/ui/views/side_search/side_search_browser_controller.cc +++ /dev/null
@@ -1,659 +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 "chrome/browser/ui/views/side_search/side_search_browser_controller.h" - -#include "base/functional/bind.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/raw_ref.h" -#include "base/strings/utf_string_conversions.h" -#include "build/branding_buildflags.h" -#include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/feature_engagement/tracker_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser_element_identifiers.h" -#include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/ui/color/chrome_color_id.h" -#include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/page_action/page_action_icon_type.h" -#include "chrome/browser/ui/side_search/side_search_utils.h" -#include "chrome/browser/ui/ui_features.h" -#include "chrome/browser/ui/view_ids.h" -#include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/side_panel/side_panel.h" -#include "chrome/browser/ui/views/side_search/default_search_icon_source.h" -#include "chrome/browser/ui/views/toolbar/toolbar_button.h" -#include "chrome/grit/generated_resources.h" -#include "components/feature_engagement/public/event_constants.h" -#include "components/feature_engagement/public/feature_constants.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/url_formatter/elide_url.h" -#include "components/user_education/common/feature_promo_controller.h" -#include "components/vector_icons/vector_icons.h" -#include "content/public/browser/navigation_handle.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/metadata/metadata_header_macros.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/base/pointer/touch_ui_controller.h" -#include "ui/color/color_id.h" -#include "ui/gfx/image/canvas_image_source.h" -#include "ui/views/animation/ink_drop.h" -#include "ui/views/background.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/image_button_factory.h" -#include "ui/views/controls/highlight_path_generator.h" -#include "ui/views/controls/label.h" -#include "ui/views/controls/separator.h" -#include "ui/views/controls/webview/webview.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/layout/flex_layout_types.h" -#include "ui/views/layout/flex_layout_view.h" -#include "ui/views/layout/layout_provider.h" -#include "ui/views/layout/layout_types.h" -#include "ui/views/view_class_properties.h" - -namespace { - -constexpr int kDefaultTouchableIconSize = 24; - -// Base header button class. Responds appropriately to touch ui changes. -class HeaderButton : public views::ImageButton { - public: - METADATA_HEADER(HeaderButton); - HeaderButton(const gfx::VectorIcon& icon, base::RepeatingClosure callback) - : ImageButton(std::move(callback)), icon_(icon) { - views::ConfigureVectorImageButton(this); - - SetBorder(views::CreateEmptyBorder( - gfx::Insets(views::LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_CLOSE_BUTTON_MARGIN)))); - - UpdateIcon(); - } - ~HeaderButton() override = default; - - // views::ImageButton: - void OnThemeChanged() override { - ImageButton::OnThemeChanged(); - views::InkDrop::Get(this)->SetBaseColor( - GetColorProvider()->GetColor(ui::kColorIcon)); - } - - void UpdateIcon() { - const int icon_size = - ui::TouchUiController::Get()->touch_ui() - ? kDefaultTouchableIconSize - : ChromeLayoutProvider::Get()->GetDistanceMetric( - ChromeDistanceMetric:: - DISTANCE_SIDE_PANEL_HEADER_VECTOR_ICON_SIZE); - SetImageModel(Button::STATE_NORMAL, ui::ImageModel::FromVectorIcon( - *icon_, ui::kColorIcon, icon_size)); - SetImageModel(Button::STATE_DISABLED, - ui::ImageModel::FromVectorIcon(*icon_, ui::kColorIconDisabled, - icon_size)); - } - - private: - const raw_ref<const gfx::VectorIcon> icon_; -}; - -BEGIN_METADATA(HeaderButton, views::ImageButton) -END_METADATA - -// A view that tracks the icon image of the current DSE. -class DseImageView : public views::ImageView { - public: - METADATA_HEADER(DseImageView); - explicit DseImageView(Browser* browser) - : browser_(browser), - icon_changed_subscription_( - DefaultSearchIconSource::GetOrCreateForBrowser(browser) - ->RegisterIconChangedSubscription( - base::BindRepeating(&DseImageView::UpdateIconImage, - base::Unretained(this)))) { - SetFlipCanvasOnPaintForRTLUI(false); - SetBorder(views::CreateEmptyBorder( - gfx::Insets::VH(0, views::LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_VERTICAL)))); - UpdateIconImage(); - } - ~DseImageView() override = default; - - void UpdateIconImage() { - // Attempt to get the default search engine's favicon. - auto* default_search_icon_source = - DefaultSearchIconSource::GetOrCreateForBrowser(browser_); - auto icon_image = default_search_icon_source->GetIconImage(); - - // Use the DSE's icon image if available. - if (!icon_image.IsEmpty()) { - SetImage(default_search_icon_source->GetIconImage()); - return; - } - - // If the icon image is empty use kSearchIcon as a default. It is not - // guaranteed that the FaviconService will return a favicon for the search - // provider. - const int icon_size = - ui::TouchUiController::Get()->touch_ui() - ? kDefaultTouchableIconSize - : ChromeLayoutProvider::Get()->GetDistanceMetric( - ChromeDistanceMetric:: - DISTANCE_SIDE_PANEL_HEADER_VECTOR_ICON_SIZE); - SetImage(ui::ImageModel::FromVectorIcon(vector_icons::kSearchIcon, - ui::kColorIcon, icon_size)); - } - - private: - const raw_ptr<Browser> browser_; - - // Subscription to change notifications to the default search icon source. - base::CallbackListSubscription icon_changed_subscription_; -}; - -BEGIN_METADATA(DseImageView, views::ImageView) -END_METADATA - -// Header view for the side search side panel. The structure is as follows. -// ___________________________________________________________________________ -// | dse_image_view | simple_site_name | feedback_button | close_button | -// | -// ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ -// The image view and buttons are fixed at their preferred size. The simple site -// name label is configured to consume the remaining horizontal space. -class HeaderView : public views::View { - public: - METADATA_HEADER(HeaderView); - HeaderView(base::RepeatingClosure callback, Browser* browser) - : layout_(SetLayoutManager(std::make_unique<views::FlexLayout>())) { - constexpr int kHeaderHeight = 44; - SetPreferredSize(gfx::Size(0, kHeaderHeight)); - - constexpr int kHorizontalMargin = 8; - layout_->SetOrientation(views::LayoutOrientation::kHorizontal) - .SetMainAxisAlignment(views::LayoutAlignment::kStart) - .SetCrossAxisAlignment(views::LayoutAlignment::kCenter) - .SetInteriorMargin(gfx::Insets::VH(0, kHorizontalMargin)); - - dse_image_view_ = AddChildView(std::make_unique<DseImageView>(browser)); - dse_image_view_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, - views::MaximumFlexSizeRule::kPreferred)); - - title_label_ = AddChildView(std::make_unique<views::Label>()); - title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - title_label_->SetTextContext(CONTEXT_SIDE_PANEL_TITLE); - title_label_->SetTextStyle(views::style::STYLE_PRIMARY); - title_label_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, - views::MaximumFlexSizeRule::kUnbounded)); - - if (base::FeatureList::IsEnabled(features::kSideSearchFeedback)) { - base::RepeatingClosure feedback_callback = base::BindRepeating( - [](Browser* browser) { - chrome::ShowFeedbackPage( - browser, chrome::FeedbackSource::kFeedbackSourceChromeLabs, - std::string() /* description_template */, - l10n_util::GetStringFUTF8( - IDS_CHROMELABS_SEND_FEEDBACK_DESCRIPTION_PLACEHOLDER, - l10n_util::GetStringUTF16(IDS_ACCNAME_SIDE_SEARCH_TOOL)), - std::string("chrome-labs-side-search"), - std::string() /* extra_diagnostics */); - }, - browser); - - feedback_button_ = - AddChildViewAt(std::make_unique<HeaderButton>( - kSubmitFeedbackIcon, std::move(feedback_callback)), - 0); - feedback_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_SIDE_SEARCH_FEEDBACK_BUTTON)); - feedback_button_->SetTooltipText( - l10n_util::GetStringUTF16(IDS_TOOLTIP_SIDE_SEARCH_FEEDBACK_BUTTON)); - feedback_button_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, - views::MaximumFlexSizeRule::kPreferred)); - } - - close_button_ = AddChildView(std::make_unique<HeaderButton>( - vector_icons::kCloseIcon, std::move(callback))); - views::InstallCircleHighlightPathGenerator(close_button_); - close_button_->SetProperty(views::kElementIdentifierKey, - kSidePanelCloseButtonElementId); - close_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_SIDE_SEARCH_CLOSE_BUTTON)); - close_button_->SetTooltipText( - l10n_util::GetStringUTF16(IDS_TOOLTIP_SIDE_SEARCH_CLOSE_BUTTON)); - close_button_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, - views::MaximumFlexSizeRule::kPreferred)); - - // Ensure the header view's containing view keeps its vertical size at the - // preferred size when laying out the side panel. The side panel does this - // using a flex layout so we need to ensure we set the correct flex - // behavior. - SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, - views::MaximumFlexSizeRule::kPreferred)); - SetBackground( - views::CreateThemedSolidBackground(ui::kColorDialogBackground)); - UpdateSpacing(); - } - ~HeaderView() override = default; - - views::Label* get_title_label() { return title_label_; } - - private: - // Updates the toolbar insets which may change as we enter / leave touch mode. - // Icons are also updated to give them the opportunity to resize and adjust - // their insets. - void UpdateSpacing() { - dse_image_view_->UpdateIconImage(); - if (feedback_button_) - feedback_button_->UpdateIcon(); - close_button_->UpdateIcon(); - } - - raw_ptr<DseImageView> dse_image_view_ = nullptr; - raw_ptr<views::Label> title_label_ = nullptr; - raw_ptr<HeaderButton> feedback_button_ = nullptr; - raw_ptr<HeaderButton> close_button_ = nullptr; - - raw_ptr<views::FlexLayout> const layout_; - - // Used to listen for when the UI enters / leaves touch mode. - base::CallbackListSubscription subscription_ = - ui::TouchUiController::Get()->RegisterCallback( - base::BindRepeating(&HeaderView::UpdateSpacing, - base::Unretained(this))); -}; - -BEGIN_METADATA(HeaderView, views::View) -END_METADATA - -} // namespace - -SideSearchBrowserController::SideSearchBrowserController( - SidePanel* side_panel, - BrowserView* browser_view) - : side_panel_(side_panel), - browser_view_(browser_view), - focus_tracker_(side_panel_, browser_view_->GetFocusManager()) { - auto container = std::make_unique<views::FlexLayoutView>(); - container->SetOrientation(views::LayoutOrientation::kVertical); - container->SetCrossAxisAlignment(views::LayoutAlignment::kStretch); - auto* header_view = container->AddChildView(std::make_unique<HeaderView>( - base::BindRepeating( - &SideSearchBrowserController::SidePanelCloseButtonPressed, - base::Unretained(this)), - browser_view_->browser())); - title_label_ = header_view->get_title_label(); - container->AddChildView(std::make_unique<views::Separator>()); - - // The WebView will fill the remaining space after the header view has been - // laid out. - web_view_ = container->AddChildView( - std::make_unique<views::WebView>(browser_view_->GetProfile())); - web_view_->SetProperty( - views::kFlexBehaviorKey, - views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, - views::MaximumFlexSizeRule::kUnbounded)); - web_view_->SetBackground(views::CreateThemedSolidBackground(kColorToolbar)); - - side_panel_->AddChildView(std::move(container)); - - // The side panel should not start visible to avoid having it participate in - // initial layout calculations. Its visibility state will be updated later on - // in UpdateSidePanel(). - side_panel_->SetVisible(false); - - web_view_visibility_subscription_ = - web_view_->AddVisibleChangedCallback(base::BindRepeating( - &SideSearchBrowserController::OnWebViewVisibilityChanged, - base::Unretained(this))); - - browser_view_observation_.Observe(browser_view_); - UpdateSidePanelForContents(browser_view_->GetActiveWebContents(), nullptr); -} - -SideSearchBrowserController::~SideSearchBrowserController() { - Observe(nullptr); -} - -bool SideSearchBrowserController::HandleKeyboardEvent( - content::WebContents* source, - const content::NativeWebKeyboardEvent& event) { - return unhandled_keyboard_event_handler_.HandleKeyboardEvent( - event, browser_view_->GetFocusManager()); -} - -content::WebContents* SideSearchBrowserController::OpenURLFromTab( - content::WebContents* source, - const content::OpenURLParams& params) { - return browser_view_->browser()->OpenURL(params); -} - -void SideSearchBrowserController::SidePanelAvailabilityChanged( - bool should_close) { - if (should_close) { - CloseSidePanel(); - } else { - UpdateSidePanel(); - } -} - -void SideSearchBrowserController::DidFinishNavigation( - content::NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInPrimaryMainFrame() || - navigation_handle->IsSameDocument() || - !navigation_handle->HasCommitted()) { - return; - } - - // The toggled state of the side panel for this tab contents should be reset - // when landing on a page that should not show the side panel (e.g. NTP, - // Google home page etc). This will prevent the side panel from reopening - // automatically after the tab next encounters a page where the side panel can - // be shown. - auto* tab_contents_helper = SideSearchTabContentsHelper::FromWebContents( - navigation_handle->GetWebContents()); - if (!tab_contents_helper) - return; - - if (GetSidePanelToggledOpen() && - !tab_contents_helper->CanShowSidePanelForCommittedNavigation()) { - CloseSidePanel(); - return; - } - - // We need to update the side panel state in response to navigations to catch - // cases where the user navigates to a page that should have the side panel - // hidden (e.g. the Google home page). - UpdateSidePanel(); -} - -void SideSearchBrowserController::OnViewAddedToWidget( - views::View* observed_view) { - DCHECK_EQ(browser_view_, observed_view); - focus_tracker_.SetFocusManager(browser_view_->GetFocusManager()); -} - -void SideSearchBrowserController::UpdateSidePanelForContents( - content::WebContents* new_contents, - content::WebContents* old_contents) { - // Ensure that the controller acts as the delegate only to the currently - // active contents. - if (old_contents) { - auto* helper = SideSearchTabContentsHelper::FromWebContents(old_contents); - if (helper) - helper->SetDelegate(nullptr); - } - if (new_contents) { - auto* helper = SideSearchTabContentsHelper::FromWebContents(new_contents); - if (helper) - helper->SetDelegate(weak_factory_.GetWeakPtr()); - } - - Observe(new_contents); - - // Update the state of the side panel to catch cases where we switch to a tab - // where the panel should be hidden (or vise versa). - UpdateSidePanel(); -} - -std::unique_ptr<ToolbarButton> -SideSearchBrowserController::CreateToolbarButton() { - auto toolbar_button = std::make_unique<ToolbarButton>(); - toolbar_button->SetAccessibleName(l10n_util::GetStringUTF16( - IDS_ACCNAME_SIDE_SEARCH_TOOLBAR_BUTTON_NOT_ACTIVATED)); - toolbar_button->SetTooltipText(l10n_util::GetStringUTF16( - IDS_TOOLTIP_SIDE_SEARCH_TOOLBAR_BUTTON_NOT_ACTIVATED)); - toolbar_button->SetProperty(views::kElementIdentifierKey, - kSideSearchButtonElementId); - -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) - toolbar_button->SetVectorIcon(vector_icons::kGoogleGLogoMonochromeIcon); -#else - toolbar_button->SetVectorIcon(kWebIcon); -#endif - - toolbar_button->SetCallback(base::BindRepeating( - &SideSearchBrowserController::ToggleSidePanel, base::Unretained(this))); - toolbar_button->SetVisible(false); - toolbar_button->SetEnabled(true); - - toolbar_button_ = toolbar_button.get(); - return toolbar_button; -} - -void SideSearchBrowserController::ToggleSidePanel() { - if (GetSidePanelToggledOpen()) - CloseSidePanel(SideSearchCloseActionType::kTapOnSideSearchToolbarButton); - else - OpenSidePanel(); -} - -bool SideSearchBrowserController::GetSidePanelToggledOpen() const { - auto* active_contents = browser_view_->GetActiveWebContents(); - if (!active_contents) - return false; - - const auto* helper = - SideSearchTabContentsHelper::FromWebContents(active_contents); - return helper ? helper->toggled_open() : false; -} - -void SideSearchBrowserController::SidePanelCloseButtonPressed() { - CloseSidePanel(SideSearchCloseActionType::kTapOnSideSearchCloseButton); -} - -void SideSearchBrowserController::OpenSidePanel() { - RecordSideSearchOpenAction( - SideSearchOpenActionType::kTapOnSideSearchToolbarButton); - RecordSidePanelOpenedMetrics(); - - shown_via_entrypoint_ = true; - - // Close the Side Search IPH if it is showing. - browser_view_->CloseFeaturePromo(feature_engagement::kIPHSideSearchFeature); - auto* tracker = feature_engagement::TrackerFactory::GetForBrowserContext( - browser_view_->GetProfile()); - if (tracker) - tracker->NotifyEvent(feature_engagement::events::kSideSearchOpened); - - SetSidePanelToggledOpen(true); - UpdateSidePanel(); - - // After showing the side panel if the web_view_ is visible request focus. - if (web_view_->GetVisible() && web_view_->web_contents()) - web_view_->web_contents()->Focus(); -} - -void SideSearchBrowserController::CloseSidePanel( - absl::optional<SideSearchCloseActionType> action) { - if (action) - RecordSideSearchCloseAction(action.value()); - - focus_tracker_.FocusLastFocusedExternalView(); - SetSidePanelToggledOpen(false); - UpdateSidePanel(); - - // Clear the side contents for the currently active tab. - ClearSideContentsCacheForActiveTab(); -} - -void SideSearchBrowserController::ClobberAllInCurrentBrowser() { - auto* tab_strip_model = browser_view_->browser()->tab_strip_model(); - for (int i = 0; i < tab_strip_model->count(); ++i) { - auto* helper = SideSearchTabContentsHelper::FromWebContents( - tab_strip_model->GetWebContentsAt(i)); - if (helper) - helper->set_toggled_open(false); - } -} - -void SideSearchBrowserController::ClearSideContentsCacheForActiveTab() { - web_view_->SetWebContents(nullptr); - - if (auto* active_contents = browser_view_->GetActiveWebContents()) { - auto* helper = - SideSearchTabContentsHelper::FromWebContents(active_contents); - if (helper) - helper->ClearSidePanelContents(); - } -} - -void SideSearchBrowserController::SetSidePanelToggledOpen(bool toggled_open) { - if (auto* active_contents = browser_view_->GetActiveWebContents()) { - auto* helper = - SideSearchTabContentsHelper::FromWebContents(active_contents); - if (helper) { - helper->set_toggled_open(toggled_open); - side_search::MaybeSaveSideSearchTabSessionData(active_contents); - } - } -} - -void SideSearchBrowserController::UpdateSidePanel() { - auto* active_contents = browser_view_->GetActiveWebContents(); - if (!active_contents) { - // Ensure we reset the `web_view_`'s hosted side contents when the active - // tab contents is null to cover cases such as the tab being moved to - // another window. This is needed as the WebView's destructor will not be - // invoked until both the remove model update is fired in this window and - // the add model update is fired in the destination window. - web_view_->SetWebContents(nullptr); - return; - } - - // Switch the WebContents currently in the windows side panel to the - // WebContents associated with the active tab. - auto* tab_contents_helper = - SideSearchTabContentsHelper::FromWebContents(active_contents); - - // Early return if the tab helper for the active tab is not defined - // (crbug.com/1307908). - if (!tab_contents_helper) - return; - - const bool can_show_side_panel_for_page = - tab_contents_helper->CanShowSidePanelForCommittedNavigation(); - const bool will_show_side_panel = - can_show_side_panel_for_page && GetSidePanelToggledOpen(); - - // When side search is shown we only need to close other side panels for the - // basic clobbering experience. The improved experience leverages a - // SidePanelVisibilityController on the browser view. - if (will_show_side_panel) { - browser_view_->CloseOpenRightAlignedSidePanel(/*exclude_side_search=*/true); - } - - // The side panel contents will be created if it does not already exist. - const auto* previous_hosted_contents = web_view_->web_contents(); - web_view_->SetWebContents(will_show_side_panel - ? tab_contents_helper->GetSidePanelContents() - : nullptr); - - // Log time shown metrics whenever a new contents is hosted in the side panel. - if (previous_hosted_contents != web_view_->web_contents()) { - // If we were hosting a side panel contents, log its open duration. - if (previous_hosted_contents) { - DCHECK(side_panel_shown_timer_); - RecordSideSearchSidePanelTimeShown(shown_via_entrypoint_, - side_panel_shown_timer_->Elapsed()); - } - - // Reset the `shown_via_entrypoint_` flag only if we were previously hosting - // a side panel contents. Do this to avoid prematurely resetting the flag - // when the side panel is first shown before the shown duration is logged. - if (previous_hosted_contents) - shown_via_entrypoint_ = false; - - // If hosting a new side panel contents start a new timer. If no longer - // hosting a side panel contents clear the timer. - DCHECK_EQ(will_show_side_panel, !!web_view_->web_contents()); - if (web_view_->web_contents()) { - side_panel_shown_timer_ = base::ElapsedTimer(); - } else { - side_panel_shown_timer_.reset(); - } - } - - // Update the side panel header title text if necessary - if (auto last_search_url = tab_contents_helper->last_search_url()) { - title_label_->SetText( - url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains( - last_search_url.value())); - } - - side_panel_->SetVisible(will_show_side_panel); - - // Update the side panel entrypoints - either the page action or the toolbar - // button. - // TODO(tluk): Split the entrypoint implementations out into a separate class. - browser_view_->UpdatePageActionIcon(PageActionIconType::kSideSearch); - - if (toolbar_button_) { - toolbar_button_->SetHighlighted(will_show_side_panel); - toolbar_button_->SetAccessibleName(l10n_util::GetStringUTF16( - will_show_side_panel - ? IDS_ACCNAME_SIDE_SEARCH_TOOLBAR_BUTTON_ACTIVATED - : IDS_ACCNAME_SIDE_SEARCH_TOOLBAR_BUTTON_NOT_ACTIVATED)); - toolbar_button_->SetTooltipText(l10n_util::GetStringUTF16( - will_show_side_panel - ? IDS_TOOLTIP_SIDE_SEARCH_TOOLBAR_BUTTON_ACTIVATED - : IDS_TOOLTIP_SIDE_SEARCH_TOOLBAR_BUTTON_NOT_ACTIVATED)); - - // The toolbar button should remain visible in the toolbar as a side panel - // can be shown for the active tab. - if (toolbar_button_->GetVisible() != can_show_side_panel_for_page) - toolbar_button_->SetVisible(can_show_side_panel_for_page); - } - - if (was_side_panel_available_for_page_ != can_show_side_panel_for_page) { - RecordSideSearchAvailabilityChanged( - can_show_side_panel_for_page - ? SideSearchAvailabilityChangeType::kBecomeAvailable - : SideSearchAvailabilityChangeType::kBecomeUnavailable); - was_side_panel_available_for_page_ = can_show_side_panel_for_page; - } - - // Once the anchor element is visible, maybe show promo for the toolbar - // button. - if (toolbar_button_ && can_show_side_panel_for_page && - tab_contents_helper->returned_to_previous_srp_count() > 0) { - browser_view_->MaybeShowFeaturePromo( - feature_engagement::kIPHSideSearchFeature); - } - - browser_view_->InvalidateLayout(); -} - -void SideSearchBrowserController::OnWebViewVisibilityChanged() { - // After the web_view_ becomes visible have the side contents request focus. - // We need to do this in the web_view_'s visibility changed listener as the - // web_view_'s visibility state could be updated by the layout manager during - // layout and we should not do this until the web_view_ is visible. Layout is - // invalidated when we call UpdateSidePanel() but is scheduled asynchronously - // by the hosting Widget. - if (web_view_->GetVisible() && web_view_->web_contents()) - web_view_->web_contents()->Focus(); -} - -void SideSearchBrowserController::RecordSidePanelOpenedMetrics() { - auto* active_contents = browser_view_->GetActiveWebContents(); - if (!active_contents) - return; - - auto* helper = SideSearchTabContentsHelper::FromWebContents(active_contents); - if (helper) - helper->MaybeRecordDurationSidePanelAvailableToFirstOpen(); -}
diff --git a/chrome/browser/ui/views/side_search/side_search_browser_controller.h b/chrome/browser/ui/views/side_search/side_search_browser_controller.h deleted file mode 100644 index efd4147..0000000 --- a/chrome/browser/ui/views/side_search/side_search_browser_controller.h +++ /dev/null
@@ -1,142 +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 CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_ -#define CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_ - -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" -#include "base/timer/elapsed_timer.h" -#include "chrome/browser/ui/side_search/side_search_metrics.h" -#include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/views/controls/label.h" -#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" -#include "ui/views/focus/external_focus_tracker.h" -#include "ui/views/view.h" -#include "ui/views/view_observer.h" - -namespace views { -class WebView; -} // namespace views - -class BrowserView; -class SidePanel; -class ToolbarButton; - -// Responsible for managing the WebContents hosted in the browser's side panel -// for Side Search in addition to managing the state of the side panel itself. -class SideSearchBrowserController - : public SideSearchTabContentsHelper::Delegate, - public content::WebContentsObserver, - public views::ViewObserver { - public: - SideSearchBrowserController(SidePanel* side_panel, BrowserView* browser_view); - SideSearchBrowserController(const SideSearchBrowserController&) = delete; - SideSearchBrowserController& operator=(const SideSearchBrowserController&) = - delete; - ~SideSearchBrowserController() override; - - // SideSearchTabContentsHelper::Delegate: - bool HandleKeyboardEvent( - content::WebContents* source, - const content::NativeWebKeyboardEvent& event) override; - content::WebContents* OpenURLFromTab( - content::WebContents* source, - const content::OpenURLParams& params) override; - void SidePanelAvailabilityChanged(bool should_close) override; - void OpenSidePanel() override; - void CloseSidePanel( - absl::optional<SideSearchCloseActionType> action = absl::nullopt); - - // content::WebContentsObserver: - void DidFinishNavigation( - content::NavigationHandle* navigation_handle) override; - - // views::ViewObserver: - void OnViewAddedToWidget(views::View* observed_view) override; - - void UpdateSidePanelForContents(content::WebContents* new_contents, - content::WebContents* old_contents); - - std::unique_ptr<ToolbarButton> CreateToolbarButton(); - - views::WebView* web_view_for_testing() { return web_view_; } - - bool GetSidePanelToggledOpen() const; - - // Toggles panel visibility. - void ToggleSidePanel(); - - // Clobbers all side search side panels in current browser. - void ClobberAllInCurrentBrowser(); - - private: - // Gets and sets the toggled state of the side panel. If called with - // kSideSearchStatePerTab enabled this determines whether the side panel - // should be open for the currently active tab. - void SetSidePanelToggledOpen(bool toggled_open); - - // Closes side panel on close button press. - void SidePanelCloseButtonPressed(); - - // Clears the side contents for the currently active tab in this browser - // window. - void ClearSideContentsCacheForActiveTab(); - - // Updates the `side_panel_`'s visibility and updates it to host the side - // contents associated with the currently active tab for this browser window. - void UpdateSidePanel(); - - // Callback invoked when the `web_view_`'s visibility state has changed. - // Visibility changes happens after we update the visibility of the - // `side_panel_` and a Layout() occurs. This can cause the side panel's layout - // manager to update the visibility of its web_view_ child. - void OnWebViewVisibilityChanged(); - - // Called after the side panel is toggled open to emit relevant UMA metrics. - void RecordSidePanelOpenedMetrics(); - - base::CallbackListSubscription web_view_visibility_subscription_; - - raw_ptr<ToolbarButton, DanglingUntriaged> toolbar_button_ = nullptr; - raw_ptr<SidePanel, DanglingUntriaged> const side_panel_; - raw_ptr<BrowserView, DanglingUntriaged> const browser_view_; - raw_ptr<views::Label, DanglingUntriaged> title_label_; - raw_ptr<views::WebView, DanglingUntriaged> web_view_; - - // Used to test whether or not the side panel was available the last time - // `UpdateSidePanel()` was called. i.e. whether the ability for the user to - // open/close the side panel has changed. This is used for metrics collection - // purposes. - bool was_side_panel_available_for_page_ = false; - - // The side panel for a given tab can be shown by having the user toggle it - // open via the entrypoint or by switching to a tab that already has its side - // panel in an open state. This tracks whether the current side panel was - // shown as the result of the user toggling it open via the entrypoint. - bool shown_via_entrypoint_ = false; - - // Time since the active tab's side panel contents was hosted in the side - // panel. - absl::optional<base::ElapsedTimer> side_panel_shown_timer_; - - // Tracks and stores the last focused view which is not the - // `side_panel_` or any of its children. Used to restore focus once - // the `side_panel_` is hidden. - views::ExternalFocusTracker focus_tracker_; - - // Observation on `browser_view_` used to track focus manager changes. - base::ScopedObservation<views::View, views::ViewObserver> - browser_view_observation_{this}; - - // A handler to handle unhandled keyboard messages coming back from the - // renderer process. - views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; - - base::WeakPtrFactory<SideSearchBrowserController> weak_factory_{this}; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_SIDE_SEARCH_SIDE_SEARCH_BROWSER_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/side_search/side_search_icon_view.cc b/chrome/browser/ui/views/side_search/side_search_icon_view.cc index 8e61270..ae67814 100644 --- a/chrome/browser/ui/views/side_search/side_search_icon_view.cc +++ b/chrome/browser/ui/views/side_search/side_search_icon_view.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_search/default_search_icon_source.h" -#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h" #include "chrome/browser/ui/views/side_search/side_search_views_utils.h" #include "chrome/browser/ui/views/side_search/unified_side_search_controller.h" #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/ui/views/side_search/side_search_views_utils.cc b/chrome/browser/ui/views/side_search/side_search_views_utils.cc index 146293e..b62c9cd 100644 --- a/chrome/browser/ui/views/side_search/side_search_views_utils.cc +++ b/chrome/browser/ui/views/side_search/side_search_views_utils.cc
@@ -7,7 +7,6 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_entry.h" -#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h" namespace side_search {
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc index c113e3ea..b2a5ea7 100644 --- a/chrome/browser/ui/views/side_search/unified_side_search_controller.cc +++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.cc
@@ -224,8 +224,7 @@ } } -void UnifiedSideSearchController::CloseSidePanel( - absl::optional<SideSearchCloseActionType> action) { +void UnifiedSideSearchController::CloseSidePanel() { auto* browser_view = GetBrowserView(); if (browser_view) { browser_view->side_panel_coordinator()->Close();
diff --git a/chrome/browser/ui/views/side_search/unified_side_search_controller.h b/chrome/browser/ui/views/side_search/unified_side_search_controller.h index 4f3d7c08..0fdcdc14 100644 --- a/chrome/browser/ui/views/side_search/unified_side_search_controller.h +++ b/chrome/browser/ui/views/side_search/unified_side_search_controller.h
@@ -8,7 +8,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" -#include "base/supports_user_data.h" #include "base/timer/elapsed_timer.h" #include "chrome/browser/ui/side_search/side_search_metrics.h" #include "chrome/browser/ui/side_search/side_search_tab_contents_helper.h" @@ -48,8 +47,6 @@ const content::OpenURLParams& params) override; void SidePanelAvailabilityChanged(bool should_close) override; void OpenSidePanel() override; - void CloseSidePanel( - absl::optional<SideSearchCloseActionType> action = absl::nullopt); // content::WebContentsObserver: void DidFinishNavigation( @@ -60,6 +57,7 @@ void OnEntryHidden(SidePanelEntry* entry) override; base::WeakPtr<UnifiedSideSearchController> GetWeakPtr(); + void CloseSidePanel(); // Gets the URL needed to open the current side search side panel contents // into a new tab.
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h index a37ad9b..3ea7f98 100644 --- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h +++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_CHROME_WEB_CONTENTS_VIEW_FOCUS_HELPER_H_ #define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_CHROME_WEB_CONTENTS_VIEW_FOCUS_HELPER_H_ -#include "base/supports_user_data.h" #include "content/public/browser/web_contents_user_data.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/view_tracker.h"
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index cad410e..52b91552 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -65,19 +65,18 @@ #include "ui/views/views_features.h" #include "ui/views/widget/root_view.h" +#if BUILDFLAG(IS_CHROMEOS) +#include "chromeos/ui/base/window_properties.h" +#include "chromeos/ui/base/window_state_type.h" // nogncheck +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/window_properties.h" // nogncheck -#include "chromeos/ui/base/window_properties.h" -#include "chromeos/ui/base/window_state_type.h" // nogncheck #include "ui/aura/window_delegate.h" #include "ui/wm/core/coordinate_conversion.h" #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/ui/base/window_properties.h" -#endif - #if BUILDFLAG(IS_MAC) #include "components/remote_cocoa/browser/window.h" #endif @@ -126,7 +125,7 @@ #endif } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // Returns the aura::Window which stores the window properties for tab-dragging. aura::Window* GetWindowForTabDraggingProperties(const TabDragContext* context) { @@ -143,6 +142,16 @@ type == chromeos::WindowStateType::kSecondarySnapped; } +#else + +bool IsSnapped(const TabDragContext* context) { + return false; +} + +#endif // BUILDFLAG(IS_CHROMEOS) + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // In Chrome OS tablet mode, when dragging a tab/tabs around, the desired // browser size during dragging is one-fourth of the workspace size or the // window's minimum size. @@ -197,10 +206,6 @@ } #else -bool IsSnapped(const TabDragContext* context) { - return false; -} - bool IsShowingInOverview(TabDragContext* context) { return false; }
diff --git a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc index bda6fece..1e2c6565 100644 --- a/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/side_panel_toolbar_button.cc
@@ -58,8 +58,6 @@ return; } - browser_view->MaybeClobberAllSideSearchSidePanels(); - if (!side_panel_webview_) { // Using base::Unretained(this) is safe here because the side panel (and the // web view as its child) will be destroyed before the toolbar which will
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index cfbd9acd..46ce747 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -60,7 +60,6 @@ #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h" #include "chrome/browser/ui/views/performance_controls/battery_saver_button.h" #include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_icon_view.h" -#include "chrome/browser/ui/views/side_search/side_search_browser_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/app_menu.h" #include "chrome/browser/ui/views/toolbar/back_forward_button.h" @@ -283,14 +282,6 @@ reload_ = AddChildView(std::move(reload)); home_ = AddChildView(std::move(home)); - // The side search button (if enabled) should sit between the location bar and - // the other navigation buttons. - if (browser_view_->side_search_controller() && - !IsSideSearchEnabled(browser_->profile())) { - left_side_panel_button_ = AddChildView( - browser_view_->side_search_controller()->CreateToolbarButton()); - } - location_bar_ = AddChildView(std::move(location_bar)); if (extensions_container)
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index bc461e34..8c2ea74 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -152,7 +152,6 @@ } ExtensionsToolbarButton* GetExtensionsButton() const; ReloadButton* reload_button() const { return reload_; } - ToolbarButton* left_side_panel_button() { return left_side_panel_button_; } LocationBarView* location_bar() const { return location_bar_; } CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; } BatterySaverButton* battery_saver_button() const { @@ -264,7 +263,6 @@ // Controls. Most of these can be null, e.g. in popup windows. Only // |location_bar_| is guaranteed to exist. These pointers are owned by the // view hierarchy. - raw_ptr<ToolbarButton> left_side_panel_button_ = nullptr; raw_ptr<ToolbarButton> back_ = nullptr; raw_ptr<ToolbarButton> forward_ = nullptr; raw_ptr<ReloadButton> reload_ = nullptr;
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc index 22712dbf..7289f880 100644 --- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -963,7 +963,7 @@ int frame_view_height = frame_view_cros->GetMinimumSize().height(); int caption_container_height = - frame_view_cros->caption_button_container_for_testing()->size().height(); + frame_view_cros->caption_button_container()->size().height(); int client_view_height = frame_view_cros->frame()->client_view()->GetMinimumSize().height();
diff --git a/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc b/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc new file mode 100644 index 0000000..61a3484 --- /dev/null +++ b/chrome/browser/ui/views/web_apps/web_ui_web_app_browsertest.cc
@@ -0,0 +1,96 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/strcat.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" +#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/password_manager/content/common/web_ui_constants.h" +#include "components/password_manager/core/common/password_manager_features.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" + +namespace { + +constexpr char kWebUIScheme[] = "chrome://"; + +} // namespace + +namespace web_app { + +class WebUIWebAppBrowserTest : public InProcessBrowserTest { + public: + WebUIWebAppBrowserTest() = default; + ~WebUIWebAppBrowserTest() override = default; + + void SetUp() override { + features_.InitAndEnableFeature( + password_manager::features::kPasswordManagerRedesign); + ASSERT_TRUE(embedded_test_server()->Start()); + InProcessBrowserTest::SetUp(); + } + + struct App { + AppId id; + std::string start_url; + raw_ptr<Browser> browser; + raw_ptr<BrowserView> browser_view; + content::WebContents* web_contents; + }; + + App InstallAndLaunch() { + Profile* profile = browser()->profile(); + std::string start_url = base::StrCat( + {kWebUIScheme, password_manager::kChromeUIPasswordManagerHost}); + + auto web_app_info = std::make_unique<WebAppInstallInfo>(); + web_app_info->start_url = GURL(start_url); + web_app_info->user_display_mode = mojom::UserDisplayMode::kStandalone; + AppId app_id = test::InstallWebApp(profile, std::move(web_app_info)); + + Browser* app_browser = LaunchWebAppBrowser(profile, app_id); + return App{app_id, start_url, app_browser, + BrowserView::GetBrowserViewForBrowser(app_browser), + app_browser->tab_strip_model()->GetActiveWebContents()}; + } + + private: + base::test::ScopedFeatureList features_; +}; + +IN_PROC_BROWSER_TEST_F(WebUIWebAppBrowserTest, NavigationsToOtherWebUIs) { + App app = InstallAndLaunch(); + + // Navigation to another page within the app scope should not open new browser + // tabs. + GURL in_scope_url = GURL(base::StrCat({app.start_url, "/settings"})); + ASSERT_TRUE(ui_test_utils::NavigateToURL(app.browser, in_scope_url)); + EXPECT_EQ(app.web_contents->GetVisibleURL(), in_scope_url); + + // Navigation to another WebUI should open a new browser tab. + GURL out_of_scope_url = GURL(base::StrCat({kWebUIScheme, "history"})); + // Add a waiter for the app to open. + ui_test_utils::AllBrowserTabAddedWaiter waiter; + ASSERT_TRUE(ui_test_utils::NavigateToURL(app.browser, out_of_scope_url)); + content::WebContents* new_web_contents = waiter.Wait(); + ASSERT_TRUE(new_web_contents); + + // URL of the WebApp should not change. + EXPECT_EQ(app.web_contents->GetVisibleURL(), in_scope_url); + + // Check that new web contents belong to the same profile. + Browser* new_browser_window = chrome::FindTabbedBrowser( + app.browser->profile(), /*match_original_profiles=*/true); + EXPECT_EQ(new_web_contents, + new_browser_window->tab_strip_model()->GetActiveWebContents()); + EXPECT_EQ(new_web_contents->GetVisibleURL(), out_of_scope_url); +} + +} // namespace web_app
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index 5644d29..6667b0a 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -430,18 +430,18 @@ AccountSelectionBubbleView::~AccountSelectionBubbleView() = default; void AccountSelectionBubbleView::ShowAccountPicker( - const std::vector<IdentityProviderDisplayData>& idp_data_list, + const std::vector<IdentityProviderDisplayData>& idp_display_data_list, bool show_back_button) { // If there are multiple IDPs, then the content::IdentityProviderMetadata // passed will be unused since there will be no `header_icon_view_`. // Therefore, it is fine to pass the first one into UpdateHeader(). - DCHECK(idp_data_list.size() == 1u || !header_icon_view_); - UpdateHeader(idp_data_list[0].idp_metadata_, accessible_title_, + DCHECK(idp_display_data_list.size() == 1u || !header_icon_view_); + UpdateHeader(idp_display_data_list[0].idp_metadata, accessible_title_, show_back_button); RemoveNonHeaderChildViews(); AddChildView(std::make_unique<views::Separator>()); - AddChildView(CreateAccountChooser(idp_data_list)); + AddChildView(CreateAccountChooser(idp_display_data_list)); SizeToContents(); PreferredSizeChanged(); @@ -458,9 +458,10 @@ void AccountSelectionBubbleView::ShowVerifyingSheet( const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, const std::u16string& title) { - UpdateHeader(idp_data.idp_metadata_, title, /*show_back_button=*/false); + UpdateHeader(idp_display_data.idp_metadata, title, + /*show_back_button=*/false); RemoveNonHeaderChildViews(); views::ProgressBar* const progress_bar = @@ -473,7 +474,7 @@ views::BoxLayout::Orientation::kVertical, gfx::Insets::VH(kTopBottomPadding, kLeftRightPadding))); row->AddChildView( - CreateAccountRow(account, idp_data, /*should_hover=*/false)); + CreateAccountRow(account, idp_display_data, /*should_hover=*/false)); AddChildView(std::move(row)); SizeToContents(); PreferredSizeChanged(); @@ -486,15 +487,15 @@ void AccountSelectionBubbleView::ShowSingleAccountConfirmDialog( const std::u16string& rp_for_display, const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data) { - std::u16string title = - l10n_util::GetStringFUTF16(SelectSingleIdpTitleResourceId(rp_context_), - rp_for_display, idp_data.idp_etld_plus_one_); - UpdateHeader(idp_data.idp_metadata_, title, true); + const IdentityProviderDisplayData& idp_display_data) { + std::u16string title = l10n_util::GetStringFUTF16( + SelectSingleIdpTitleResourceId(rp_context_), rp_for_display, + idp_display_data.idp_etld_plus_one); + UpdateHeader(idp_display_data.idp_metadata, title, true); RemoveNonHeaderChildViews(); AddChildView(std::make_unique<views::Separator>()); - AddChildView(CreateSingleAccountChooser(idp_data, account)); + AddChildView(CreateSingleAccountChooser(idp_display_data, account)); SizeToContents(); PreferredSizeChanged(); @@ -620,36 +621,37 @@ } std::unique_ptr<views::View> AccountSelectionBubbleView::CreateAccountChooser( - const std::vector<IdentityProviderDisplayData>& idp_data_list) { - if (idp_data_list.size() == 1u && idp_data_list[0].accounts_.size() == 1u) { - return CreateSingleAccountChooser(idp_data_list[0], - idp_data_list[0].accounts_[0]); + const std::vector<IdentityProviderDisplayData>& idp_display_data_list) { + if (idp_display_data_list.size() == 1u && + idp_display_data_list[0].accounts.size() == 1u) { + return CreateSingleAccountChooser(idp_display_data_list[0], + idp_display_data_list[0].accounts[0]); } - return CreateMultipleAccountChooser(idp_data_list); + return CreateMultipleAccountChooser(idp_display_data_list); } std::unique_ptr<views::View> AccountSelectionBubbleView::CreateSingleAccountChooser( - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, const content::IdentityRequestAccount& account) { auto row = std::make_unique<views::View>(); row->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, gfx::Insets::VH(0, kLeftRightPadding), kVerticalSpacing)); row->AddChildView( - CreateAccountRow(account, idp_data, /*should_hover=*/false)); + CreateAccountRow(account, idp_display_data, /*should_hover=*/false)); // Prefer using the given name if it is provided, otherwise fallback to name. const std::string display_name = account.given_name.empty() ? account.name : account.given_name; const content::IdentityProviderMetadata& idp_metadata = - idp_data.idp_metadata_; + idp_display_data.idp_metadata; // We can pass crefs to OnAccountSelected because the `observer_` owns the // data. auto button = std::make_unique<ContinueButton>( base::BindRepeating(&Observer::OnAccountSelected, base::Unretained(observer_), std::cref(account), - std::cref(idp_data), /*auto_signin=*/false), + std::cref(idp_display_data), /*auto_signin=*/false), l10n_util::GetStringFUTF16(IDS_ACCOUNT_SELECTION_CONTINUE, base::UTF8ToUTF16(display_name)), this, idp_metadata.brand_background_color, idp_metadata.brand_text_color); @@ -675,7 +677,8 @@ views::CreateEmptyBorder(gfx::Insets::TLBR(5, 0, 0, 0))); disclosure_label->SetDefaultTextStyle(views::style::STYLE_SECONDARY); - const content::ClientMetadata& client_metadata = idp_data.client_metadata_; + const content::ClientMetadata& client_metadata = + idp_display_data.client_metadata; int disclosure_resource_id = SelectDisclosureTextResourceId( client_metadata.privacy_policy_url, client_metadata.terms_of_service_url); @@ -692,7 +695,8 @@ } // Each link has both <ph name="BEGIN_LINK"> and <ph name="END_LINK">. - std::vector<std::u16string> replacements = {idp_data.idp_etld_plus_one_}; + std::vector<std::u16string> replacements = { + idp_display_data.idp_etld_plus_one}; replacements.insert(replacements.end(), link_data.size() * 2, std::u16string()); @@ -716,7 +720,7 @@ std::unique_ptr<views::View> AccountSelectionBubbleView::CreateMultipleAccountChooser( - const std::vector<IdentityProviderDisplayData>& idp_data_list) { + const std::vector<IdentityProviderDisplayData>& idp_display_data_list) { auto scroll_view = std::make_unique<views::ScrollView>(); scroll_view->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); @@ -724,19 +728,19 @@ scroll_view->SetContents(std::make_unique<views::View>()); row->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); - bool is_multi_idp = idp_data_list.size() > 1u; + bool is_multi_idp = idp_display_data_list.size() > 1u; size_t num_rows = 0; - for (const auto& idp_data : idp_data_list) { + for (const auto& idp_display_data : idp_display_data_list) { if (is_multi_idp) { row->AddChildView(CreateIdpHeaderRowForMultiIdp( - idp_data.idp_etld_plus_one_, idp_data.idp_metadata_)); + idp_display_data.idp_etld_plus_one, idp_display_data.idp_metadata)); ++num_rows; } - for (const auto& account : idp_data.accounts_) { + for (const auto& account : idp_display_data.accounts) { row->AddChildView( - CreateAccountRow(account, idp_data, /*should_hover=*/true)); + CreateAccountRow(account, idp_display_data, /*should_hover=*/true)); } - num_rows += idp_data.accounts_.size(); + num_rows += idp_display_data.accounts.size(); } // The maximum height that the multi-account-picker can have. This value was // chosen so that if there are more than two accounts, the picker will show up @@ -776,7 +780,7 @@ std::unique_ptr<views::View> AccountSelectionBubbleView::CreateAccountRow( const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, bool should_hover) { auto image_view = std::make_unique<AccountImageView>(); image_view->SetImageSize({kDesiredAvatarSize, kDesiredAvatarSize}); @@ -787,7 +791,7 @@ auto row = std::make_unique<HoverButton>( base::BindRepeating(&Observer::OnAccountSelected, base::Unretained(observer_), std::cref(account), - std::cref(idp_data), /*auto_signin=*/false), + std::cref(idp_display_data), /*auto_signin=*/false), std::move(image_view), base::UTF8ToUTF16(account.name), base::UTF8ToUTF16(account.email)); row->SetBorder(views::CreateEmptyBorder(
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.h b/chrome/browser/ui/views/webid/account_selection_bubble_view.h index 52c83cc..d75718d 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.h +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.h
@@ -43,12 +43,12 @@ // 1. A user either selects the account from the multi-account chooser or // clicks the "continue" button. (auto_signin == false) // 2. Auto sign-in is triggered. (auto_signin == true) - // Takes `account` as well as `idp_data` since passing `account_id` is - // insufficient in the multiple IDP case. The caller should pass a cref, as - // these objects are owned by the observer. + // Takes `account` as well as `idp_display_data` since passing `account_id` + // is insufficient in the multiple IDP case. The caller should pass a cref, + // as these objects are owned by the observer. virtual void OnAccountSelected( const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, bool auto_signin, const ui::Event& event) = 0; @@ -76,16 +76,16 @@ // AccountSelectionBubbleViewInterface: void ShowAccountPicker( - const std::vector<IdentityProviderDisplayData>& idp_data_list, + const std::vector<IdentityProviderDisplayData>& idp_display_data_list, bool show_back_button) override; void ShowVerifyingSheet(const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, const std::u16string& title) override; void ShowSingleAccountConfirmDialog( const std::u16string& rp_for_display, const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data) override; + const IdentityProviderDisplayData& idp_display_data) override; void ShowFailureDialog(const std::u16string& rp_for_display, const std::u16string& idp_for_display) override; @@ -105,19 +105,19 @@ // Returns a View containing the account chooser, i.e. everything that goes // below the horizontal separator on the initial FedCM bubble. std::unique_ptr<views::View> CreateAccountChooser( - const std::vector<IdentityProviderDisplayData>& idp_data_list); + const std::vector<IdentityProviderDisplayData>& idp_display_data_list); // Returns a View for single account chooser. It contains the account // information, disclosure text and a button for the user to confirm the - // selection. The size of the `idp_data.accounts` vector must be 1. + // selection. The size of the `idp_display_data.accounts` vector must be 1. std::unique_ptr<views::View> CreateSingleAccountChooser( - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, const content::IdentityRequestAccount& account); // Returns a View for multiple account chooser. It contains the info for each // account in a button, so the user can pick an account. std::unique_ptr<views::View> CreateMultipleAccountChooser( - const std::vector<IdentityProviderDisplayData>& idp_data_list); + const std::vector<IdentityProviderDisplayData>& idp_display_data_list); // Creates a row containing the IDP icon as well as the IDP ETLD+1. Used in // the multi IDP scenario, when the user is selecting from multiple accounts. @@ -131,7 +131,7 @@ // not. std::unique_ptr<views::View> CreateAccountRow( const content::IdentityRequestAccount& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, bool should_hover); // Updates the header title, the header icon visibility and the header back
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc index ac286589b..04bcd67 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -51,7 +51,8 @@ void FedCmAccountSelectionView::Show( const std::string& rp_etld_plus_one, - const std::vector<content::IdentityProviderData>& identity_provider_data, + const std::vector<content::IdentityProviderData>& + identity_provider_data_list, Account::SignInMode sign_in_mode) { // Either Show or ShowFailureDialog has already been called for other IDPs // from the same token request. This could happen when accounts fetch fails @@ -68,8 +69,8 @@ size_t accounts_size = 0u; blink::mojom::RpContext rp_context = blink::mojom::RpContext::kSignIn; - for (const auto& identity_provider : identity_provider_data) { - idp_data_list_.emplace_back( + for (const auto& identity_provider : identity_provider_data_list) { + idp_display_data_list_.emplace_back( base::UTF8ToUTF16(identity_provider.idp_for_display), identity_provider.idp_metadata, identity_provider.client_metadata, identity_provider.accounts); @@ -81,16 +82,16 @@ state_ = accounts_size == 1u ? State::PERMISSION : State::ACCOUNT_PICKER; absl::optional<std::u16string> idp_title = - identity_provider_data.size() == 1u - ? absl::make_optional<std::u16string>( - base::UTF8ToUTF16(identity_provider_data[0].idp_for_display)) + identity_provider_data_list.size() == 1u + ? absl::make_optional<std::u16string>(base::UTF8ToUTF16( + identity_provider_data_list[0].idp_for_display)) : absl::nullopt; rp_for_display_ = base::UTF8ToUTF16(rp_etld_plus_one); bubble_widget_ = CreateBubble(browser, rp_for_display_, idp_title, rp_context) ->GetWeakPtr(); if (sign_in_mode == Account::SignInMode::kAuto) { - for (const auto& idp_data : idp_data_list_) { - for (const auto& account : idp_data.accounts_) { + for (const auto& idp_display_data : idp_display_data_list_) { + for (const auto& account : idp_display_data.accounts) { if (account.login_state != Account::LoginState::kSignIn) { continue; } @@ -99,7 +100,7 @@ // is generally meant to be called with an associated event, so pass a // dummy one, which will be ignored. OnAccountSelected( - account, idp_data, /*auto_signin=*/true, + account, idp_display_data, /*auto_signin=*/true, ui::MouseEvent(ui::ET_UNKNOWN, gfx::Point(), gfx::Point(), base::TimeTicks(), 0, 0)); // Initialize InputEventActivationProtector to handle potentially @@ -115,7 +116,7 @@ // Should return in the for loop above. DCHECK(false); } - GetBubbleView()->ShowAccountPicker(idp_data_list_, + GetBubbleView()->ShowAccountPicker(idp_display_data_list_, /*show_back_button=*/false); // Initialize InputEventActivationProtector to handle potentially unintended // input events. @@ -240,7 +241,7 @@ void FedCmAccountSelectionView::OnAccountSelected( const Account& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, bool auto_signin, const ui::Event& event) { if (!auto_signin && @@ -256,7 +257,8 @@ base::WeakPtr<FedCmAccountSelectionView> weak_ptr( weak_ptr_factory_.GetWeakPtr()); - delegate_->OnAccountSelected(idp_data.idp_metadata_.config_url, account); + delegate_->OnAccountSelected(idp_display_data.idp_metadata.config_url, + account); // AccountSelectionView::Delegate::OnAccountSelected() might delete this. // See https://crbug.com/1393650 for details. if (!weak_ptr) @@ -265,13 +267,13 @@ const std::u16string title = auto_signin ? l10n_util::GetStringFUTF16( IDS_VERIFY_SHEET_TITLE_AUTO_SIGNIN, rp_for_display_, - idp_data.idp_etld_plus_one_) + idp_display_data.idp_etld_plus_one) : l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE); - GetBubbleView()->ShowVerifyingSheet(account, idp_data, title); + GetBubbleView()->ShowVerifyingSheet(account, idp_display_data, title); return; } GetBubbleView()->ShowSingleAccountConfirmDialog(rp_for_display_, account, - idp_data); + idp_display_data); } void FedCmAccountSelectionView::OnLinkClicked(LinkType link_type, @@ -302,7 +304,7 @@ void FedCmAccountSelectionView::OnBackButtonClicked() { // No need to protect input here since back cannot be the first event. state_ = State::ACCOUNT_PICKER; - GetBubbleView()->ShowAccountPicker(idp_data_list_, + GetBubbleView()->ShowAccountPicker(idp_display_data_list_, /*show_back_button=*/false); }
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h index 1ba2c467..5f1e061f 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -88,7 +88,7 @@ // AccountSelectionBubbleView::Observer: void OnAccountSelected(const Account& account, - const IdentityProviderDisplayData& idp_data, + const IdentityProviderDisplayData& idp_display_data, bool auto_signin, const ui::Event& event) override; void OnLinkClicked(LinkType link_type, @@ -108,7 +108,7 @@ void OnDismiss( content::IdentityRequestDialogController::DismissReason dismiss_reason); - std::vector<IdentityProviderDisplayData> idp_data_list_; + std::vector<IdentityProviderDisplayData> idp_display_data_list_; std::u16string rp_for_display_;
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 fc61e14..a0b606a 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
@@ -42,8 +42,9 @@ show_verifying_sheet_ = false; account_ids_.clear(); - for (content::IdentityRequestAccount account : idp_data_list[0].accounts_) + for (content::IdentityRequestAccount account : idp_data_list[0].accounts) { account_ids_.push_back(account.id); + } } void ShowVerifyingSheet(const content::IdentityRequestAccount& account, @@ -198,7 +199,7 @@ const char kAccountId[] = "account_id"; IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({{kAccountId, LoginState::kSignUp}}); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kExplicit); AccountSelectionBubbleView::Observer* observer = @@ -219,7 +220,7 @@ const char kAccountId2[] = "account_id2"; IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData( {{kAccountId1, LoginState::kSignIn}, {kAccountId2, LoginState::kSignIn}}); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kExplicit); AccountSelectionBubbleView::Observer* observer = @@ -243,7 +244,7 @@ {kAccountId1, LoginState::kSignUp}, {kAccountId2, LoginState::kSignUp}, }); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kExplicit); AccountSelectionBubbleView::Observer* observer = @@ -282,7 +283,7 @@ const char kAccountId[] = "account_id"; IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({{kAccountId, LoginState::kSignIn}}); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kAuto); @@ -297,7 +298,7 @@ const char kAccountId2[] = "account_id2"; IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData( {{kAccountId1, LoginState::kSignIn}, {kAccountId2, LoginState::kSignUp}}); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kAuto); @@ -348,7 +349,7 @@ IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({ {kAccountId1, LoginState::kSignIn}, }); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; AccountSelectionBubbleView::Observer* observer = nullptr; { @@ -368,7 +369,7 @@ const char kAccountId[] = "account_id"; IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({{kAccountId, LoginState::kSignUp}}); - const std::vector<Account>& accounts = idp_data.accounts_; + const std::vector<Account>& accounts = idp_data.accounts; std::unique_ptr<TestFedCmAccountSelectionView> controller = CreateAndShow(accounts, SignInMode::kExplicit); AccountSelectionBubbleView::Observer* observer =
diff --git a/chrome/browser/ui/views/webid/identity_provider_display_data.cc b/chrome/browser/ui/views/webid/identity_provider_display_data.cc index bb39ddeb7..5ec8e16e 100644 --- a/chrome/browser/ui/views/webid/identity_provider_display_data.cc +++ b/chrome/browser/ui/views/webid/identity_provider_display_data.cc
@@ -9,10 +9,10 @@ const content::IdentityProviderMetadata& idp_metadata, const content::ClientMetadata& client_metadata, const std::vector<content::IdentityRequestAccount>& accounts) - : idp_etld_plus_one_(idp_etld_plus_one), - idp_metadata_(idp_metadata), - client_metadata_(client_metadata), - accounts_(accounts) {} + : idp_etld_plus_one(idp_etld_plus_one), + idp_metadata(idp_metadata), + client_metadata(client_metadata), + accounts(accounts) {} IdentityProviderDisplayData::IdentityProviderDisplayData( const IdentityProviderDisplayData& other) = default;
diff --git a/chrome/browser/ui/views/webid/identity_provider_display_data.h b/chrome/browser/ui/views/webid/identity_provider_display_data.h index 1e32003..e1365ac6 100644 --- a/chrome/browser/ui/views/webid/identity_provider_display_data.h +++ b/chrome/browser/ui/views/webid/identity_provider_display_data.h
@@ -10,8 +10,7 @@ #include "content/public/browser/identity_request_account.h" #include "content/public/browser/identity_request_dialog_controller.h" -class IdentityProviderDisplayData { - public: +struct IdentityProviderDisplayData { IdentityProviderDisplayData( const std::u16string& idp_etld_plus_one, const content::IdentityProviderMetadata& idp_metadata, @@ -22,10 +21,10 @@ ~IdentityProviderDisplayData(); - std::u16string idp_etld_plus_one_; - content::IdentityProviderMetadata idp_metadata_; - content::ClientMetadata client_metadata_; - std::vector<content::IdentityRequestAccount> accounts_; + std::u16string idp_etld_plus_one; + content::IdentityProviderMetadata idp_metadata; + content::ClientMetadata client_metadata; + std::vector<content::IdentityRequestAccount> accounts; }; #endif // CHROME_BROWSER_UI_VIEWS_WEBID_IDENTITY_PROVIDER_DISPLAY_DATA_H_
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc index fba8ab0..6d0024e6 100644 --- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -275,6 +275,15 @@ } IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest, + FileExtensionCaseInsensitive) { + InstallFileHandlingPWA(); + base::FilePath test_file_path = CreateTestFileWithExtension("TXT"); + LaunchWithFiles(app_id(), GetTextFileHandlerActionURL(), {test_file_path}); + + VerifyPwaDidReceiveFileLaunchParams(true, test_file_path); +} + +IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest, PWAsCanReceiveFileLaunchParamsInTab) { InstallFileHandlingPWA(); base::FilePath test_file_path = CreateTestFileWithExtension("txt");
diff --git a/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.cc b/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.cc new file mode 100644 index 0000000..cf6fd3b --- /dev/null +++ b/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.cc
@@ -0,0 +1,96 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/web_applications/web_app_constants.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/url_utils.h" +#include "url/gurl.h" + +namespace web_app { + +WebUIWebAppNavigationThrottle::WebUIWebAppNavigationThrottle( + content::NavigationHandle* navigation_handle) + : content::NavigationThrottle(navigation_handle) {} + +WebUIWebAppNavigationThrottle::~WebUIWebAppNavigationThrottle() = default; + +const char* WebUIWebAppNavigationThrottle::GetNameForLogging() { + return "WebUIWebAppNavigationThrottle"; +} + +// static +std::unique_ptr<content::NavigationThrottle> +WebUIWebAppNavigationThrottle::MaybeCreateThrottleFor( + content::NavigationHandle* handle) { + if (!handle->IsInPrimaryMainFrame()) { + return nullptr; + } + + // Reloading the page should not cause the tab to change. + if (handle->GetReloadType() != content::ReloadType::NONE) { + return nullptr; + } + + content::WebContents* web_contents = handle->GetWebContents(); + + Browser* browser = chrome::FindBrowserWithWebContents(web_contents); + if (!browser || !browser->app_controller()) { + return nullptr; + } + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Exclude system web apps. + if (browser->app_controller()->system_app()) { + return nullptr; + } +#endif + + // Proceed only if the app is coming from Chrome WebUI. + GURL start_url = browser->app_controller()->GetAppStartUrl(); + if (!content::HasWebUIScheme(start_url)) { + return nullptr; + } + + return std::make_unique<WebUIWebAppNavigationThrottle>(handle); +} + +content::NavigationThrottle::ThrottleCheckResult +WebUIWebAppNavigationThrottle::WillStartRequest() { + GURL navigation_url = navigation_handle()->GetURL(); + + content::WebContents* web_contents = navigation_handle()->GetWebContents(); + Browser* browser = chrome::FindBrowserWithWebContents(web_contents); + DCHECK(browser); + web_app::AppBrowserController* app_controller = browser->app_controller(); + DCHECK(app_controller); + GURL start_url = browser->app_controller()->GetAppStartUrl(); + + if (content::HasWebUIScheme(navigation_url) && + !url::IsSameOriginWith(navigation_url, start_url)) { + content::OpenURLParams params = + content::OpenURLParams::FromNavigationHandle(navigation_handle()); + params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + navigation_handle()->GetWebContents()->OpenURL(std::move(params)); + // Deactivate app window to foreground the browser with new tab. + browser->window()->Deactivate(); + return content::NavigationThrottle::CANCEL_AND_IGNORE; + } else { + return content::NavigationThrottle::PROCEED; + } +} + +content::NavigationThrottle::ThrottleCheckResult +WebUIWebAppNavigationThrottle::WillRedirectRequest() { + return WillStartRequest(); +} + +} // namespace web_app
diff --git a/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.h b/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.h new file mode 100644 index 0000000..7d522e6b --- /dev/null +++ b/chrome/browser/ui/web_applications/webui_web_app_navigation_throttle.h
@@ -0,0 +1,32 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEB_APPLICATIONS_WEBUI_WEB_APP_NAVIGATION_THROTTLE_H_ +#define CHROME_BROWSER_UI_WEB_APPLICATIONS_WEBUI_WEB_APP_NAVIGATION_THROTTLE_H_ + +#include "content/public/browser/navigation_throttle.h" + +namespace web_app { + +// A navigation throttle that helps WebUI web apps to open links in the +// correct tab. +class WebUIWebAppNavigationThrottle : public content::NavigationThrottle { + public: + // Returns a navigation throttle when the navigation is happening inside + // a web app with a WebUI start url. + static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor( + content::NavigationHandle* handle); + + explicit WebUIWebAppNavigationThrottle(content::NavigationHandle* handle); + ~WebUIWebAppNavigationThrottle() override; + + // content::NavigationThrottle: + ThrottleCheckResult WillStartRequest() override; + ThrottleCheckResult WillRedirectRequest() override; + const char* GetNameForLogging() override; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_WEBUI_WEB_APP_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/ui/webui/app_home/app_home.mojom b/chrome/browser/ui/webui/app_home/app_home.mojom index 5d66b59..5795831 100644 --- a/chrome/browser/ui/webui/app_home/app_home.mojom +++ b/chrome/browser/ui/webui/app_home/app_home.mojom
@@ -37,8 +37,8 @@ // The app's `RunOnOsLoginMode`, including `RunOnOsLoginModeNotRun` and // `RunOnOsLoginModeWindowed`. RunOnOsLoginMode run_on_os_login_mode; - // Whether to show `open_in_window` menu item. - bool may_show_open_in_window; + // Whether the app is installed locally. + bool is_locally_installed; // Whether the app open in a app window or as a browser tab. bool open_in_window;
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc index 07c23a2..5c1d1c3 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h" #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/browser/web_applications/extension_status_utils.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "chrome/browser/web_applications/locks/app_lock.h" #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" #include "chrome/browser/web_applications/web_app.h" @@ -332,7 +333,7 @@ app_info->may_toggle_run_on_os_login_mode = login_mode.user_controllable; app_info->run_on_os_login_mode = login_mode.value; - app_info->may_show_open_in_window = is_locally_installed; + app_info->is_locally_installed = is_locally_installed; // Treat all other types of display mode as "open as window". app_info->open_in_window = registrar.GetAppEffectiveDisplayMode(app_id) != blink::mojom::DisplayMode::kBrowser; @@ -357,7 +358,10 @@ app_info->may_show_run_on_os_login_mode = false; app_info->may_toggle_run_on_os_login_mode = false; - app_info->may_show_open_in_window = false; + app_info->is_locally_installed = + !extension->is_hosted_app() || + extensions::BookmarkAppIsLocallyInstalled(extension_service_->profile(), + extension); return app_info; } @@ -564,6 +568,11 @@ page_->AddApp(CreateAppInfoPtrFromWebApp(app_id)); } +void AppHomePageHandler::OnWebAppInstalledWithOsHooks( + const web_app::AppId& app_id) { + page_->AddApp(CreateAppInfoPtrFromWebApp(app_id)); +} + void AppHomePageHandler::OnAppRegistrarDestroyed() { web_app_registrar_observation_.Reset(); }
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h index 060625df..040f1ba 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -60,7 +60,12 @@ ~AppHomePageHandler() override; // web_app::WebAppInstallManagerObserver: + // Listens to both `OnWebAppInstalled` and `OnWebAppInstalledWithOsHooks` as + // some type of installs, e.g. sync install only trigger `OnWebAppInstalled`. + // `OnWebAppInstalledWithOsHooks` also gets fired when an installed app gets + // locally installed. void OnWebAppInstalled(const web_app::AppId& app_id) override; + void OnWebAppInstalledWithOsHooks(const web_app::AppId& app_id) override; void OnWebAppWillBeUninstalled(const web_app::AppId& app_id) override; void OnWebAppInstallManagerDestroyed() override;
diff --git a/chrome/browser/ui/webui/app_home/app_home_ui.cc b/chrome/browser/ui/webui/app_home/app_home_ui.cc index e6d5ac6..11a918ea 100644 --- a/chrome/browser/ui/webui/app_home/app_home_ui.cc +++ b/chrome/browser/ui/webui/app_home/app_home_ui.cc
@@ -28,6 +28,7 @@ {"appLaunchAtStartupCheckboxLabel", IDS_ACCNAME_APP_HOME_LAUNCH_AT_STARTUP_CHECKBOX}, {"createShortcutForAppLabel", IDS_APP_HOME_CREATE_SHORTCUT}, + {"installLocallyLabel", IDS_APP_HOME_INSTALL_LOCALLY}, {"uninstallAppLabel", IDS_APP_HOME_UNINSTALL_APP}, {"appSettingsLabel", IDS_APP_HOME_APP_SETTINGS}, };
diff --git a/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.cc b/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.cc index 70989c0..8e35a46d 100644 --- a/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.cc +++ b/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/ash/login/screens/arc_vm_data_migration_screen.h" #include "components/login/localized_values_builder.h" +#include "ui/base/text/bytes_formatting.h" namespace ash { @@ -17,12 +18,15 @@ void ArcVmDataMigrationScreenHandler::DeclareLocalizedValues( ::login::LocalizedValuesBuilder* builder) { // TODO(b/258278176): Replace strings with l10n ones. + builder->Add("loadingDialogTitle", u"Loading..."); builder->Add("welcomeScreenTitle", u"Update your Chromebook"); builder->Add("welcomeScreenDescriptionHeader", u"What to expect"); builder->Add("welcomeScreenDescriptionBody", u"This is a critical update. During the update you will not be " u"able to use your device for up to 10 minutes. Please keep " u"your device connected to a charger during the update."); + builder->Add("notEnoughFreeDiskSpaceMessage", + u"Free up more than $1 of space"); builder->Add("skipButtonLabel", u"Remind me later"); builder->Add("updateButtonLabel", u"Next"); } @@ -35,4 +39,10 @@ CallExternalAPI("setUIState", static_cast<int>(state)); } +void ArcVmDataMigrationScreenHandler::SetRequiredFreeDiskSpace( + int64_t required_free_disk_space) { + CallExternalAPI("setRequiredFreeDiskSpace", + ui::FormatBytes(required_free_disk_space)); +} + } // namespace ash
diff --git a/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h b/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h index 9686b87..9c9a7c6 100644 --- a/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h +++ b/chrome/browser/ui/webui/ash/login/arc_vm_data_migration_screen_handler.h
@@ -21,13 +21,15 @@ "arc-vm-data-migration", "ArcVmDataMigrationScreen"}; enum class UIState { - kWelcome = 0, + kLoading = 0, + kWelcome = 1, }; virtual ~ArcVmDataMigrationScreenView() = default; virtual void Show() = 0; virtual void SetUIState(UIState state) = 0; + virtual void SetRequiredFreeDiskSpace(int64_t required_free_disk_space) = 0; }; class ArcVmDataMigrationScreenHandler : public BaseScreenHandler, @@ -50,6 +52,7 @@ // ArcVmDataMigrationScreenView overrides: void Show() override; void SetUIState(UIState state) override; + void SetRequiredFreeDiskSpace(int64_t required_free_disk_space) override; }; } // namespace ash
diff --git a/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn b/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn index 73b690f9..997f1de 100644 --- a/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn +++ b/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
@@ -34,6 +34,7 @@ mojom("mojo_bindings") { sources = [ "bluetooth_internals.mojom" ] webui_module_path = "/" + use_typescript_sources = true deps = [ "//device/bluetooth/public/mojom:deprecated_experimental_interfaces" ]
diff --git a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc index 2f9ee31..bd86627 100644 --- a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc +++ b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.cc
@@ -35,6 +35,10 @@ prefs->IsManagedPreference(history_clusters::prefs::kVisible)); source->AddBoolean("isHistoryClustersDebug", history_clusters::GetConfig().user_visible_debug); + source->AddBoolean("isHideVisitsEnabled", + history_clusters::GetConfig().hide_visits); + source->AddBoolean("isHideVisitsIconEnabled", + history_clusters::GetConfig().hide_visits_icon); static constexpr webui::LocalizedString kHistoryClustersStrings[] = { {"actionMenuDescription", IDS_HISTORY_CLUSTERS_ACTION_MENU_DESCRIPTION}, @@ -46,6 +50,7 @@ {"deleteWarning", IDS_HISTORY_CLUSTERS_DELETE_PRIOR_VISITS_WARNING}, {"disableHistoryClusters", IDS_HISTORY_CLUSTERS_DISABLE_MENU_ITEM_LABEL}, {"enableHistoryClusters", IDS_HISTORY_CLUSTERS_ENABLE_MENU_ITEM_LABEL}, + {"hideFromCluster", IDS_HISTORY_CLUSTERS_HIDE_PAGE}, {"historyClustersTabLabel", IDS_HISTORY_CLUSTERS_JOURNEYS_TAB_LABEL}, {"historyListTabLabel", IDS_HISTORY_CLUSTERS_LIST_TAB_LABEL}, {"loadMoreButtonLabel", IDS_HISTORY_CLUSTERS_LOAD_MORE_BUTTON_LABEL},
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc index ce0314b..86e912f 100644 --- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc +++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
@@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" @@ -28,8 +29,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/hats/hats_service.h" -#include "chrome/browser/ui/hats/hats_service_factory.h" #include "chrome/common/pref_names.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" @@ -138,6 +137,7 @@ mojom::URLVisitPtr VisitToMojom(Profile* profile, const history::ClusterVisit& visit) { auto visit_mojom = mojom::URLVisit::New(); + visit_mojom->visit_id = visit.annotated_visit.visit_row.visit_id; visit_mojom->normalized_url = visit.normalized_url; visit_mojom->url_for_display = base::UTF16ToUTF8(visit.url_for_display); if (!visit.image_url.is_empty()) { @@ -238,24 +238,6 @@ return search_query_mojom; } -void ShowSurveyAndLogMetrics(HatsService* service, - content::WebContents* contents, - const std::string& trigger, - base::TimeDelta delay) { - DCHECK(service); - DCHECK(contents); - - base::UmaHistogramBoolean("History.Clusters.Survey.CanShowAnySurvey", - service->CanShowAnySurvey(/*user_prompted=*/false)); - base::UmaHistogramBoolean("History.Clusters.Survey.CanShowSurvey", - service->CanShowSurvey(trigger)); - - bool success = service->LaunchDelayedSurveyForWebContents( - kHatsSurveyTriggerJourneysHistoryEntrypoint, contents, - delay.InMilliseconds()); - base::UmaHistogramBoolean("History.Clusters.Survey.Success", success); -} - } // namespace // Creates a `mojom::QueryResultPtr` using the original `query`, if the query @@ -280,6 +262,8 @@ } } + cluster_mojom->from_persistence = cluster.from_persistence; + if (GetConfig().user_visible_debug && cluster.from_persistence) { cluster_mojom->debug_info = "persisted, id = " + base::NumberToString(cluster.cluster_id); @@ -323,12 +307,12 @@ DCHECK(history_clusters_service); service_observation_.Observe(history_clusters_service); - history::HistoryService* local_history = HistoryServiceFactory::GetForProfile( + history_service_ = HistoryServiceFactory::GetForProfile( profile_, ServiceAccessType::EXPLICIT_ACCESS); syncer::SyncService* sync_service = SyncServiceFactory::GetForProfile(profile_); browsing_history_service_ = std::make_unique<history::BrowsingHistoryService>( - this, local_history, sync_service); + this, history_service_, sync_service); } HistoryClustersHandler::~HistoryClustersHandler() = default; @@ -420,6 +404,33 @@ } } +void HistoryClustersHandler::HideVisits(std::vector<mojom::URLVisitPtr> visits, + HideVisitsCallback callback) { + DCHECK(!visits.empty()); + + // If there's a pending request, fail because `HistoryClustersHandler` only + // supports one hide request at a time. + if (!pending_hide_visits_callback_.is_null() || !history_service_) { + std::move(callback).Run(/*success=*/false); + return; + } + + std::vector<history::VisitID> visit_ids; + base::ranges::transform( + visits, std::back_inserter(visit_ids), + [](const auto& url_visit_ptr) { return url_visit_ptr->visit_id; }); + + // Transfer the visits and the callback to member variables. + pending_hide_visits_ = std::move(visits); + pending_hide_visits_callback_ = std::move(callback); + + history_service_->HideVisits( + visit_ids, + base::BindOnce(&HistoryClustersHandler::OnHideVisitsComplete, + weak_ptr_factory_.GetWeakPtr()), + &pending_hide_visits_task_tracker_); +} + void HistoryClustersHandler::RemoveVisits( std::vector<mojom::URLVisitPtr> visits, RemoveVisitsCallback callback) { @@ -539,61 +550,13 @@ QueryClustersResultToMojom(profile_, query, std::move(clusters_batch), can_load_more, is_continuation); page_->OnClustersQueryResult(std::move(query_result)); - - // The user loading their first set of clusters should start the timer for - // launching the Journeys survey. - LaunchJourneysSurvey(); } -void HistoryClustersHandler::LaunchJourneysSurvey() { - // All the below is to attempt launch a survey, after loading the first set of - // clusters. - if (survey_launch_attempted_) { - return; - } - survey_launch_attempted_ = true; - - HatsService* hats_service = HatsServiceFactory::GetForProfile(profile_, true); - if (!hats_service) { - return; - } - - auto* logger = - history_clusters::HistoryClustersMetricsLogger::GetOrCreateForPage( - web_contents_->GetPrimaryPage()); - auto initial_state = logger->initial_state(); - if (!initial_state) { - return; - } - - constexpr char kHistoryClustersSurveyRequestedUmaName[] = - "History.Clusters.Survey.Requested"; - // These values must match enums.xml, and should not be modified. - enum HistoryClustersSurvey { - kHistoryEntrypoint = 0, - kOmniboxEntrypoint = 1, - kMaxValue = kOmniboxEntrypoint, - }; - if (*initial_state == - history_clusters::HistoryClustersInitialState::kSameDocument && - base::FeatureList::IsEnabled(kJourneysSurveyForHistoryEntrypoint)) { - // Same document navigation basically means clicking over from History. - ShowSurveyAndLogMetrics(hats_service, web_contents_, - kHatsSurveyTriggerJourneysHistoryEntrypoint, - kJourneysSurveyForHistoryEntrypointDelay.Get()); - base::UmaHistogramEnumeration(kHistoryClustersSurveyRequestedUmaName, - kHistoryEntrypoint); - } else if (*initial_state == history_clusters::HistoryClustersInitialState:: - kIndirectNavigation && - base::FeatureList::IsEnabled( - kJourneysSurveyForOmniboxEntrypoint)) { - // Indirect navigation basically means from the omnibox. - ShowSurveyAndLogMetrics(hats_service, web_contents_, - kHatsSurveyTriggerJourneysOmniboxEntrypoint, - kJourneysSurveyForOmniboxEntrypointDelay.Get()); - base::UmaHistogramEnumeration(kHistoryClustersSurveyRequestedUmaName, - kOmniboxEntrypoint); - } +void HistoryClustersHandler::OnHideVisitsComplete() { + DCHECK(!pending_hide_visits_callback_.is_null()); + std::move(pending_hide_visits_callback_).Run(/*success=*/true); + // Notify the page of the successfully hidden visits to update the UI. + page_->OnVisitsHidden(std::move(pending_hide_visits_)); } void HistoryClustersHandler::RecordVisitAction(mojom::VisitAction visit_action,
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h index d16e652..d6e4d66b 100644 --- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h +++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h
@@ -77,6 +77,8 @@ void LoadMoreClusters(const std::string& query) override; void RemoveVisits(std::vector<mojom::URLVisitPtr> visits, RemoveVisitsCallback callback) override; + void HideVisits(std::vector<mojom::URLVisitPtr> visits, + HideVisitsCallback callback) override; void OpenVisitUrlsInTabGroup(std::vector<mojom::URLVisitPtr> visits) override; void RecordVisitAction(mojom::VisitAction visit_action, uint32_t visit_index, @@ -106,8 +108,7 @@ bool can_load_more, bool is_continuation); - // Launches the Journeys survey, if user is eligible. - void LaunchJourneysSurvey(); + void OnHideVisitsComplete(); base::WeakPtr<ui::MojoBubbleWebUIController::Embedder> history_clusters_side_panel_embedder_; @@ -126,22 +127,26 @@ // Encapsulates the currently loaded clusters state on the page. std::unique_ptr<QueryClustersState> query_clusters_state_; + // Used only for hiding History visits. It's not used for querying History, + // because we do our querying with HistoryClustersService. + base::raw_ptr<history::HistoryService> history_service_; + // Used only for deleting History properly, and observing deletions that occur // from other tabs. It's not used for querying History, because we do our // querying with HistoryClustersService. std::unique_ptr<history::BrowsingHistoryService> browsing_history_service_; - // The following variables hold the visits requested to be deleted and the - // callback for the respective request. `BrowsingHistoryService` can only - // handle one deletion request at a time. + // The visits requested to be hidden and related request fields. + // `HistoryClustersHandler` can only handle 1 hide request at a time. + std::vector<mojom::URLVisitPtr> pending_hide_visits_; + RemoveVisitsCallback pending_hide_visits_callback_; + base::CancelableTaskTracker pending_hide_visits_task_tracker_; + + // The visits requested to be deleted and the request's callback. + // `BrowsingHistoryService` can handle only 1 delete request at a time. std::vector<mojom::URLVisitPtr> pending_remove_visits_; RemoveVisitsCallback pending_remove_visits_callback_; - // Flag used to launch survey once (at most) for each WebUI instance. The - // survey service itself has a limiter, but we also want to skip all the work - // to enqueue the request, so we have a separate flag here too. - bool survey_launch_attempted_ = false; - // Last query issued by the WebUI. The WebUI always makes a query upon load, // so this string is always set. If the WebUI loads without a query in the q= // GET parameter, it STILL makes a query for "", and so this variable being
diff --git a/chrome/browser/ui/webui/intro/intro_handler.cc b/chrome/browser/ui/webui/intro/intro_handler.cc index deb6c6b3..c78c0b4 100644 --- a/chrome/browser/ui/webui/intro/intro_handler.cc +++ b/chrome/browser/ui/webui/intro/intro_handler.cc
@@ -5,9 +5,11 @@ #include "chrome/browser/ui/webui/intro/intro_handler.h" #include "base/cancelable_callback.h" #include "base/functional/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/scoped_observation.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" +#include "base/time/time.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/ui/managed_ui.h" @@ -28,23 +30,39 @@ // PolicyStoreState will make it easier to handle all the states in a single // callback. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class PolicyStoreState { - // Store has been loaded before the time delay ends. - kSuccess, - // Store did not load in time. - kTimeout, - // OnStoreError called. - kStoreError, // Store was already loaded when we attached the observer. - kSuccessAlreadyLoaded, + kSuccessAlreadyLoaded = 0, + // Store has been loaded before the time delay ends. + kSuccess = 1, + // Store did not load in time. + kTimeout = 2, + // OnStoreError called. + kStoreError = 3, + kMaxValue = kStoreError, }; +void RecordDisclaimerMetrics(PolicyStoreState state, + base::TimeTicks start_time) { + base::UmaHistogramEnumeration("ProfilePicker.FirstRun.PolicyStoreState", + state); + if (state == PolicyStoreState::kSuccess) { + base::UmaHistogramTimes( + "ProfilePicker.FirstRun.OrganizationAvailableTiming", + /*sample*/ base::TimeTicks::Now() - start_time); + } +} + class PolicyStoreObserver : public policy::CloudPolicyStore::Observer { public: explicit PolicyStoreObserver( base::OnceCallback<void(std::string)> handle_policy_store_change) : handle_policy_store_change_(std::move(handle_policy_store_change)) { DCHECK(handle_policy_store_change_); + start_time_ = base::TimeTicks::Now(); + // Update the disclaimer directly if the policy store is already loaded. auto* policy_store = GetCloudPolicyStore(); if (policy_store->is_initialized()) { @@ -87,6 +105,7 @@ } void HandlePolicyStoreStatusChange(PolicyStoreState state) { + RecordDisclaimerMetrics(state, start_time_); std::string managed_device_disclaimer; if (state == PolicyStoreState::kSuccess || state == PolicyStoreState::kSuccessAlreadyLoaded) { @@ -110,6 +129,7 @@ policy_store_observation_{this}; base::OnceCallback<void(std::string)> handle_policy_store_change_; base::CancelableOnceCallback<void()> on_organization_fetch_timeout_; + base::TimeTicks start_time_; }; #endif } // namespace
diff --git a/chrome/browser/ui/webui/intro/intro_ui.cc b/chrome/browser/ui/webui/intro/intro_ui.cc index e3d6a749..54c10c85 100644 --- a/chrome/browser/ui/webui/intro/intro_ui.cc +++ b/chrome/browser/ui/webui/intro/intro_ui.cc
@@ -18,7 +18,6 @@ #include "components/signin/public/base/signin_buildflags.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" -#include "ui/base/l10n/l10n_util.h" #if BUILDFLAG(ENABLE_DICE_SUPPORT) #include "chrome/grit/chromium_strings.h"
diff --git a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc index 437256d..fd4cf35 100644 --- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc +++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -109,7 +109,9 @@ {"leakedPassword", IDS_PASSWORD_MANAGER_UI_PASSWORD_LEAKED}, {"localPasswordManager", IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SAVING_ON_DEVICE}, + {"menu", IDS_MENU}, {"moreActions", IDS_PASSWORD_MANAGER_UI_MORE_ACTIONS}, + {"muteCompromisedPassword", IDS_PASSWORD_MANAGER_UI_MUTE_ISSUE}, {"mutedCompromisedCredentials", IDS_PASSWORD_MANAGER_UI_MUTED_COMPROMISED_PASSWORDS}, {"notesLabel", IDS_PASSWORD_MANAGER_UI_NOTES_LABEL}, @@ -139,6 +141,7 @@ {"trustedVaultBannerSubLabelOfferOptIn", IDS_PASSWORD_MANAGER_UI_RUSTED_VAULT_OPT_IN_DESCRIPTION}, {"tryAgain", IDS_PASSWORD_MANAGER_UI_CHECK_PASSWORDS_AFTER_ERROR}, + {"unmuteCompromisedPassword", IDS_PASSWORD_MANAGER_UI_UNMUTE_ISSUE}, {"usernameCopiedToClipboard", IDS_PASSWORD_MANAGER_UI_USERNAME_COPIED_TO_CLIPBOARD}, {"usernameLabel", IDS_PASSWORD_MANAGER_UI_USERNAME_LABEL},
diff --git a/chrome/browser/ui/webui/settings/ash/BUILD.gn b/chrome/browser/ui/webui/settings/ash/BUILD.gn index 105f9c7..c6d56e9 100644 --- a/chrome/browser/ui/webui/settings/ash/BUILD.gn +++ b/chrome/browser/ui/webui/settings/ash/BUILD.gn
@@ -6,15 +6,6 @@ assert(is_chromeos_ash, "Non-ChromeOS builds cannot depend on //chromeos/ash") -group("mojom_js") { - public_deps = [ - "//chrome/browser/ui/webui/settings/ash/search:mojo_bindings_js", - "//chrome/browser/ui/webui/settings/chromeos/constants:mojom_js", - "//chromeos/ash/components/audio/public/mojom:mojom_js", - "//chromeos/ash/services/nearby/public/mojom:mojom_js", - ] -} - static_library("test_support") { testonly = true sources = [
diff --git a/chrome/browser/ui/webui/settings/ash/account_manager_ui_handler_browsertest.cc b/chrome/browser/ui/webui/settings/ash/account_manager_ui_handler_browsertest.cc index 68b94dcd..c319a5e 100644 --- a/chrome/browser/ui/webui/settings/ash/account_manager_ui_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/ash/account_manager_ui_handler_browsertest.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" @@ -25,6 +24,7 @@ #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_type.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ui/webui/settings/ash/device_keyboard_handler.cc b/chrome/browser/ui/webui/settings/ash/device_keyboard_handler.cc index c123f9a..4780ebe 100644 --- a/chrome/browser/ui/webui/settings/ash/device_keyboard_handler.cc +++ b/chrome/browser/ui/webui/settings/ash/device_keyboard_handler.cc
@@ -4,12 +4,15 @@ #include "chrome/browser/ui/webui/settings/ash/device_keyboard_handler.h" +#include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "ash/public/cpp/keyboard_shortcut_viewer.h" #include "ash/public/cpp/tablet_mode.h" #include "base/command_line.h" #include "base/functional/bind.h" #include "base/values.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "content/public/browser/web_ui.h" #include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/chromeos/events/keyboard_capability.h" @@ -105,6 +108,11 @@ void KeyboardHandler::HandleShowKeyboardShortcutViewer( const base::Value::List& args) const { + if (ash::features::ShouldOnlyShowNewShortcutApp()) { + ash::LaunchSystemWebAppAsync(ProfileManager::GetActiveUserProfile(), + ash::SystemWebAppType::SHORTCUT_CUSTOMIZATION); + return; + } ToggleKeyboardShortcutViewer(); }
diff --git a/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc b/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc index bb2a44c..0e2dd83 100644 --- a/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/ash/os_settings_ui.cc
@@ -15,6 +15,7 @@ #include "ash/webui/personalization_app/search/search.mojom.h" #include "ash/webui/personalization_app/search/search_handler.h" #include "base/metrics/histogram_functions.h" +#include "chrome/browser/ash/login/quick_unlock/pin_backend.h" #include "chrome/browser/ash/login/quick_unlock/quick_unlock_factory.h" #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_manager.h" #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_manager_factory.h" @@ -250,6 +251,15 @@ web_ui()->GetWebContents(), std::move(receiver)); } +void OSSettingsUI::BindInterface( + mojo::PendingReceiver<auth::mojom::PinFactorEditor> receiver) { + auto* pin_backend = quick_unlock::PinBackend::GetInstance(); + CHECK(pin_backend); + auth::BindToPinFactorEditor(std::move(receiver), + quick_unlock::QuickUnlockFactory::GetDelegate(), + *pin_backend); +} + WEB_UI_CONTROLLER_TYPE_IMPL(OSSettingsUI) } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/settings/ash/os_settings_ui.h b/chrome/browser/ui/webui/settings/ash/os_settings_ui.h index 408e646..75a485f 100644 --- a/chrome/browser/ui/webui/settings/ash/os_settings_ui.h +++ b/chrome/browser/ui/webui/settings/ash/os_settings_ui.h
@@ -149,6 +149,8 @@ mojo::PendingReceiver<auth::mojom::AuthFactorConfig> receiver); void BindInterface( mojo::PendingReceiver<auth::mojom::RecoveryFactorEditor> receiver); + void BindInterface( + mojo::PendingReceiver<auth::mojom::PinFactorEditor> receiver); // Binds to the Jelly dynamic color Mojo void BindInterface(
diff --git a/chrome/browser/ui/webui/settings/captions_handler.cc b/chrome/browser/ui/webui/settings/captions_handler.cc index 67fe981e..b33b8cb2 100644 --- a/chrome/browser/ui/webui/settings/captions_handler.cc +++ b/chrome/browser/ui/webui/settings/captions_handler.cc
@@ -32,6 +32,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) soda_available_ = base::FeatureList::IsEnabled(ash::features::kOnDeviceSpeechRecognition); +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + soda_available_ = false; #endif // BUILDFLAG(IS_CHROMEOS_ASH) }
diff --git a/chrome/browser/ui/webui/settings/settings_utils_mac.mm b/chrome/browser/ui/webui/settings/settings_utils_mac.mm index 9feca41..816f9de 100644 --- a/chrome/browser/ui/webui/settings/settings_utils_mac.mm +++ b/chrome/browser/ui/webui/settings/settings_utils_mac.mm
@@ -6,7 +6,10 @@ #include "chrome/browser/ui/webui/settings/settings_utils.h" +#include "base/functional/callback_helpers.h" #include "base/logging.h" +#include "base/mac/foundation_util.h" +#include "base/mac/launch_application.h" #include "base/mac/mac_logging.h" #include "base/mac/mac_util.h" #include "base/strings/sys_string_conversions.h" @@ -39,11 +42,11 @@ } void ShowManageSSLCertificates(content::WebContents* web_contents) { - NSString* const kKeychainBundleId = @"com.apple.keychainaccess"; - [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:kKeychainBundleId - options:0L - additionalEventParamDescriptor:nil - launchIdentifier:nil]; + NSURL* keychain_app = [NSWorkspace.sharedWorkspace + URLForApplicationWithBundleIdentifier:@"com.apple.keychainaccess"]; + base::mac::LaunchApplication(base::mac::NSURLToFilePath(keychain_app), + /*command_line_args=*/{}, /*url_specs=*/{}, + /*options=*/{}, base::DoNothing()); } void ValidateSavedFonts(PrefService* prefs) {
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index b8cac118..56c9a25 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -127,6 +127,14 @@ // only has placeholder, then create an ETLD+1 origin. constexpr char kPlaceholder[] = "placeholder"; +// Content types for chooser data. +constexpr ContentSettingsType kChooserDataContentSettingsTypes[] = { + ContentSettingsType::BLUETOOTH_CHOOSER_DATA, + ContentSettingsType::HID_CHOOSER_DATA, + ContentSettingsType::SERIAL_CHOOSER_DATA, + ContentSettingsType::USB_CHOOSER_DATA, +}; + // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class AllSitesAction2 { @@ -1177,6 +1185,32 @@ } } + // Get device chooser permission exceptions. + for (auto content_type : kChooserDataContentSettingsTypes) { + base::StringPiece group_name = + site_settings::ContentSettingsTypeToGroupName(content_type); + DCHECK(!group_name.empty()); + const site_settings::ChooserTypeNameEntry* chooser_type = + site_settings::ChooserTypeFromGroupName(group_name); + DCHECK(chooser_type); + base::Value::List exceptions = + site_settings::GetChooserExceptionListFromProfile(profile_, + *chooser_type); + for (const base::Value& exception : exceptions) { + const base::Value::List* sites = + exception.GetDict().FindList(site_settings::kSites); + DCHECK(sites); + for (const base::Value& site : *sites) { + const std::string* origin = + site.GetDict().FindString(site_settings::kOrigin); + DCHECK(origin); + GURL url = GURL(*origin); + CreateOrAppendSiteGroupEntry(&all_sites_map_, url); + origin_permission_set_.insert(url.spec()); + } + } + } + // Recreate the cookies tree model to refresh the usage information. // This happens in the background and will call TreeModelEndBatch() when // finished. At that point we send usage data to the page. @@ -1487,16 +1521,46 @@ if (!origin.is_valid()) return; + ContentSetting setting; + CHECK(content_settings::ContentSettingFromString(value, &setting)); std::vector<ContentSettingsType> types; if (type_string) { types.push_back( site_settings::ContentSettingsTypeFromGroupName(*type_string)); } else { + // Clear device chooser data permission exceptions. + if (setting == CONTENT_SETTING_DEFAULT) { + for (auto content_type : kChooserDataContentSettingsTypes) { + base::StringPiece group_name = + site_settings::ContentSettingsTypeToGroupName(content_type); + DCHECK(!group_name.empty()); + const site_settings::ChooserTypeNameEntry* chooser_type = + site_settings::ChooserTypeFromGroupName(group_name); + DCHECK(chooser_type); + + // The BluetoothChooserContext is only available when the + // WebBluetoothNewPermissionsBackend flag is enabled. + // TODO(crbug.com/589228): Remove the nullptr check when it is enabled + // by default. + permissions::ObjectPermissionContextBase* chooser_context = + chooser_type->get_context(profile_); + if (!chooser_context) { + continue; + } + + auto objects = chooser_context->GetAllGrantedObjects(); + for (const auto& object : objects) { + if (origin == object->origin) { + chooser_context->RevokeObjectPermission(url::Origin::Create(origin), + object->value); + } + } + } + } + types = site_settings::GetVisiblePermissionCategories(); } - ContentSetting setting; - CHECK(content_settings::ContentSettingFromString(value, &setting)); HostContentSettingsMap* map = HostContentSettingsMapFactory::GetForProfile(profile_); for (ContentSettingsType content_type : types) {
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index 369f5f5..8bb89ef2 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -90,18 +90,14 @@ void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change); private: + friend class SiteSettingsHandlerBaseTest; friend class SiteSettingsHandlerChooserExceptionTest; friend class SiteSettingsHandlerInfobarTest; - friend class SiteSettingsHandlerTest; // TODO(crbug.com/1373962): Remove this friend class when // Persistent Permissions is launched. friend class PersistentPermissionsSiteSettingsHandlerTest; FRIEND_TEST_ALL_PREFIXES(PersistentPermissionsSiteSettingsHandlerTest, HandleGetFileSystemGrants); - FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerChooserExceptionTest, - HandleGetChooserExceptionListForUsb); - FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerChooserExceptionTest, - HandleResetChooserExceptionForSiteForUsb); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 71ca303f..a16782a 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/barrier_closure.h" #include "base/command_line.h" #include "base/files/scoped_temp_dir.h" #include "base/functional/callback_helpers.h" @@ -19,12 +20,16 @@ #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" +#include "base/test/gmock_callback_support.h" #include "base/test/simple_test_clock.h" +#include "base/test/test_future.h" +#include "base/test/values_test_util.h" #include "base/values.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h" #include "chrome/browser/browsing_topics/browsing_topics_service_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/engagement/site_engagement_service_factory.h" @@ -36,6 +41,7 @@ #include "chrome/browser/permissions/notification_permission_review_service_factory.h" #include "chrome/browser/permissions/notifications_engagement_service_factory.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" +#include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/privacy_sandbox/mock_privacy_sandbox_service.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h" #include "chrome/browser/ui/browser_window.h" @@ -48,6 +54,7 @@ #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/browsing_data/content/browsing_data_model.h" @@ -66,12 +73,14 @@ #include "components/history/core/browser/history_service.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" +#include "components/permissions/contexts/bluetooth_chooser_context.h" #include "components/permissions/object_permission_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_uma_util.h" #include "components/permissions/permission_util.h" #include "components/permissions/test/object_permission_context_base_mock_permission_observer.h" #include "components/permissions/test/permission_test_util.h" +#include "components/prefs/testing_pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" @@ -82,22 +91,30 @@ #include "content/public/browser/navigation_controller.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" +#include "device/bluetooth/test/mock_bluetooth_device.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_builder.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "ppapi/buildflags/buildflags.h" #include "services/device/public/cpp/test/fake_usb_device_manager.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/storage_key/storage_key.h" +#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" #include "ui/webui/webui_allowlist.h" #include "url/gurl.h" #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/login/users/mock_user_manager.h" +#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "components/account_id/account_id.h" #include "components/user_manager/scoped_user_manager.h" #endif @@ -105,15 +122,32 @@ #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #endif -using ::testing::_; -using ::testing::Return; +#if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/hid/hid_chooser_context.h" +#include "chrome/browser/hid/hid_chooser_context_factory.h" +#include "chrome/browser/serial/serial_chooser_context.h" +#include "chrome/browser/serial/serial_chooser_context_factory.h" +#include "services/device/public/cpp/test/fake_hid_manager.h" +#include "services/device/public/cpp/test/fake_serial_port_manager.h" +#include "services/device/public/mojom/hid.mojom.h" +#include "services/device/public/mojom/serial.mojom.h" +#endif namespace { +using ::base::test::ParseJson; +using ::base::test::RunClosure; +using ::base::test::TestFuture; +using ::testing::_; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::UnorderedElementsAre; + constexpr char kCallbackId[] = "test-callback-id"; constexpr char kSetting[] = "setting"; constexpr char kSource[] = "source"; constexpr char kExtensionName[] = "Test Extension"; +constexpr char kTestUserEmail[] = "user@example.com"; const struct PatternContentTypeTestCase { struct { @@ -235,26 +269,26 @@ ContentSettingsType content_type_; }; -class SiteSettingsHandlerTest : public testing::Test, - public testing::WithParamInterface<bool> { +class SiteSettingsHandlerBaseTest : public testing::Test { public: - SiteSettingsHandlerTest() + SiteSettingsHandlerBaseTest() : kNotifications(site_settings::ContentSettingsTypeToGroupName( ContentSettingsType::NOTIFICATIONS)), kCookies(site_settings::ContentSettingsTypeToGroupName( ContentSettingsType::COOKIES)) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( - std::make_unique<ash::MockUserManager>()); -#endif - // Fully initialize |profile_| in the constructor since some children // classes need it right away for SetUp(). - TestingProfile::Builder profile_builder; - profile_builder.AddTestingFactory( - HistoryServiceFactory::GetInstance(), - HistoryServiceFactory::GetDefaultFactory()); - profile_ = profile_builder.Build(); + testing_profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + EXPECT_TRUE(testing_profile_manager_->SetUp()); + profile_ = testing_profile_manager_->CreateTestingProfile( + kTestUserEmail, {{HistoryServiceFactory::GetInstance(), + HistoryServiceFactory::GetDefaultFactory()}}); + EXPECT_TRUE(profile_); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + SetUpUserManager(profile_.get()); +#endif } void SetUp() override { @@ -295,6 +329,25 @@ } } +#if BUILDFLAG(IS_CHROMEOS_ASH) + void SetUpUserManager(TestingProfile* profile) { + // On ChromeOS a user account is needed in order to check whether the user + // account is affiliated with the device owner for the purposes of applying + // enterprise policy. + constexpr char kTestUserGaiaId[] = "1111111111"; + auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>(); + auto* fake_user_manager_ptr = fake_user_manager.get(); + scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( + std::move(fake_user_manager)); + + auto account_id = + AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + fake_user_manager_ptr->AddUserWithAffiliation(account_id, + /*is_affiliated=*/true); + fake_user_manager_ptr->LoginUser(account_id); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + void RecordNotification(permissions::NotificationsEngagementService* service, GURL url, int daily_avarage_count) { @@ -310,7 +363,7 @@ } TestingProfile* profile() { return profile_.get(); } - TestingProfile* incognito_profile() { return incognito_profile_; } + Profile* incognito_profile() { return incognito_profile_; } content::TestWebUI* web_ui() { return &web_ui_; } SiteSettingsHandler* handler() { return handler_.get(); } browsing_topics::MockBrowsingTopicsService* mock_browsing_topics_service() { @@ -561,7 +614,8 @@ } void CreateIncognitoProfile() { - incognito_profile_ = TestingProfile::Builder().BuildIncognito(profile()); + incognito_profile_ = profile_->GetOffTheRecordProfile( + Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); } virtual void DestroyIncognitoProfile() { @@ -766,18 +820,22 @@ private: content::BrowserTaskEnvironment task_environment_; - std::unique_ptr<TestingProfile> profile_; - raw_ptr<TestingProfile> incognito_profile_; + std::unique_ptr<TestingProfileManager> testing_profile_manager_; + raw_ptr<TestingProfile> profile_ = nullptr; + raw_ptr<Profile> incognito_profile_ = nullptr; content::TestWebUI web_ui_; std::unique_ptr<SiteSettingsHandler> handler_; #if BUILDFLAG(IS_CHROMEOS_ASH) - std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; + std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; #endif raw_ptr<browsing_topics::MockBrowsingTopicsService> mock_browsing_topics_service_; raw_ptr<MockPrivacySandboxService> mock_privacy_sandbox_service_; }; +class SiteSettingsHandlerTest : public SiteSettingsHandlerBaseTest, + public testing::WithParamInterface<bool> {}; + // True if testing for handle clear unpartitioned usage with HTTPS scheme URL. // When set to true, the tests use HTTPS scheme as origin. When set to // false, the tests use HTTP scheme as origin. @@ -1928,6 +1986,10 @@ void SetUp() override { BrowserWithTestWindowTest::SetUp(); +#if BUILDFLAG(IS_CHROMEOS_ASH) + SetUpUserManager(profile()); +#endif + handler_ = std::make_unique<SiteSettingsHandler>(profile()); handler()->set_web_ui(web_ui()); handler()->AllowJavascript(); @@ -1967,6 +2029,25 @@ BrowserWithTestWindowTest::TearDown(); } +#if BUILDFLAG(IS_CHROMEOS_ASH) + void SetUpUserManager(TestingProfile* profile) { + // On ChromeOS a user account is needed in order to check whether the user + // account is affiliated with the device owner for the purposes of applying + // enterprise policy. + constexpr char kTestUserGaiaId[] = "1111111111"; + auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>(); + auto* fake_user_manager_ptr = fake_user_manager.get(); + scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( + std::move(fake_user_manager)); + + auto account_id = + AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + fake_user_manager_ptr->AddUserWithAffiliation(account_id, + /*is_affiliated=*/true); + fake_user_manager_ptr->LoginUser(account_id); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + infobars::ContentInfoBarManager* GetInfoBarManagerForTab(Browser* browser, int tab_index, GURL* tab_url) { @@ -2511,26 +2592,23 @@ namespace { -constexpr char kUsbPolicySetting[] = R"( - [ - { - "devices": [{ "vendor_id": 6353, "product_id": 5678 }], - "urls": ["https://chromium.org"] - }, { - "devices": [{ "vendor_id": 6353 }], - "urls": ["https://google.com,https://android.com"] - }, { - "devices": [{ "vendor_id": 6354 }], - "urls": ["https://android.com,"] - }, { - "devices": [{}], - "urls": ["https://google.com,https://google.com"] - } - ])"; +std::vector<std::string> GetExceptionDisplayNames( + const base::Value& exceptions) { + std::vector<std::string> display_names; + for (const base::Value& exception : exceptions.GetList()) { + const std::string* display_name = + exception.GetDict().FindString(site_settings::kDisplayName); + if (display_name) { + display_names.push_back(*display_name); + } + } + return display_names; +} } // namespace -class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest { +class SiteSettingsHandlerChooserExceptionTest + : public SiteSettingsHandlerBaseTest { protected: const GURL kAndroidUrl{"https://android.com"}; const GURL kChromiumUrl{"https://chromium.org"}; @@ -2538,103 +2616,22 @@ const GURL kWebUIUrl{"chrome://test"}; void SetUp() override { - // Set up UsbChooserContext first, since the granting of device permissions - // causes the WebUI listener callbacks for - // contentSettingSitePermissionChanged and - // contentSettingChooserPermissionChanged to be fired. The base class SetUp - // method reset the WebUI call data. - SetUpUsbChooserContext(); - SiteSettingsHandlerTest::SetUp(); + SiteSettingsHandlerBaseTest::SetUp(); + SetUpChooserContext(); + SetUpPolicyGrantedPermissions(); + + // Add the observer for permission changes. + GetChooserContext(profile())->AddObserver(&observer_); } void TearDown() override { - auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile()); - chooser_context->permissions::ObjectPermissionContextBase::RemoveObserver( - &observer_); - } - - // Sets up the UsbChooserContext with two devices and permissions for these - // devices. It also adds three policy defined permissions. There are three - // devices that are granted user permissions. Two are covered by different - // policy permissions, while the third is not covered by policy at all. These - // unit tests will check that the WebUI is able to receive the exceptions and - // properly manipulate their permissions. - void SetUpUsbChooserContext() { - persistent_device_info_ = device_manager_.CreateAndAddDevice( - 6353, 5678, "Google", "Gizmo", "123ABC"); - ephemeral_device_info_ = - device_manager_.CreateAndAddDevice(6354, 0, "Google", "Gadget", ""); - user_granted_device_info_ = device_manager_.CreateAndAddDevice( - 6355, 0, "Google", "Widget", "789XYZ"); - - auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile()); - mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager; - device_manager_.AddReceiver( - device_manager.InitWithNewPipeAndPassReceiver()); - chooser_context->SetDeviceManagerForTesting(std::move(device_manager)); - chooser_context->GetDevices(base::DoNothing()); - base::RunLoop().RunUntilIdle(); - - const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); - const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); - const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); - const auto kWebUIOrigin = url::Origin::Create(kWebUIUrl); - - // Add the user granted permissions for testing. - // These two persistent device permissions should be lumped together with - // the policy permissions, since they apply to the same device and URL. - chooser_context->GrantDevicePermission(kChromiumOrigin, - *persistent_device_info_); - chooser_context->GrantDevicePermission(kGoogleOrigin, - *persistent_device_info_); - chooser_context->GrantDevicePermission(kWebUIOrigin, - *persistent_device_info_); - chooser_context->GrantDevicePermission(kAndroidOrigin, - *ephemeral_device_info_); - chooser_context->GrantDevicePermission(kAndroidOrigin, - *user_granted_device_info_); - - // Add the policy granted permissions for testing. - auto policy_value = base::JSONReader::ReadDeprecated(kUsbPolicySetting); - DCHECK(policy_value); - profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls, - *policy_value); - - // Add the observer for permission changes. - chooser_context->permissions::ObjectPermissionContextBase::AddObserver( - &observer_); - } - - void SetUpOffTheRecordUsbChooserContext() { - off_the_record_device_ = device_manager_.CreateAndAddDevice( - 6353, 8765, "Google", "Contraption", "A9B8C7"); - - CreateIncognitoProfile(); - auto* chooser_context = - UsbChooserContextFactory::GetForProfile(incognito_profile()); - mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager; - device_manager_.AddReceiver( - device_manager.InitWithNewPipeAndPassReceiver()); - chooser_context->SetDeviceManagerForTesting(std::move(device_manager)); - chooser_context->GetDevices(base::DoNothing()); - base::RunLoop().RunUntilIdle(); - - const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); - chooser_context->GrantDevicePermission(kChromiumOrigin, - *off_the_record_device_); - - // Add the observer for permission changes. - chooser_context->permissions::ObjectPermissionContextBase::AddObserver( - &observer_); + GetChooserContext(profile())->RemoveObserver(&observer_); + SiteSettingsHandlerBaseTest::TearDown(); } void DestroyIncognitoProfile() override { - auto* chooser_context = - UsbChooserContextFactory::GetForProfile(incognito_profile()); - chooser_context->permissions::ObjectPermissionContextBase::RemoveObserver( - &observer_); - - SiteSettingsHandlerTest::DestroyIncognitoProfile(); + GetChooserContext(incognito_profile())->RemoveObserver(&observer_); + SiteSettingsHandlerBaseTest::DestroyIncognitoProfile(); } // Call SiteSettingsHandler::HandleGetChooserExceptionList for |chooser_type| @@ -2674,7 +2671,7 @@ // Iterate through the exception's sites array and return true if a site // exception matches |requesting_origin| and |embedding_origin|. bool ChooserExceptionContainsSiteException(const base::Value& exception, - const std::string& origin) { + base::StringPiece origin) { const base::Value* sites = exception.FindListKey(site_settings::kSites); if (!sites) return false; @@ -2694,8 +2691,8 @@ // chooser exception with |display_name| that contains a site exception for // |origin|. bool ChooserExceptionContainsSiteException(const base::Value& exceptions, - const std::string& display_name, - const std::string& origin) { + base::StringPiece display_name, + base::StringPiece origin) { if (!exceptions.is_list()) return false; @@ -2712,210 +2709,1495 @@ return false; } - device::mojom::UsbDeviceInfoPtr ephemeral_device_info_; - device::mojom::UsbDeviceInfoPtr off_the_record_device_; - device::mojom::UsbDeviceInfoPtr persistent_device_info_; - device::mojom::UsbDeviceInfoPtr user_granted_device_info_; + void TestHandleGetChooserExceptionList() { + AddPersistentDevice(); + AddEphemeralDevice(); + AddUserGrantedDevice(); + base::RunLoop().RunUntilIdle(); - permissions::MockPermissionObserver observer_; + SetUpUserGrantedPermissions(); - private: - device::FakeUsbDeviceManager device_manager_; -}; + base::RunLoop().RunUntilIdle(); + web_ui()->ClearTrackedCalls(); -TEST_F(SiteSettingsHandlerChooserExceptionTest, - HandleGetChooserExceptionListForUsb) { - const std::string kUsbChooserGroupName( - site_settings::ContentSettingsTypeToGroupName( - ContentSettingsType::USB_CHOOSER_DATA)); + const std::string group_name( + site_settings::ContentSettingsTypeToGroupName(content_type())); - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/1u); - EXPECT_EQ(exceptions.GetList().size(), 5u); - - // Don't include WebUI schemes. - const std::string kWebUIOriginStr = - kWebUIUrl.DeprecatedGetOriginAsURL().spec(); - EXPECT_FALSE(ChooserExceptionContainsSiteException(exceptions, "Gizmo", - kWebUIOriginStr)); -} - -TEST_F(SiteSettingsHandlerChooserExceptionTest, - HandleGetChooserExceptionListForUsbOffTheRecord) { - const std::string kUsbChooserGroupName( - site_settings::ContentSettingsTypeToGroupName( - ContentSettingsType::USB_CHOOSER_DATA)); - SetUpOffTheRecordUsbChooserContext(); - web_ui()->ClearTrackedCalls(); - - // The objects returned by GetChooserExceptionListFromProfile should also - // include the incognito permissions. The two extra objects represent the - // "Widget" device and the policy permission for "Unknown product 0x162E from - // Google Inc.". The policy granted permission shows up here because the off - // the record profile does not have a user granted permission for the - // |persistent_device_info_|, so it cannot use the name of that device. - { const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/1u); - EXPECT_EQ(exceptions.GetList().size(), 7u); - for (const auto& exception : exceptions.GetList()) { - LOG(INFO) << exception.FindKey(site_settings::kDisplayName)->GetString(); + group_name, /*expected_total_calls=*/1u); + + // There are 9 granted permissions: + // 1. Persistent permission for persistent-device on kChromiumOrigin + // 2. Persistent permission for persistent-device on kGoogleOrigin + // 3. Persistent permission for persistent-device on kWebUIOrigin + // 4. Persistent permission for user-granted-device on kAndroidOrigin + // 5. Ephemeral permission for ephemeral-device on kAndroidOrigin + // 6. Policy-granted permission for any device on kGoogleOrigin + // 7. Policy-granted permission for vendor 18D1 on kAndroidOrigin + // 8. Policy-granted permission for vendor 18D2 on kAndroidOrigin + // 9. Policy-granted permission for device 18D1:162E on kChromiumOrigin + // + // Permission 3 is ignored by GetChooserExceptionListFromProfile because its + // origin has a WebUI scheme (chrome://). + // + // Some of the user-granted permissions are redundant due to policy-granted + // permissions. Permission 1 is redundant due to permission 9; 2 is + // redundant due to 6; 5 is redundant due to 8. UsbChooserContext omits + // redundant items but other APIs do not. This causes + // GetChooserExceptionListForProfile to return a different number of + // exceptions depending on the API. + // + // UsbChooserContext also detects when a policy-granted permission refers to + // the same origin and device IDs as a user-granted permission. When + // deduplicating redundant exceptions, the user-granted exception display + // name is used because it contains the device name. + // + // TODO(https://crbug.com/1392442): Update SerialChooserContext and + // HidChooserContext to deduplicate redundant exceptions. + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + // BluetoothChooserContext creates a different permission object for + // each (device,origin) pair, so persistent-device shows up for each of + // kChromiumOrigin and kGoogleOrigin. + // + // TODO(https://crbug.com/1040174): No policy-granted exceptions are + // included because Web Bluetooth does not support granting device + // permissions by policy. + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "persistent-device", + "ephemeral-device", "user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "user-granted-device", + "ephemeral-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "user-granted-device", + GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName())); + break; + default: + NOTREACHED(); + break; + } + + // Don't include WebUI schemes. + const std::string kWebUIOriginStr = + kWebUIUrl.DeprecatedGetOriginAsURL().spec(); + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "persistent-device", kWebUIOriginStr)); + } + + void TestHandleGetChooserExceptionListForOffTheRecord() { + SetUpOffTheRecordChooserContext(); + AddPersistentDevice(); + AddEphemeralDevice(); + AddUserGrantedDevice(); + AddOffTheRecordDevice(); + base::RunLoop().RunUntilIdle(); + + SetUpUserGrantedPermissions(); + + base::RunLoop().RunUntilIdle(); + web_ui()->ClearTrackedCalls(); + + const std::string group_name( + site_settings::ContentSettingsTypeToGroupName(content_type())); + + // The objects returned by GetChooserExceptionListFromProfile should also + // include the incognito permissions. + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/1u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "persistent-device", + "ephemeral-device", "user-granted-device", + "off-the-record-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "persistent-device", "ephemeral-device", + "user-granted-device", "off-the-record-device", + GetAllDevicesDisplayName(), GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "persistent-device", "user-granted-device", + "off-the-record-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + } + + // Destroy the off the record profile and check that the objects returned do + // not include incognito permissions anymore. The destruction of the profile + // causes the "onIncognitoStatusChanged" WebUIListener callback to fire. + DestroyIncognitoProfile(); + EXPECT_EQ(web_ui()->call_data().size(), 2u); + + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/3u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "persistent-device", + "ephemeral-device", "user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "persistent-device", "ephemeral-device", + "user-granted-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "user-granted-device", + GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName())); + break; + default: + NOTREACHED(); + break; + } } } - // Destroy the off the record profile and check that the objects returned do - // not include incognito permissions anymore. The destruction of the profile - // causes the "onIncognitoStatusChanged" WebUIListener callback to fire. - DestroyIncognitoProfile(); - EXPECT_EQ(web_ui()->call_data().size(), 2u); + void TestHandleResetChooserExceptionForSite() { + AddPersistentDevice(); + AddEphemeralDevice(); + AddUserGrantedDevice(); + base::RunLoop().RunUntilIdle(); - { - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/3u); - EXPECT_EQ(exceptions.GetList().size(), 5u); + SetUpUserGrantedPermissions(); + + base::RunLoop().RunUntilIdle(); + web_ui()->ClearTrackedCalls(); + + const std::string group_name( + site_settings::ContentSettingsTypeToGroupName(content_type())); + const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); + const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const std::string kAndroidOriginStr = + kAndroidUrl.DeprecatedGetOriginAsURL().spec(); + const std::string kChromiumOriginStr = + kChromiumUrl.DeprecatedGetOriginAsURL().spec(); + const std::string kGoogleOriginStr = + kGoogleUrl.DeprecatedGetOriginAsURL().spec(); + + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/1u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "persistent-device", + "ephemeral-device", "user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "persistent-device", "ephemeral-device", + "user-granted-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "user-granted-device", + GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName())); + break; + default: + NOTREACHED(); + break; + } + } + + // User granted USB permissions for devices also containing policy + // permissions should be able to be reset without removing the chooser + // exception object from the list. + base::Value::List args; + args.Append(group_name); + args.Append(kGoogleOriginStr); + args.Append(GetPersistentDeviceValueForOrigin(kGoogleOrigin)); + + EXPECT_CALL(observer_, + OnObjectPermissionChanged({guard_type()}, content_type())); + EXPECT_CALL(observer_, OnPermissionRevoked(kGoogleOrigin)); + handler()->HandleResetChooserExceptionForSite(args); + GetChooserContext(profile())->FlushScheduledSaveSettingsCalls(); + + // The HandleResetChooserExceptionForSite() method should have also caused + // the WebUIListenerCallbacks for contentSettingSitePermissionChanged and + // contentSettingChooserPermissionChanged to fire. + EXPECT_EQ(web_ui()->call_data().size(), 3u); + { + // The exception list size should not have been reduced since there is + // still a policy granted permission for "persistent-device". + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/4u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "ephemeral-device", + "user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "persistent-device", "ephemeral-device", + "user-granted-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("persistent-device", "user-granted-device", + GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName())); + break; + default: + NOTREACHED(); + break; + } + + // Ensure that the sites list does not contain the URLs of the removed + // permission. + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "persistent-device", kGoogleOriginStr)); + + // User granted exceptions that are also granted by policy are only + // displayed through the policy granted site exception, so ensure that the + // policy exception is present under "persistent-device". + if (content_type() != ContentSettingsType::BLUETOOTH_CHOOSER_DATA) { + EXPECT_TRUE(ChooserExceptionContainsSiteException( + exceptions, "persistent-device", kChromiumOriginStr)); + } + } + + // Try revoking the user-granted permission for persistent-device. There is + // also a policy-granted permission for the same device. + args.clear(); + args.Append(group_name); + args.Append(kChromiumOriginStr); + args.Append(GetPersistentDeviceValueForOrigin(kChromiumOrigin)); + + EXPECT_CALL(observer_, + OnObjectPermissionChanged({guard_type()}, content_type())); + EXPECT_CALL(observer_, OnPermissionRevoked(kChromiumOrigin)); + handler()->HandleResetChooserExceptionForSite(args); + GetChooserContext(profile())->FlushScheduledSaveSettingsCalls(); + + // The HandleResetChooserExceptionForSite() method should have also caused + // the WebUIListenerCallbacks for contentSettingSitePermissionChanged and + // contentSettingChooserPermissionChanged to fire. + EXPECT_EQ(web_ui()->call_data().size(), 6u); + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/7u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("ephemeral-device", "user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("ephemeral-device", "user-granted-device", + GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "user-granted-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + + // Ensure that the sites list still displays a site exception entry for an + // origin of kGoogleOriginStr. Since now the device has had its + // permission revoked, the policy-provided object will not be able to + // deduce the name "persistent-device" from the connected device. As such + // we check that the policy is still active by looking for the genericly + // constructed name. + if (content_type() != ContentSettingsType::BLUETOOTH_CHOOSER_DATA) { + EXPECT_TRUE(ChooserExceptionContainsSiteException( + exceptions, GetUnknownProductDisplayName(), kChromiumOriginStr)); + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "persistent-device", kGoogleOriginStr)); + } + + // Ensure the exception for user-granted-device on kAndroidOrigin is + // present since we will try to revoke it. + EXPECT_TRUE(ChooserExceptionContainsSiteException( + exceptions, "user-granted-device", kAndroidOriginStr)); + } + + // User granted USB permissions that are not covered by policy should be + // able to be reset and the chooser exception entry should be removed from + // the list when the exception only has one site exception granted to it. + args.clear(); + args.Append(group_name); + args.Append(kAndroidOriginStr); + args.Append(GetUserGrantedDeviceValueForOrigin(kAndroidOrigin)); + + EXPECT_CALL(observer_, + OnObjectPermissionChanged({guard_type()}, content_type())); + EXPECT_CALL(observer_, OnPermissionRevoked(kAndroidOrigin)); + handler()->HandleResetChooserExceptionForSite(args); + GetChooserContext(profile())->FlushScheduledSaveSettingsCalls(); + + // The HandleResetChooserExceptionForSite() method should have also caused + // the WebUIListenerCallbacks for contentSettingSitePermissionChanged and + // contentSettingChooserPermissionChanged to fire. + EXPECT_EQ(web_ui()->call_data().size(), 9u); + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/10u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("ephemeral-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "ephemeral-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre(GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "user-granted-device", kAndroidOriginStr)); + } } + + void TestHandleSetOriginPermissions() { + constexpr base::StringPiece kYoutubeOriginStr = "https://youtube.com/"; + const GURL kYoutubeUrl{kYoutubeOriginStr}; + const auto kYoutubeOrigin = url::Origin::Create(kYoutubeUrl); + + // Grant permissions for user-granted-device on `kYoutubeOrigin`. + AddUserGrantedDevice(); + SetUpUserGrantedPermissionForOrigin(kYoutubeOrigin); + + base::RunLoop().RunUntilIdle(); + web_ui()->ClearTrackedCalls(); + + const std::string group_name( + site_settings::ContentSettingsTypeToGroupName(content_type())); + + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/1u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre("user-granted-device")); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT(GetExceptionDisplayNames(exceptions), + UnorderedElementsAre( + "user-granted-device", GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + EXPECT_TRUE(ChooserExceptionContainsSiteException( + exceptions, "user-granted-device", kYoutubeOriginStr)); + } + + // Clear data for kYoutubeOrigin. The permission should be revoked. + base::Value::List args; + args.Append(kYoutubeOriginStr); + args.Append(base::Value()); + args.Append( + content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT)); + + EXPECT_CALL(observer_, + OnObjectPermissionChanged({guard_type()}, content_type())); + EXPECT_CALL(observer_, OnPermissionRevoked(kYoutubeOrigin)); + handler()->HandleSetOriginPermissions(args); + GetChooserContext(profile())->FlushScheduledSaveSettingsCalls(); + + // HandleSetOriginPermissions caused WebUIListenerCallbacks: + // * contentSettingsChooserPermissionChanged once + // * contentSettingsSitePermissionChanged for each visible content type + // * contentSettingsSitePermissionChanged again for `content_type()` + const size_t kContentSettingsTypeCount = + site_settings::GetVisiblePermissionCategories().size(); + EXPECT_EQ(kContentSettingsTypeCount + 3, web_ui()->call_data().size()); + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/kContentSettingsTypeCount + 4); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_TRUE(exceptions.GetList().empty()); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre(GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "user-granted-device", kYoutubeOriginStr)); + } + } + + void TestHandleSetOriginPermissionsPolicyOnly() { + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const std::string kGoogleOriginStr = + kGoogleUrl.DeprecatedGetOriginAsURL().spec(); + + base::RunLoop().RunUntilIdle(); + web_ui()->ClearTrackedCalls(); + + const std::string group_name( + site_settings::ContentSettingsTypeToGroupName(content_type())); + + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/1u); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_TRUE(exceptions.GetList().empty()); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre(GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + } + + // Clear data for kGoogleOrigin. + base::Value::List args; + args.Append(kGoogleOriginStr); + args.Append(base::Value()); + args.Append( + content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT)); + + EXPECT_CALL(observer_, OnObjectPermissionChanged).Times(0); + EXPECT_CALL(observer_, OnPermissionRevoked).Times(0); + handler()->HandleSetOriginPermissions(args); + GetChooserContext(profile())->FlushScheduledSaveSettingsCalls(); + + // HandleSetOriginPermissions caused WebUIListenerCallbacks: + // * contentSettingsSitePermissionChanged for each visible content type + const size_t kContentSettingsTypeCount = + site_settings::GetVisiblePermissionCategories().size(); + EXPECT_EQ(kContentSettingsTypeCount + 1, web_ui()->call_data().size()); + { + const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( + group_name, /*expected_total_calls=*/kContentSettingsTypeCount + 2); + switch (content_type()) { + case ContentSettingsType::BLUETOOTH_CHOOSER_DATA: + EXPECT_TRUE(exceptions.GetList().empty()); + break; + case ContentSettingsType::HID_CHOOSER_DATA: + case ContentSettingsType::SERIAL_CHOOSER_DATA: + case ContentSettingsType::USB_CHOOSER_DATA: + EXPECT_THAT( + GetExceptionDisplayNames(exceptions), + UnorderedElementsAre(GetAllDevicesDisplayName(), + GetDevicesFromGoogleDisplayName(), + GetDevicesFromVendor18D2DisplayName(), + GetUnknownProductDisplayName())); + break; + default: + NOTREACHED(); + break; + } + } + } + + // Returns the ContentSettingsType for the chooser data (device permissions). + virtual ContentSettingsType content_type() = 0; + + // Returns the ContentSettingsType for the guard permission. + virtual ContentSettingsType guard_type() = 0; + + // Returns the chooser context for `profile`. + virtual permissions::ObjectPermissionContextBase* GetChooserContext( + Profile* profile) = 0; + + // Sets up the chooser context. + virtual void SetUpChooserContext() = 0; + + // Creates an incognito profile and sets up the chooser context for that + // profile. Tests must call DestroyIncognitoProfile before exiting. + virtual void SetUpOffTheRecordChooserContext() {} + + // Grants permissions used by tests. There are four devices that are + // granted user permissions. Two (persistent-device and ephemeral-device) are + // covered by different policy permissions, while the third + // (user-granted-device) is not covered by policy at all. If the + // off-the-record-device is present, a user-granted permission is granted for + // the incognito profile. + virtual void SetUpUserGrantedPermissions() = 0; + + // Configures policies to automatically grant device permissions. + virtual void SetUpPolicyGrantedPermissions() {} + + // Grants device permissions for user-granted-device on `origin`. + virtual void SetUpUserGrantedPermissionForOrigin( + const url::Origin& origin) = 0; + + // Create and add a device eligible for persistent permissions. The device + // name is "persistent-device". + virtual void AddPersistentDevice() = 0; + + // Create and add a device ineligible for persistent permissions. The device + // name is "ephemeral-device". + virtual void AddEphemeralDevice() = 0; + + // Create and add a device. The permission policies added in + // `SetUpPolicyGrantedPermissions` should not grant permissions for this + // device except for policies which affect all devices. The device name is + // "user-granted-device". + virtual void AddUserGrantedDevice() = 0; + + // Create and add a device. Tests should only grant permissions for this + // device using the off the record profile. The device name is + // "off-the-record-device". + virtual void AddOffTheRecordDevice() = 0; + + // Returns the permission object representing persistent-device granted to + // `origin`. + virtual base::Value GetPersistentDeviceValueForOrigin( + const url::Origin& origin) = 0; + + // Returns the permission object representing user-granted-device granted to + // `origin`. + virtual base::Value GetUserGrantedDeviceValueForOrigin( + const url::Origin& origin) = 0; + + // Returns the display name for a chooser exception that allows an origin to + // access any device. + virtual std::string GetAllDevicesDisplayName() { return {}; } + + // Returns the display name for a chooser exception that allows an origin to + // access any device with the Google vendor ID. + virtual std::string GetDevicesFromGoogleDisplayName() { return {}; } + + // Returns the display name for a chooser exception that allows an origin to + // access any device from vendor 0x18D2. + virtual std::string GetDevicesFromVendor18D2DisplayName() { return {}; } + + // Returns the display name for a chooser exception that allows an origin to + // access a specific device by its vendor and product IDs. + virtual std::string GetUnknownProductDisplayName() { return {}; } + + permissions::MockPermissionObserver observer_; +}; + +class SiteSettingsHandlerBluetoothTest + : public SiteSettingsHandlerChooserExceptionTest { + protected: + SiteSettingsHandlerBluetoothTest() + : SiteSettingsHandlerChooserExceptionTest() { + feature_list_.InitAndEnableFeature( + features::kWebBluetoothNewPermissionsBackend); + } + + permissions::ObjectPermissionContextBase* GetChooserContext( + Profile* profile) override { + return BluetoothChooserContextFactory::GetForProfile(profile); + } + + void SetUpChooserContext() override { + adapter_ = base::MakeRefCounted<NiceMock<device::MockBluetoothAdapter>>(); + EXPECT_CALL(*adapter_, IsPresent).WillRepeatedly(Return(true)); + EXPECT_CALL(*adapter_, IsPowered).WillRepeatedly(Return(true)); + device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_); + base::RunLoop().RunUntilIdle(); + } + + void SetUpOffTheRecordChooserContext() override { + CreateIncognitoProfile(); + GetChooserContext(incognito_profile())->AddObserver(&observer_); + } + + void AddPersistentDevice() override { + persistent_device_ = + std::make_unique<NiceMock<device::MockBluetoothDevice>>( + adapter_.get(), /*bluetooth_class=*/0, /*name=*/"persistent-device", + /*address=*/"1", /*paired=*/false, /*connected=*/false); + } + + void AddEphemeralDevice() override { + ephemeral_device_ = std::make_unique<NiceMock<device::MockBluetoothDevice>>( + adapter_.get(), /*bluetooth_class=*/0, /*name=*/"ephemeral-device", + /*address=*/"2", /*paired=*/false, /*connected=*/false); + } + + void AddUserGrantedDevice() override { + user_granted_device_ = + std::make_unique<NiceMock<device::MockBluetoothDevice>>( + adapter_.get(), /*bluetooth_class=*/0, + /*name=*/"user-granted-device", /*address=*/"3", /*paired=*/false, + /*connected=*/false); + } + + void AddOffTheRecordDevice() override { + off_the_record_device_ = + std::make_unique<NiceMock<device::MockBluetoothDevice>>( + adapter_.get(), /*bluetooth_class=*/0, + /*name=*/"off-the-record-device", /*address=*/"4", /*paired=*/false, + /*connected=*/false); + } + + void SetUpUserGrantedPermissions() override { + const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); + const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const auto kWebUIOrigin = url::Origin::Create(kWebUIUrl); + + auto options = blink::mojom::WebBluetoothRequestDeviceOptions::New(); + options->accept_all_devices = true; + { + base::RunLoop loop; + auto barrier_closure = base::BarrierClosure(5, loop.QuitClosure()); + auto* bluetooth_chooser_context = + BluetoothChooserContextFactory::GetForProfile(profile()); + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::BLUETOOTH_GUARD}, + ContentSettingsType::BLUETOOTH_CHOOSER_DATA)) + .Times(5) + .WillRepeatedly(RunClosure(barrier_closure)); + bluetooth_chooser_context->GrantServiceAccessPermission( + kChromiumOrigin, persistent_device_.get(), options.get()); + bluetooth_chooser_context->GrantServiceAccessPermission( + kGoogleOrigin, persistent_device_.get(), options.get()); + bluetooth_chooser_context->GrantServiceAccessPermission( + kWebUIOrigin, persistent_device_.get(), options.get()); + bluetooth_chooser_context->GrantServiceAccessPermission( + kAndroidOrigin, ephemeral_device_.get(), options.get()); + bluetooth_chooser_context->GrantServiceAccessPermission( + kAndroidOrigin, user_granted_device_.get(), options.get()); + loop.Run(); + } + + if (off_the_record_device_) { + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::BLUETOOTH_GUARD}, + ContentSettingsType::BLUETOOTH_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + BluetoothChooserContextFactory::GetForProfile(incognito_profile()) + ->GrantServiceAccessPermission( + kChromiumOrigin, off_the_record_device_.get(), options.get()); + loop.Run(); + } + } + + void SetUpUserGrantedPermissionForOrigin(const url::Origin& origin) override { + auto* bluetooth_chooser_context = + BluetoothChooserContextFactory::GetForProfile(profile()); + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::BLUETOOTH_GUARD}, + ContentSettingsType::BLUETOOTH_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + auto options = blink::mojom::WebBluetoothRequestDeviceOptions::New(); + options->accept_all_devices = true; + bluetooth_chooser_context->GrantServiceAccessPermission( + origin, user_granted_device_.get(), options.get()); + loop.Run(); + } + + base::Value GetPersistentDeviceValueForOrigin( + const url::Origin& origin) override { + auto options = blink::mojom::WebBluetoothRequestDeviceOptions::New(); + options->accept_all_devices = true; + auto device_id = + BluetoothChooserContextFactory::GetForProfile(profile()) + ->GetWebBluetoothDeviceId(origin, persistent_device_->GetAddress()); + return base::Value(permissions::BluetoothChooserContext::DeviceInfoToValue( + persistent_device_.get(), options.get(), device_id)); + } + + base::Value GetUserGrantedDeviceValueForOrigin( + const url::Origin& origin) override { + auto options = blink::mojom::WebBluetoothRequestDeviceOptions::New(); + options->accept_all_devices = true; + auto device_id = BluetoothChooserContextFactory::GetForProfile(profile()) + ->GetWebBluetoothDeviceId( + origin, user_granted_device_->GetAddress()); + return base::Value(permissions::BluetoothChooserContext::DeviceInfoToValue( + user_granted_device_.get(), options.get(), device_id)); + } + + ContentSettingsType content_type() override { + return ContentSettingsType::BLUETOOTH_CHOOSER_DATA; + } + + ContentSettingsType guard_type() override { + return ContentSettingsType::BLUETOOTH_GUARD; + } + + base::test::ScopedFeatureList feature_list_; + scoped_refptr<NiceMock<device::MockBluetoothAdapter>> adapter_; + std::unique_ptr<NiceMock<device::MockBluetoothDevice>> ephemeral_device_; + std::unique_ptr<NiceMock<device::MockBluetoothDevice>> off_the_record_device_; + std::unique_ptr<NiceMock<device::MockBluetoothDevice>> persistent_device_; + std::unique_ptr<NiceMock<device::MockBluetoothDevice>> user_granted_device_; +}; + +TEST_F(SiteSettingsHandlerBluetoothTest, HandleGetChooserExceptionList) { + TestHandleGetChooserExceptionList(); } -TEST_F(SiteSettingsHandlerChooserExceptionTest, - HandleResetChooserExceptionForSiteForUsb) { - const std::string kUsbChooserGroupName( - site_settings::ContentSettingsTypeToGroupName( - ContentSettingsType::USB_CHOOSER_DATA)); - const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); - const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); - const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); - const std::string kAndroidOriginStr = - kAndroidUrl.DeprecatedGetOriginAsURL().spec(); - const std::string kChromiumOriginStr = - kChromiumUrl.DeprecatedGetOriginAsURL().spec(); - const std::string kGoogleOriginStr = - kGoogleUrl.DeprecatedGetOriginAsURL().spec(); +TEST_F(SiteSettingsHandlerBluetoothTest, + HandleGetChooserExceptionListForOffTheRecord) { + TestHandleGetChooserExceptionListForOffTheRecord(); +} - { - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/1u); - EXPECT_EQ(exceptions.GetList().size(), 5u); +TEST_F(SiteSettingsHandlerBluetoothTest, HandleResetChooserExceptionForSite) { + TestHandleResetChooserExceptionForSite(); +} + +TEST_F(SiteSettingsHandlerBluetoothTest, HandleSetOriginPermissions) { + TestHandleSetOriginPermissions(); +} + +TEST_F(SiteSettingsHandlerBluetoothTest, HandleSetOriginPermissionsPolicyOnly) { + TestHandleSetOriginPermissionsPolicyOnly(); +} + +#if !BUILDFLAG(IS_ANDROID) +class SiteSettingsHandlerHidTest + : public SiteSettingsHandlerChooserExceptionTest { + protected: + void SetUpChooserContext() override { + mojo::PendingRemote<device::mojom::HidManager> hid_manager; + hid_manager_.AddReceiver(hid_manager.InitWithNewPipeAndPassReceiver()); + HidChooserContext* hid_chooser_context = + HidChooserContextFactory::GetForProfile(profile()); + TestFuture<std::vector<device::mojom::HidDeviceInfoPtr>> get_devices_future; + hid_chooser_context->SetHidManagerForTesting( + std::move(hid_manager), get_devices_future.GetCallback()); + EXPECT_TRUE(get_devices_future.Wait()); } - // User granted USB permissions for devices also containing policy permissions - // should be able to be reset without removing the chooser exception object - // from the list. - base::Value::List args; - args.Append(kUsbChooserGroupName); - args.Append(kGoogleOriginStr); - args.Append(UsbChooserContext::DeviceInfoToValue(*persistent_device_info_)); - - EXPECT_CALL(observer_, - OnObjectPermissionChanged(absl::optional<ContentSettingsType>( - ContentSettingsType::USB_GUARD), - ContentSettingsType::USB_CHOOSER_DATA)); - EXPECT_CALL(observer_, OnPermissionRevoked(kGoogleOrigin)); - handler()->HandleResetChooserExceptionForSite(args); - auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile()); - chooser_context->FlushScheduledSaveSettingsCalls(); - - // The HandleResetChooserExceptionForSite() method should have also caused the - // WebUIListenerCallbacks for contentSettingSitePermissionChanged and - // contentSettingChooserPermissionChanged to fire. - EXPECT_EQ(web_ui()->call_data().size(), 3u); - { - // The exception list size should not have been reduced since there is still - // a policy granted permission for the "Gizmo" device. - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/4u); - EXPECT_EQ(exceptions.GetList().size(), 5u); - - // Ensure that the sites list does not contain the URLs of the removed - // permission. - EXPECT_FALSE(ChooserExceptionContainsSiteException(exceptions, "Gizmo", - kGoogleOriginStr)); + void SetUpPolicyGrantedPermissions() override { + auto* local_state = TestingBrowserProcess::GetGlobal()->local_state(); + ASSERT_TRUE(local_state); + local_state->Set(prefs::kManagedWebHidAllowDevicesForUrls, ParseJson(R"( + [ + { + "devices": [{ "vendor_id": 6353, "product_id": 5678 }], + "urls": ["https://chromium.org"] + }, { + "devices": [{ "vendor_id": 6353 }], + "urls": ["https://android.com"] + }, { + "devices": [{ "vendor_id": 6354 }], + "urls": ["https://android.com"] + } + ])")); + local_state->Set(prefs::kManagedWebHidAllowAllDevicesForUrls, + ParseJson(R"([ "https://google.com" ])")); } - // User granted USB permissions that are also granted by policy should not - // be able to be reset. - args.clear(); - args.Append(kUsbChooserGroupName); - args.Append(kChromiumOriginStr); - args.Append(UsbChooserContext::DeviceInfoToValue(*persistent_device_info_)); - - { - const base::Value& exceptions = - GetChooserExceptionListFromWebUiCallData(kUsbChooserGroupName, 5u); - EXPECT_EQ(exceptions.GetList().size(), 5u); - - // User granted exceptions that are also granted by policy are only - // displayed through the policy granted site exception, so ensure that the - // policy exception is present under the "Gizmo" device. - EXPECT_TRUE(ChooserExceptionContainsSiteException(exceptions, "Gizmo", - kChromiumOriginStr)); - EXPECT_FALSE(ChooserExceptionContainsSiteException(exceptions, "Gizmo", - kGoogleOriginStr)); + void SetUpOffTheRecordChooserContext() override { + CreateIncognitoProfile(); + mojo::PendingRemote<device::mojom::HidManager> hid_manager; + hid_manager_.AddReceiver(hid_manager.InitWithNewPipeAndPassReceiver()); + HidChooserContext* hid_chooser_context = + HidChooserContextFactory::GetForProfile(incognito_profile()); + TestFuture<std::vector<device::mojom::HidDeviceInfoPtr>> get_devices_future; + hid_chooser_context->SetHidManagerForTesting( + std::move(hid_manager), get_devices_future.GetCallback()); + EXPECT_TRUE(get_devices_future.Wait()); + GetChooserContext(incognito_profile())->AddObserver(&observer_); } - EXPECT_CALL(observer_, - OnObjectPermissionChanged(absl::optional<ContentSettingsType>( - ContentSettingsType::USB_GUARD), - ContentSettingsType::USB_CHOOSER_DATA)); - EXPECT_CALL(observer_, OnPermissionRevoked(kChromiumOrigin)); - handler()->HandleResetChooserExceptionForSite(args); - chooser_context->FlushScheduledSaveSettingsCalls(); - - // The HandleResetChooserExceptionForSite() method should have also caused the - // WebUIListenerCallbacks for contentSettingSitePermissionChanged and - // contentSettingChooserPermissionChanged to fire. - EXPECT_EQ(web_ui()->call_data().size(), 7u); - { - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/8u); - EXPECT_EQ(exceptions.GetList().size(), 5u); - - // Ensure that the sites list still displays a site exception entry for an - // origin of kGoogleOriginStr. Since now the device has had its - // permission revoked, the policy-provided object will not be able to deduce - // the name "Gizmo" from the connected device. As such we check that the - // policy is still active by looking for the genericly constructed name. - EXPECT_TRUE(ChooserExceptionContainsSiteException( - exceptions, "Unknown product 0x162E from Google Inc.", - kChromiumOriginStr)); - EXPECT_FALSE(ChooserExceptionContainsSiteException(exceptions, "Gizmo", - kGoogleOriginStr)); + void AddPersistentDevice() override { + persistent_device_ = hid_manager_.CreateAndAddDevice( + /*physical_device_id=*/"1", /*vendor_id=*/6353, /*product_id=*/5678, + /*product_name=*/"persistent-device", /*serial_number=*/"123ABC", + device::mojom::HidBusType::kHIDBusTypeUSB); } - // User granted USB permissions that are not covered by policy should be able - // to be reset and the chooser exception entry should be removed from the list - // when the exception only has one site exception granted to it.. - args.clear(); - args.Append(kUsbChooserGroupName); - args.Append(kAndroidOriginStr); - args.Append(UsbChooserContext::DeviceInfoToValue(*user_granted_device_info_)); - - { - const base::Value& exceptions = - GetChooserExceptionListFromWebUiCallData(kUsbChooserGroupName, 9u); - EXPECT_EQ(exceptions.GetList().size(), 5u); - EXPECT_TRUE(ChooserExceptionContainsSiteException(exceptions, "Widget", - kAndroidOriginStr)); + void AddEphemeralDevice() override { + ephemeral_device_ = hid_manager_.CreateAndAddDevice( + /*physical_device_id=*/"2", /*vendor_id=*/6354, /*product_id=*/0, + /*product_name=*/"ephemeral-device", /*serial_number=*/"", + device::mojom::HidBusType::kHIDBusTypeUSB); } - EXPECT_CALL(observer_, - OnObjectPermissionChanged(absl::optional<ContentSettingsType>( - ContentSettingsType::USB_GUARD), - ContentSettingsType::USB_CHOOSER_DATA)); - EXPECT_CALL(observer_, OnPermissionRevoked(kAndroidOrigin)); - handler()->HandleResetChooserExceptionForSite(args); - chooser_context->FlushScheduledSaveSettingsCalls(); - - // The HandleResetChooserExceptionForSite() method should have also caused the - // WebUIListenerCallbacks for contentSettingSitePermissionChanged and - // contentSettingChooserPermissionChanged to fire. - EXPECT_EQ(web_ui()->call_data().size(), 11u); - { - const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( - kUsbChooserGroupName, /*expected_total_calls=*/12u); - EXPECT_EQ(exceptions.GetList().size(), 4u); - EXPECT_FALSE(ChooserExceptionContainsSiteException(exceptions, "Widget", - kAndroidOriginStr)); + void AddUserGrantedDevice() override { + user_granted_device_ = hid_manager_.CreateAndAddDevice( + /*physical_device_id=*/"3", /*vendor_id=*/6355, /*product_id=*/0, + /*product_name=*/"user-granted-device", /*serial_number=*/"789XYZ", + device::mojom::HidBusType::kHIDBusTypeUSB); } + + void AddOffTheRecordDevice() override { + off_the_record_device_ = hid_manager_.CreateAndAddDevice( + /*physical_device_id=*/"4", /*vendor_id=*/6353, + /*product_id=*/8765, /*product_name=*/"off-the-record-device", + /*serial_number=*/"A9B8C7", device::mojom::HidBusType::kHIDBusTypeUSB); + } + + void SetUpUserGrantedPermissions() override { + const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); + const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const auto kWebUIOrigin = url::Origin::Create(kWebUIUrl); + + // Add the user granted permissions for testing. + // These two persistent device permissions should be lumped together + // with the policy permissions, since they apply to the same device and + // URL. + { + base::RunLoop loop; + auto barrier_closure = base::BarrierClosure(5, loop.QuitClosure()); + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::HID_GUARD}, + ContentSettingsType::HID_CHOOSER_DATA)) + .Times(5) + .WillRepeatedly(RunClosure(barrier_closure)); + auto* hid_chooser_context = + HidChooserContextFactory::GetForProfile(profile()); + hid_chooser_context->GrantDevicePermission(kChromiumOrigin, + *persistent_device_); + hid_chooser_context->GrantDevicePermission(kGoogleOrigin, + *persistent_device_); + hid_chooser_context->GrantDevicePermission(kWebUIOrigin, + *persistent_device_); + hid_chooser_context->GrantDevicePermission(kAndroidOrigin, + *ephemeral_device_); + hid_chooser_context->GrantDevicePermission(kAndroidOrigin, + *user_granted_device_); + loop.Run(); + } + + if (off_the_record_device_) { + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::HID_GUARD}, + ContentSettingsType::HID_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + HidChooserContextFactory::GetForProfile(incognito_profile()) + ->GrantDevicePermission(kChromiumOrigin, *off_the_record_device_); + loop.Run(); + } + } + + void SetUpUserGrantedPermissionForOrigin(const url::Origin& origin) override { + auto* hid_chooser_context = + HidChooserContextFactory::GetForProfile(profile()); + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::HID_GUARD}, + ContentSettingsType::HID_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + hid_chooser_context->GrantDevicePermission(origin, *user_granted_device_); + loop.Run(); + } + + base::Value GetPersistentDeviceValueForOrigin( + const url::Origin& origin) override { + return HidChooserContext::DeviceInfoToValue(*persistent_device_); + } + + base::Value GetUserGrantedDeviceValueForOrigin( + const url::Origin& origin) override { + return HidChooserContext::DeviceInfoToValue(*user_granted_device_); + } + + std::string GetAllDevicesDisplayName() override { return "Any HID device"; } + + std::string GetDevicesFromGoogleDisplayName() override { + return "HID devices from vendor 18D1"; + } + + std::string GetDevicesFromVendor18D2DisplayName() override { + return "HID devices from vendor 18D2"; + } + + std::string GetUnknownProductDisplayName() override { + return "HID device (18D1:162E)"; + } + + permissions::ObjectPermissionContextBase* GetChooserContext( + Profile* profile) override { + return HidChooserContextFactory::GetForProfile(profile); + } + + ContentSettingsType content_type() override { + return ContentSettingsType::HID_CHOOSER_DATA; + } + + ContentSettingsType guard_type() override { + return ContentSettingsType::HID_GUARD; + } + + device::FakeHidManager hid_manager_; + device::mojom::HidDeviceInfoPtr ephemeral_device_; + device::mojom::HidDeviceInfoPtr off_the_record_device_; + device::mojom::HidDeviceInfoPtr persistent_device_; + device::mojom::HidDeviceInfoPtr user_granted_device_; +}; + +TEST_F(SiteSettingsHandlerHidTest, HandleGetChooserExceptionList) { + TestHandleGetChooserExceptionList(); +} + +TEST_F(SiteSettingsHandlerHidTest, + HandleGetChooserExceptionListForOffTheRecord) { + TestHandleGetChooserExceptionListForOffTheRecord(); +} + +TEST_F(SiteSettingsHandlerHidTest, HandleResetChooserExceptionForSite) { + TestHandleResetChooserExceptionForSite(); +} + +TEST_F(SiteSettingsHandlerHidTest, HandleSetOriginPermissions) { + TestHandleSetOriginPermissions(); +} + +TEST_F(SiteSettingsHandlerHidTest, HandleSetOriginPermissionsPolicyOnly) { + TestHandleSetOriginPermissionsPolicyOnly(); +} + +class SiteSettingsHandlerSerialTest + : public SiteSettingsHandlerChooserExceptionTest { + protected: + void SetUpChooserContext() override { + mojo::PendingRemote<device::mojom::SerialPortManager> serial_port_manager; + serial_port_manager_.AddReceiver( + serial_port_manager.InitWithNewPipeAndPassReceiver()); + SerialChooserContext* serial_chooser_context = + SerialChooserContextFactory::GetForProfile(profile()); + serial_chooser_context->SetPortManagerForTesting( + std::move(serial_port_manager)); + base::RunLoop().RunUntilIdle(); + } + + void SetUpPolicyGrantedPermissions() override { + auto* local_state = TestingBrowserProcess::GetGlobal()->local_state(); + ASSERT_TRUE(local_state); + local_state->Set(prefs::kManagedSerialAllowUsbDevicesForUrls, ParseJson(R"( + [ + { + "devices": [{ "vendor_id": 6353, "product_id": 5678 }], + "urls": ["https://chromium.org"] + }, { + "devices": [{ "vendor_id": 6353 }], + "urls": ["https://android.com"] + }, { + "devices": [{ "vendor_id": 6354 }], + "urls": ["https://android.com"] + } + ])")); + local_state->Set(prefs::kManagedSerialAllowAllPortsForUrls, + ParseJson(R"([ "https://google.com" ])")); + } + + void SetUpOffTheRecordChooserContext() override { + CreateIncognitoProfile(); + mojo::PendingRemote<device::mojom::SerialPortManager> serial_port_manager; + serial_port_manager_.AddReceiver( + serial_port_manager.InitWithNewPipeAndPassReceiver()); + SerialChooserContext* serial_chooser_context = + SerialChooserContextFactory::GetForProfile(incognito_profile()); + serial_chooser_context->SetPortManagerForTesting( + std::move(serial_port_manager)); + base::RunLoop().RunUntilIdle(); + GetChooserContext(incognito_profile())->AddObserver(&observer_); + } + + void AddPersistentDevice() override { + persistent_port_ = device::mojom::SerialPortInfo::New(); + persistent_port_->token = base::UnguessableToken::Create(); + persistent_port_->display_name = "persistent-device"; +#if BUILDFLAG(IS_WIN) + persistent_port_->device_instance_id = "1"; +#else + persistent_port_->has_vendor_id = true; + persistent_port_->vendor_id = 6353; + persistent_port_->has_product_id = true; + persistent_port_->product_id = 5678; + persistent_port_->serial_number = "123ABC"; +#if BUILDFLAG(IS_MAC) + persistent_port_->usb_driver_name = "AppleUSBCDC"; +#endif +#endif // BUILDFLAG(IS_WIN) + serial_port_manager_.AddPort(persistent_port_.Clone()); + } + + void AddEphemeralDevice() override { + ephemeral_port_ = device::mojom::SerialPortInfo::New(); + ephemeral_port_->token = base::UnguessableToken::Create(); + ephemeral_port_->display_name = "ephemeral-device"; +#if BUILDFLAG(IS_WIN) + ephemeral_port_->device_instance_id = "2"; +#else + ephemeral_port_->has_vendor_id = true; + ephemeral_port_->vendor_id = 6354; + ephemeral_port_->has_product_id = true; + ephemeral_port_->product_id = 0; +#if BUILDFLAG(IS_MAC) + ephemeral_port_->usb_driver_name = "AppleUSBCDC"; +#endif +#endif // BUILDFLAG(IS_WIN) + serial_port_manager_.AddPort(ephemeral_port_.Clone()); + } + + void AddUserGrantedDevice() override { + user_granted_port_ = device::mojom::SerialPortInfo::New(); + user_granted_port_->token = base::UnguessableToken::Create(); + user_granted_port_->display_name = "user-granted-device"; +#if BUILDFLAG(IS_WIN) + user_granted_port_->device_instance_id = "3"; +#else + user_granted_port_->has_vendor_id = true; + user_granted_port_->vendor_id = 6355; + user_granted_port_->has_product_id = true; + user_granted_port_->product_id = 0; + user_granted_port_->serial_number = "789XYZ"; +#if BUILDFLAG(IS_MAC) + user_granted_port_->usb_driver_name = "AppleUSBCDC"; +#endif +#endif // BUILDFLAG(IS_WIN) + serial_port_manager_.AddPort(user_granted_port_.Clone()); + } + + void AddOffTheRecordDevice() override { + off_the_record_port_ = device::mojom::SerialPortInfo::New(); + off_the_record_port_->token = base::UnguessableToken::Create(); + off_the_record_port_->display_name = "off-the-record-device"; +#if BUILDFLAG(IS_WIN) + off_the_record_port_->device_instance_id = "4"; +#else + off_the_record_port_->has_vendor_id = true; + off_the_record_port_->vendor_id = 6353; + off_the_record_port_->has_product_id = true; + off_the_record_port_->product_id = 8765; + off_the_record_port_->serial_number = "A9B8C7"; +#if BUILDFLAG(IS_MAC) + off_the_record_port_->usb_driver_name = "AppleUSBCDC"; +#endif +#endif // BUILDFLAG(IS_WIN) + serial_port_manager_.AddPort(off_the_record_port_.Clone()); + } + + void SetUpUserGrantedPermissions() override { + const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); + const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const auto kWebUIOrigin = url::Origin::Create(kWebUIUrl); + + // Add the user granted permissions for testing. + // These two persistent device permissions should be lumped together + // with the policy permissions, since they apply to the same device and + // URL. + { + base::RunLoop loop; + auto barrier_closure = base::BarrierClosure(5, loop.QuitClosure()); + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::SERIAL_GUARD}, + ContentSettingsType::SERIAL_CHOOSER_DATA)) + .Times(5) + .WillRepeatedly(RunClosure(barrier_closure)); + auto* serial_chooser_context = + SerialChooserContextFactory::GetForProfile(profile()); + serial_chooser_context->GrantPortPermission(kChromiumOrigin, + *persistent_port_); + serial_chooser_context->GrantPortPermission(kGoogleOrigin, + *persistent_port_); + serial_chooser_context->GrantPortPermission(kWebUIOrigin, + *persistent_port_); + serial_chooser_context->GrantPortPermission(kAndroidOrigin, + *ephemeral_port_); + serial_chooser_context->GrantPortPermission(kAndroidOrigin, + *user_granted_port_); + loop.Run(); + } + + if (off_the_record_port_) { + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::SERIAL_GUARD}, + ContentSettingsType::SERIAL_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + SerialChooserContextFactory::GetForProfile(incognito_profile()) + ->GrantPortPermission(kChromiumOrigin, *off_the_record_port_); + loop.Run(); + } + } + + void SetUpUserGrantedPermissionForOrigin(const url::Origin& origin) override { + auto* serial_chooser_context = + SerialChooserContextFactory::GetForProfile(profile()); + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::SERIAL_GUARD}, + ContentSettingsType::SERIAL_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + serial_chooser_context->GrantPortPermission(origin, *user_granted_port_); + loop.Run(); + } + + base::Value GetPersistentDeviceValueForOrigin( + const url::Origin& origin) override { + return SerialChooserContext::PortInfoToValue(*persistent_port_); + } + + base::Value GetUserGrantedDeviceValueForOrigin( + const url::Origin& origin) override { + return SerialChooserContext::PortInfoToValue(*user_granted_port_); + } + + std::string GetAllDevicesDisplayName() override { return "Any serial port"; } + + std::string GetDevicesFromGoogleDisplayName() override { + return "USB devices from Google Inc."; + } + + std::string GetDevicesFromVendor18D2DisplayName() override { + return "USB devices from vendor 18D2"; + } + + std::string GetUnknownProductDisplayName() override { + return "USB device from Google Inc. (product 162E)"; + } + + permissions::ObjectPermissionContextBase* GetChooserContext( + Profile* profile) override { + return SerialChooserContextFactory::GetForProfile(profile); + } + + ContentSettingsType content_type() override { + return ContentSettingsType::SERIAL_CHOOSER_DATA; + } + + ContentSettingsType guard_type() override { + return ContentSettingsType::SERIAL_GUARD; + } + + device::FakeSerialPortManager serial_port_manager_; + device::mojom::SerialPortInfoPtr ephemeral_port_; + device::mojom::SerialPortInfoPtr off_the_record_port_; + device::mojom::SerialPortInfoPtr persistent_port_; + device::mojom::SerialPortInfoPtr user_granted_port_; +}; + +TEST_F(SiteSettingsHandlerSerialTest, HandleGetChooserExceptionList) { + TestHandleGetChooserExceptionList(); +} + +TEST_F(SiteSettingsHandlerSerialTest, + HandleGetChooserExceptionListForOffTheRecord) { + TestHandleGetChooserExceptionListForOffTheRecord(); +} + +TEST_F(SiteSettingsHandlerSerialTest, HandleResetChooserExceptionForSite) { + TestHandleResetChooserExceptionForSite(); +} + +TEST_F(SiteSettingsHandlerSerialTest, HandleSetOriginPermissions) { + TestHandleSetOriginPermissions(); +} + +TEST_F(SiteSettingsHandlerSerialTest, HandleSetOriginPermissionsPolicyOnly) { + TestHandleSetOriginPermissionsPolicyOnly(); +} +#endif // !BUILDFLAG(IS_ANDROID) + +class SiteSettingsHandlerUsbTest + : public SiteSettingsHandlerChooserExceptionTest { + protected: + void SetUpChooserContext() override { + mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager; + usb_device_manager_.AddReceiver( + device_manager.InitWithNewPipeAndPassReceiver()); + UsbChooserContext* usb_chooser_context = + UsbChooserContextFactory::GetForProfile(profile()); + usb_chooser_context->SetDeviceManagerForTesting(std::move(device_manager)); + TestFuture<std::vector<device::mojom::UsbDeviceInfoPtr>> get_devices_future; + usb_chooser_context->GetDevices(get_devices_future.GetCallback()); + EXPECT_TRUE(get_devices_future.Wait()); + } + + void SetUpPolicyGrantedPermissions() override { + profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls, + ParseJson(R"( + [ + { + "devices": [{ "vendor_id": 6353, "product_id": 5678 }], + "urls": ["https://chromium.org"] + }, { + "devices": [{ "vendor_id": 6353 }], + "urls": ["https://google.com,https://android.com"] + }, { + "devices": [{ "vendor_id": 6354 }], + "urls": ["https://android.com,"] + }, { + "devices": [{}], + "urls": ["https://google.com,https://google.com"] + } + ])")); + } + + void SetUpOffTheRecordChooserContext() override { + CreateIncognitoProfile(); + mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager; + usb_device_manager_.AddReceiver( + device_manager.InitWithNewPipeAndPassReceiver()); + UsbChooserContext* usb_chooser_context = + UsbChooserContextFactory::GetForProfile(incognito_profile()); + usb_chooser_context->SetDeviceManagerForTesting(std::move(device_manager)); + TestFuture<std::vector<device::mojom::UsbDeviceInfoPtr>> get_devices_future; + usb_chooser_context->GetDevices(get_devices_future.GetCallback()); + EXPECT_TRUE(get_devices_future.Wait()); + GetChooserContext(incognito_profile())->AddObserver(&observer_); + } + + void AddPersistentDevice() override { + persistent_device_ = usb_device_manager_.CreateAndAddDevice( + /*vendor_id=*/6353, /*product_id=*/5678, + /*manufacturer_string=*/"Google", + /*product_string=*/"persistent-device", /*serial_number=*/"123ABC"); + } + + void AddEphemeralDevice() override { + ephemeral_device_ = usb_device_manager_.CreateAndAddDevice( + /*vendor_id=*/6354, /*product_id=*/0, + /*manufacturer_string=*/"Google", + /*product_string=*/"ephemeral-device", /*serial_number=*/""); + } + + void AddUserGrantedDevice() override { + user_granted_device_ = usb_device_manager_.CreateAndAddDevice( + /*vendor_id=*/6355, /*product_id=*/0, + /*manufacturer_string=*/"Google", + /*product_string=*/"user-granted-device", + /*serial_number=*/"789XYZ"); + } + + void AddOffTheRecordDevice() override { + off_the_record_device_ = usb_device_manager_.CreateAndAddDevice( + /*vendor_id=*/6353, /*product_id=*/8765, + /*manufacturer_string=*/"Google", + /*product_string=*/"off-the-record-device", + /*serial_number=*/"A9B8C7"); + } + + void SetUpUserGrantedPermissions() override { + const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl); + const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl); + const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl); + const auto kWebUIOrigin = url::Origin::Create(kWebUIUrl); + + // Add the user granted permissions for testing. + // These two persistent device permissions should be lumped together + // with the policy permissions, since they apply to the same device and + // URL. + { + base::RunLoop loop; + auto barrier_closure = base::BarrierClosure(5, loop.QuitClosure()); + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::USB_GUARD}, + ContentSettingsType::USB_CHOOSER_DATA)) + .Times(5) + .WillRepeatedly(RunClosure(barrier_closure)); + auto* usb_chooser_context = + UsbChooserContextFactory::GetForProfile(profile()); + usb_chooser_context->GrantDevicePermission(kChromiumOrigin, + *persistent_device_); + usb_chooser_context->GrantDevicePermission(kGoogleOrigin, + *persistent_device_); + usb_chooser_context->GrantDevicePermission(kWebUIOrigin, + *persistent_device_); + usb_chooser_context->GrantDevicePermission(kAndroidOrigin, + *ephemeral_device_); + usb_chooser_context->GrantDevicePermission(kAndroidOrigin, + *user_granted_device_); + loop.Run(); + } + + if (off_the_record_device_) { + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::USB_GUARD}, + ContentSettingsType::USB_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + UsbChooserContextFactory::GetForProfile(incognito_profile()) + ->GrantDevicePermission(kChromiumOrigin, *off_the_record_device_); + loop.Run(); + } + } + + void SetUpUserGrantedPermissionForOrigin(const url::Origin& origin) override { + auto* usb_chooser_context = + UsbChooserContextFactory::GetForProfile(profile()); + base::RunLoop loop; + EXPECT_CALL(observer_, OnObjectPermissionChanged( + {ContentSettingsType::USB_GUARD}, + ContentSettingsType::USB_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + usb_chooser_context->GrantDevicePermission(origin, *user_granted_device_); + loop.Run(); + } + + base::Value GetPersistentDeviceValueForOrigin( + const url::Origin& origin) override { + return UsbChooserContext::DeviceInfoToValue(*persistent_device_); + } + + base::Value GetUserGrantedDeviceValueForOrigin( + const url::Origin& origin) override { + return UsbChooserContext::DeviceInfoToValue(*user_granted_device_); + } + + std::string GetAllDevicesDisplayName() override { + return "Devices from any vendor"; + } + + std::string GetDevicesFromGoogleDisplayName() override { + return "Devices from Google Inc."; + } + + std::string GetDevicesFromVendor18D2DisplayName() override { + return "Devices from vendor 0x18D2"; + } + + std::string GetUnknownProductDisplayName() override { + return "Unknown product 0x162E from Google Inc."; + } + + permissions::ObjectPermissionContextBase* GetChooserContext( + Profile* profile) override { + return UsbChooserContextFactory::GetForProfile(profile); + } + + ContentSettingsType content_type() override { + return ContentSettingsType::USB_CHOOSER_DATA; + } + + ContentSettingsType guard_type() override { + return ContentSettingsType::USB_GUARD; + } + + device::FakeUsbDeviceManager usb_device_manager_; + device::mojom::UsbDeviceInfoPtr ephemeral_device_; + device::mojom::UsbDeviceInfoPtr off_the_record_device_; + device::mojom::UsbDeviceInfoPtr persistent_device_; + device::mojom::UsbDeviceInfoPtr user_granted_device_; +}; + +TEST_F(SiteSettingsHandlerUsbTest, HandleGetChooserExceptionList) { + TestHandleGetChooserExceptionList(); +} + +TEST_F(SiteSettingsHandlerUsbTest, + HandleGetChooserExceptionListForOffTheRecord) { + TestHandleGetChooserExceptionListForOffTheRecord(); +} + +TEST_F(SiteSettingsHandlerUsbTest, HandleResetChooserExceptionForSite) { + TestHandleResetChooserExceptionForSite(); +} + +TEST_F(SiteSettingsHandlerUsbTest, HandleSetOriginPermissions) { + TestHandleSetOriginPermissions(); +} + +TEST_F(SiteSettingsHandlerUsbTest, HandleSetOriginPermissionsPolicyOnly) { + TestHandleSetOriginPermissionsPolicyOnly(); } TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) {
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc index 7bbe01e..3ec3e14 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -907,7 +907,7 @@ } } -const ChooserTypeNameEntry* ChooserTypeFromGroupName(const std::string& name) { +const ChooserTypeNameEntry* ChooserTypeFromGroupName(base::StringPiece name) { for (const auto& chooser_type : kChooserTypeGroupNames) { if (chooser_type.name == name) return &chooser_type;
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.h b/chrome/browser/ui/webui/settings/site_settings_helper.h index f28fb01..0e9e64c2e 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper.h +++ b/chrome/browser/ui/webui/settings/site_settings_helper.h
@@ -188,7 +188,7 @@ const char* name; }; -const ChooserTypeNameEntry* ChooserTypeFromGroupName(const std::string& name); +const ChooserTypeNameEntry* ChooserTypeFromGroupName(base::StringPiece name); // Creates a chooser exception object for the object with |display_name|. The // object contains the following properties
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc index ecaaa8a7..f9ea66c 100644 --- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.cc
@@ -4,7 +4,12 @@ #include "chrome/browser/ui/webui/settings/site_settings_permissions_handler.h" +#include "base/check.h" +#include "base/metrics/histogram_functions.h" #include "base/threading/thread_checker.h" +#include "base/time/clock.h" +#include "base/time/default_clock.h" +#include "base/time/time.h" #include "base/values.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/permissions/unused_site_permissions_service_factory.h" @@ -14,14 +19,24 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/features.h" +#include "components/permissions/constants.h" #include "components/permissions/unused_site_permissions_service.h" #include "url/gurl.h" #include "url/origin.h" -constexpr char kRevokedPermissionsKey[] = "revoked"; +namespace { +// Reflects the maximum number of days between a permissions being revoked and +// the time when the user regrants the permission through the unused site +// permission module of Safete Check. The maximum number of days is determined +// by `kRevocationCleanUpThreshold`. +size_t kAllowAgainMetricsExclusiveMaxCount = 31; +// Using a single bucket per day, following the value of +// |kAllowAgainMetricsExclusiveMaxCount|. +size_t kAllowAgainMetricsBuckets = 31; +} // namespace SiteSettingsPermissionsHandler::SiteSettingsPermissionsHandler(Profile* profile) - : profile_(profile) {} + : profile_(profile), clock_(base::DefaultClock::GetInstance()) {} SiteSettingsPermissionsHandler::~SiteSettingsPermissionsHandler() = default; void SiteSettingsPermissionsHandler::HandleGetRevokedUnusedSitePermissionsList( @@ -45,8 +60,21 @@ UnusedSitePermissionsServiceFactory::GetForProfile(profile_); url::Origin origin = url::Origin::Create(GURL(origin_str)); - service->RegrantPermissionsForOrigin(origin); + HostContentSettingsMap* hcsm = + HostContentSettingsMapFactory::GetForProfile(profile_); + content_settings::SettingInfo info; + base::Value stored_value(hcsm->GetWebsiteSetting( + origin.GetURL(), origin.GetURL(), + ContentSettingsType::REVOKED_UNUSED_SITE_PERMISSIONS, &info)); + base::Time revoked_time = + info.metadata.expiration - permissions::kRevocationCleanUpThreshold; + base::UmaHistogramCustomCounts( + "Settings.SafetyCheck.UnusedSitePermissionsAllowAgainDays", + (clock_->Now() - revoked_time).InDays(), 0, + kAllowAgainMetricsExclusiveMaxCount, kAllowAgainMetricsBuckets); + + service->RegrantPermissionsForOrigin(origin); SendUnusedSitePermissionsReviewList(); } @@ -83,10 +111,10 @@ DCHECK(stored_value.is_dict()); // The revoked permissions list should be reachable by given key. - DCHECK(stored_value.GetDict().FindList(kRevokedPermissionsKey)); + DCHECK(stored_value.GetDict().FindList(permissions::kRevokedKey)); auto type_list = - stored_value.GetDict().FindList(kRevokedPermissionsKey)->Clone(); + stored_value.GetDict().FindList(permissions::kRevokedKey)->Clone(); base::Value::List permissions_value_list; for (base::Value& type : type_list) { permissions_value_list.Append( @@ -132,6 +160,10 @@ PopulateUnusedSitePermissionsData()); } +void SiteSettingsPermissionsHandler::SetClockForTesting(base::Clock* clock) { + clock_ = clock; +} + void SiteSettingsPermissionsHandler::OnJavascriptAllowed() {} void SiteSettingsPermissionsHandler::OnJavascriptDisallowed() {}
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h index c61d0c8..05fa225 100644 --- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_SITE_SETTINGS_PERMISSIONS_HANDLER_H_ #include "base/memory/raw_ptr.h" +#include "base/time/clock.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" @@ -57,6 +58,10 @@ void SendUnusedSitePermissionsReviewList(); const raw_ptr<Profile> profile_; + + base::Clock* clock_; + + void SetClockForTesting(base::Clock* clock); }; #endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SITE_SETTINGS_PERMISSIONS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc index 741bd3d4..60942e0 100644 --- a/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_permissions_handler_unittest.cc
@@ -6,8 +6,10 @@ #include <memory> #include "base/memory/scoped_refptr.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" #include "base/time/clock.h" +#include "base/time/time.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/ui/webui/settings/site_settings_helper.h" @@ -18,13 +20,14 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/features.h" +#include "components/permissions/constants.h" +#include "components/permissions/unused_site_permissions_service.h" #include "content/public/browser/storage_partition.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -constexpr char kRevokedKey[] = "revoked"; constexpr char kUnusedTestSite[] = "https://example1.com"; constexpr char kUsedTestSite[] = "https://example2.com"; @@ -60,12 +63,16 @@ base::Value::List permission_type_list = base::Value::List(); permission_type_list.Append( static_cast<int32_t>(ContentSettingsType::GEOLOCATION)); - dict.Set(kRevokedKey, base::Value::List(std::move(permission_type_list))); + dict.Set(permissions::kRevokedKey, + base::Value::List(std::move(permission_type_list))); + const content_settings::ContentSettingConstraints constraint{ + .expiration = + clock()->Now() + permissions::kRevocationCleanUpThreshold}; hcsm()->SetWebsiteSettingDefaultScope( GURL(kUnusedTestSite), GURL(kUnusedTestSite), ContentSettingsType::REVOKED_UNUSED_SITE_PERMISSIONS, - base::Value(dict.Clone())); + base::Value(dict.Clone()), constraint); // There should be only an unused URL in the revoked permissions list. const auto& revoked_permissions = @@ -74,6 +81,7 @@ EXPECT_EQ( GURL(kUnusedTestSite), GURL(*revoked_permissions[0].FindStringKey(site_settings::kOrigin))); + handler()->SetClockForTesting(&clock_); } void TearDown() override { @@ -104,6 +112,7 @@ TEST_F(SiteSettingsPermissionsHandlerTest, PopulateUnusedSitePermissionsData) { // Add GEOLOCATION setting for url but do not add to revoked list. const content_settings::ContentSettingConstraints constraint{ + .expiration = clock()->Now() + permissions::kRevocationCleanUpThreshold, .track_last_visit_for_autoexpiration = true}; hcsm()->SetContentSettingDefaultScope( GURL(kUsedTestSite), GURL(kUsedTestSite), @@ -121,11 +130,23 @@ TEST_F(SiteSettingsPermissionsHandlerTest, HandleAllowPermissionsAgainForUnusedSite) { + // Advance 14 days; this will be the expected histogram sample. + clock()->Advance(base::Days(14)); + base::HistogramTester histogram_tester; + // Allow the revoked permission for the unused site again. base::Value::List args; args.Append(base::Value(kUnusedTestSite)); handler()->HandleAllowPermissionsAgainForUnusedSite(args); + // Only a single entry should be recorded in the histogram. + const std::vector<base::Bucket> buckets = histogram_tester.GetAllSamples( + "Settings.SafetyCheck.UnusedSitePermissionsAllowAgainDays"); + EXPECT_EQ(1U, buckets.size()); + // The recorded metric should be the elapsed days since the revocation. + histogram_tester.ExpectUniqueSample( + "Settings.SafetyCheck.UnusedSitePermissionsAllowAgainDays", 14, 1); + // Check there is no origin in revoked permissions list. ContentSettingsForOneType revoked_permissions_list; hcsm()->GetSettingsForOneType(
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc index c97aa4f..e5d58be0 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc +++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -39,6 +39,7 @@ #include "ui/base/ui_base_features.h" #include "ui/base/webui/web_ui_util.h" #include "ui/views/style/platform_style.h" +#include "ui/webui/color_change_listener/color_change_handler.h" BookmarksSidePanelUI::BookmarksSidePanelUI(content::WebUI* web_ui) : ui::MojoBubbleWebUIController(web_ui, true) { @@ -180,6 +181,13 @@ shopping_list_factory_receiver_.Bind(std::move(receiver)); } +void BookmarksSidePanelUI::BindInterface( + mojo::PendingReceiver<color_change_listener::mojom::PageHandler> + pending_receiver) { + color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( + web_ui()->GetWebContents(), std::move(pending_receiver)); +} + void BookmarksSidePanelUI::CreateBookmarksPageHandler( mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) { bookmarks_page_handler_ =
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h index e8c0655..0f08a31 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h +++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h
@@ -14,6 +14,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "ui/webui/mojo_bubble_web_ui_controller.h" +#include "ui/webui/resources/cr_components/color_change_listener/color_change_listener.mojom.h" class BookmarksPageHandler; @@ -21,6 +22,10 @@ class ShoppingListHandler; } +namespace ui { +class ColorChangeHandler; +} + class BookmarksSidePanelUI : public ui::MojoBubbleWebUIController, public side_panel::mojom::BookmarksPageHandlerFactory, @@ -41,6 +46,10 @@ mojo::PendingReceiver<shopping_list::mojom::ShoppingListHandlerFactory> receiver); + void BindInterface( + mojo::PendingReceiver<color_change_listener::mojom::PageHandler> + pending_receiver); + private: // side_panel::mojom::BookmarksPageHandlerFactory: void CreateBookmarksPageHandler( @@ -59,6 +68,7 @@ std::unique_ptr<commerce::ShoppingListHandler> shopping_list_handler_; mojo::Receiver<shopping_list::mojom::ShoppingListHandlerFactory> shopping_list_factory_receiver_{this}; + std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; WEB_UI_CONTROLLER_TYPE_DECL(); };
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom index cf5eda4..e721c33 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom
@@ -95,6 +95,12 @@ bool enabled; }; +enum CustomizeChromeSection { + kAppearance, + kShortcuts, + kModules, +}; + // Used by the WebUI page to bootstrap bidirectional communication. interface CustomizeChromePageHandlerFactory { // The WebUI calls this method when the page is first initialized. @@ -160,6 +166,9 @@ // Disables module with ID `module_id` if `disabled`. Enables otherwise. SetModuleDisabled(string module_id, bool disabled); + + // Triggers a call to |CustomizeChromePage.UpdateScrollToSection()|. + UpdateScrollToSection(); }; // WebUI-side handler for requests from the browser. @@ -172,4 +181,7 @@ SetMostVisitedSettings(bool custom_links_enabled, bool visible); // Sets the current theme. SetTheme(Theme theme); + // Scrolls side panel to |section|. Possibly a response to a call to + // |CustomizeChromePageHandler.UpdateScrollToSection()|. + ScrollToSection(CustomizeChromeSection section); };
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index 027548c..19c5a8412 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/search/ntp_user_data_types.h" #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_colors.h" +#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/common/pref_names.h" #include "chrome/common/themes/autogenerated_theme_util.h" #include "components/prefs/pref_service.h" @@ -109,6 +110,27 @@ } } +void CustomizeChromePageHandler::ScrollToSection( + CustomizeChromeSection section) { + last_requested_section_ = section; + side_panel::mojom::CustomizeChromeSection mojo_section; + switch (section) { + case CustomizeChromeSection::kUnspecified: + // Cannot scroll to unspecified section. + return; + case CustomizeChromeSection::kAppearance: + mojo_section = side_panel::mojom::CustomizeChromeSection::kAppearance; + break; + case CustomizeChromeSection::kShortcuts: + mojo_section = side_panel::mojom::CustomizeChromeSection::kShortcuts; + break; + case CustomizeChromeSection::kModules: + mojo_section = side_panel::mojom::CustomizeChromeSection::kModules; + break; + } + page_->ScrollToSection(mojo_section); +} + void CustomizeChromePageHandler::SetDefaultColor() { theme_service_->UseDefaultTheme(); } @@ -360,6 +382,10 @@ profile_->GetPrefs()->GetBoolean(prefs::kNtpModulesVisible)); } +void CustomizeChromePageHandler::UpdateScrollToSection() { + ScrollToSection(last_requested_section_); +} + void CustomizeChromePageHandler::LogEvent(NTPLoggingEventType event) { switch (event) { case NTP_CUSTOMIZE_SHORTCUT_TOGGLE_TYPE:
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h index 70ef4531..3fca722 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h
@@ -14,6 +14,7 @@ #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_observer.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" +#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/common/search/ntp_logging_events.h" #include "components/prefs/pref_change_registrar.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -51,6 +52,8 @@ ~CustomizeChromePageHandler() override; + void ScrollToSection(CustomizeChromeSection section); + // side_panel::mojom::CustomizeChromePageHandler: void SetDefaultColor() override; void SetSeedColor(SkColor seed_color) override; @@ -78,6 +81,7 @@ void SetModulesVisible(bool visible) override; void SetModuleDisabled(const std::string& module_id, bool disabled) override; void UpdateModulesSettings() override; + void UpdateScrollToSection() override; private: void LogEvent(NTPLoggingEventType event); @@ -120,6 +124,10 @@ base::TimeTicks background_images_request_start_time_; raw_ptr<ThemeService> theme_service_; const std::vector<std::pair<const std::string, int>> module_id_names_; + // Caches a request to scroll to a section in case the front-end queries the + // last requested section, e.g. during load. + CustomizeChromeSection last_requested_section_ = + CustomizeChromeSection::kUnspecified; PrefChangeRegistrar pref_change_registrar_; base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index 27e39fe0..a0165fc 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_colors.h" +#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/common/pref_names.h" #include "chrome/common/themes/autogenerated_theme_util.h" #include "chrome/grit/generated_resources.h" @@ -156,6 +157,8 @@ MOCK_METHOD2(SetMostVisitedSettings, void(bool custom_links_enabled, bool visible)); MOCK_METHOD1(SetTheme, void(side_panel::mojom::ThemePtr)); + MOCK_METHOD1(ScrollToSection, + void(side_panel::mojom::CustomizeChromeSection)); mojo::Receiver<side_panel::mojom::CustomizeChromePage> receiver_{this}; }; @@ -715,6 +718,38 @@ handler().SetDailyRefreshCollectionId("test_id"); } +TEST_F(CustomizeChromePageHandlerTest, ScrollToSection) { + side_panel::mojom::CustomizeChromeSection section; + EXPECT_CALL(mock_page_, ScrollToSection) + .Times(1) + .WillOnce(testing::SaveArg<0>(§ion)); + + handler().ScrollToSection(CustomizeChromeSection::kAppearance); + mock_page_.FlushForTesting(); + + EXPECT_EQ(side_panel::mojom::CustomizeChromeSection::kAppearance, section); +} + +TEST_F(CustomizeChromePageHandlerTest, ScrollToUnspecifiedSection) { + EXPECT_CALL(mock_page_, ScrollToSection).Times(0); + + handler().ScrollToSection(CustomizeChromeSection::kUnspecified); + mock_page_.FlushForTesting(); +} + +TEST_F(CustomizeChromePageHandlerTest, UpdateScrollToSection) { + side_panel::mojom::CustomizeChromeSection section; + EXPECT_CALL(mock_page_, ScrollToSection) + .Times(2) + .WillRepeatedly(testing::SaveArg<0>(§ion)); + + handler().ScrollToSection(CustomizeChromeSection::kAppearance); + handler().UpdateScrollToSection(); + mock_page_.FlushForTesting(); + + EXPECT_EQ(side_panel::mojom::CustomizeChromeSection::kAppearance, section); +} + class CustomizeChromePageHandlerWithModulesTest : public CustomizeChromePageHandlerTest { public:
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc index 2af7059..26004e7 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" #include "chrome/browser/ui/webui/sanitized_image_source.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h" +#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" @@ -24,6 +25,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/webui/web_ui_util.h" CustomizeChromeUI::CustomizeChromeUI(content::WebUI* web_ui) @@ -96,6 +98,18 @@ CustomizeChromeUI::~CustomizeChromeUI() = default; +void CustomizeChromeUI::ScrollToSection(CustomizeChromeSection section) { + if (customize_chrome_page_handler_) { + customize_chrome_page_handler_->ScrollToSection(section); + } else { + section_ = section; + } +} + +base::WeakPtr<CustomizeChromeUI> CustomizeChromeUI::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + WEB_UI_CONTROLLER_TYPE_IMPL(CustomizeChromeUI) void CustomizeChromeUI::BindInterface( @@ -123,4 +137,8 @@ std::move(pending_page_handler), std::move(pending_page), NtpCustomBackgroundServiceFactory::GetForProfile(profile_), web_contents_, module_id_names_); + if (section_.has_value()) { + customize_chrome_page_handler_->ScrollToSection(*section_); + section_.reset(); + } }
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h index 16a781d..e8178dbb 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h
@@ -7,12 +7,15 @@ #include <memory> +#include "base/memory/weak_ptr.h" #include "chrome/browser/cart/chrome_cart.mojom.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" +#include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "content/public/browser/web_ui_controller.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 "third_party/abseil-cpp/absl/types/optional.h" #include "ui/webui/mojo_bubble_web_ui_controller.h" namespace content { @@ -34,6 +37,11 @@ ~CustomizeChromeUI() override; + void ScrollToSection(CustomizeChromeSection section); + + // Gets a weak pointer to this object. + base::WeakPtr<CustomizeChromeUI> GetWeakPtr(); + // Instantiates the implementor of the // mojom::CustomizeChromePageHandler mojo interface passing the pending // receiver that will be internally bound. @@ -60,6 +68,11 @@ const std::vector<std::pair<const std::string, int>> module_id_names_; mojo::Receiver<side_panel::mojom::CustomizeChromePageHandlerFactory> page_factory_receiver_; + // Caches a request to scroll to a section in case the request happens before + // the front-end is ready to receive the request. + absl::optional<CustomizeChromeSection> section_; + + base::WeakPtrFactory<CustomizeChromeUI> weak_ptr_factory_{this}; WEB_UI_CONTROLLER_TYPE_DECL(); };
diff --git a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc index a4d9890..a89d0e5 100644 --- a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc +++ b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/signin_promo.h" -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/webui/ash/edu_coexistence/edu_coexistence_login_handler.h" #include "chrome/common/pref_names.h" @@ -28,6 +27,7 @@ #include "components/account_manager_core/mock_account_manager_facade.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_type.h" #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.cc b/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.cc index 2561326..02c31cc 100644 --- a/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.cc +++ b/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.cc
@@ -10,8 +10,8 @@ #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "base/values.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/policy_switches.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -110,7 +110,9 @@ DCHECK(callback); DCHECK(!callback_) << "A request is already in progress"; callback_ = std::move(callback); - if (policy::BrowserPolicyConnector::IsNonEnterpriseUser(email_)) { + if (signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + email_) == signin::AccountManagedStatusFinder::EmailEnterpriseStatus:: + kKnownNonEnterprise) { // Non Enterprise accounts do not have restrictions. std::move(callback_).Run(/*status=*/Status::kUnsupportedAccountTypeError, /*policy=*/absl::nullopt,
diff --git a/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.h b/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.h index 95903c5..56aaf37 100644 --- a/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.h +++ b/chrome/browser/ui/webui/signin/ash/user_cloud_signin_restriction_policy_fetcher.h
@@ -92,7 +92,7 @@ // (abc1234@gmail.com). It's used to skip API requests for domains such as // gmail.com and others since these type of users are known to be // non-enterprise. For more information check - // policy::BrowserPolicyConnector::IsNonEnterpriseUser. + // signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail. UserCloudSigninRestrictionPolicyFetcher( const std::string& email, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc index df30d39..eeae88a 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
@@ -307,9 +307,7 @@ } return l10n_util::GetStringUTF8( - base::FeatureList::IsEnabled(kSigninInterceptBubbleV2) - ? IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL_V2 - : IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL); + IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL); } std::string DiceWebSigninInterceptHandler::GetCancelButtonLabel() {
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler_unittest.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler_unittest.cc index c2cf70c..cf29c35b 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler_unittest.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler_unittest.cc
@@ -91,7 +91,7 @@ IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC_V2), /*confirm_button_label=*/ l10n_util::GetStringUTF8( - IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL_V2), + IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL), /*cancel_button_label=*/ l10n_util::GetStringUTF8( IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_CANCEL_BUTTON_LABEL),
diff --git a/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc index 4f6477d..e96f364 100644 --- a/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc +++ b/chrome/browser/ui/webui/signin/turn_sync_on_helper.cc
@@ -40,11 +40,11 @@ #include "chrome/browser/unified_consent/unified_consent_service_factory.h" #include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h" #include "components/keyed_service/core/keyed_service_shutdown_notifier.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/management/management_service.h" #include "components/prefs/pref_service.h" #include "components/signin/public/base/signin_metrics.h" #include "components/signin/public/base/signin_pref_names.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" #include "components/signin/public/identity_manager/accounts_mutator.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" @@ -544,8 +544,9 @@ // for cloud policies because local policies are instantly available. See // http://crbug.com/812546 bool may_have_cloud_policies = - !policy::BrowserPolicyConnector::IsNonEnterpriseUser( - account_info_.email) || + signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_info_.email) == signin::AccountManagedStatusFinder:: + EmailEnterpriseStatus::kUnknown || policy::ManagementServiceFactory::GetForProfile(profile_) ->HasManagementAuthority( policy::EnterpriseManagementAuthority::CLOUD) || @@ -652,8 +653,9 @@ const bool is_managed_account = account_info_.IsValid() ? account_info_.IsManaged() - : !policy::BrowserPolicyConnector::IsNonEnterpriseUser( - account_info_.email); + : signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + account_info_.email) == signin::AccountManagedStatusFinder:: + EmailEnterpriseStatus::kUnknown; delegate_->ShowSyncDisabledConfirmation( is_managed_account, base::BindOnce(&TurnSyncOnHelper::FinishSyncSetupAndDelete,
diff --git a/chrome/browser/ui/webui/webapks/OWNERS b/chrome/browser/ui/webui/webapks/OWNERS index 3fa3f22..3f3a939 100644 --- a/chrome/browser/ui/webui/webapks/OWNERS +++ b/chrome/browser/ui/webui/webapks/OWNERS
@@ -1 +1 @@ -file://components/webapk/OWNERS +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc index 113e20d9..532c5e9 100644 --- a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc +++ b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
@@ -11,6 +11,8 @@ #include "base/build_time.h" #include "base/check_op.h" #include "base/command_line.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/no_destructor.h" @@ -26,7 +28,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/buildflags.h" #include "chrome/browser/google/google_brand.h" -#include "chrome/browser/obsolete_system/obsolete_system.h" #include "chrome/browser/upgrade_detector/build_state.h" #include "chrome/browser/upgrade_detector/get_installed_version.h" #include "chrome/common/chrome_switches.h" @@ -204,13 +205,6 @@ if (!base::FeatureList::IsEnabled(kOutdatedBuildDetector)) return; - // Don't detect outdated builds for obsolete operating systems when new builds - // are no longer available. - if (ObsoleteSystem::IsObsoleteNowOrSoon() && - ObsoleteSystem::IsEndOfTheLine()) { - return; - } - // Don't show the bubble if we have a brand code that is NOT organic, unless // an outdated build is being simulated by command line switches. if (!simulating_outdated_) { @@ -258,7 +252,13 @@ if (network_time.is_null() || build_date_.is_null() || build_date_ > network_time) { - NOTREACHED(); + // TODO(crbug.com/1407664): Figure out why this is failing and either fix it + // and turn the conditional above into a CHECK or document how this can fail + // in the wild and either keep the DumpWithoutCrashing() or remove it. + base::Time build_date = build_date_; + base::debug::Alias(&network_time); + base::debug::Alias(&build_date); + base::debug::DumpWithoutCrashing(); return; }
diff --git a/chrome/browser/util/BUILD.gn b/chrome/browser/util/BUILD.gn index 0e2ec6a4..4d9ba47 100644 --- a/chrome/browser/util/BUILD.gn +++ b/chrome/browser/util/BUILD.gn
@@ -8,6 +8,7 @@ sources = [ "android/java/src/org/chromium/chrome/browser/util/AfterStartupTaskUtils.java", "android/java/src/org/chromium/chrome/browser/util/AndroidTaskUtils.java", + "android/java/src/org/chromium/chrome/browser/util/BrowserUiUtils.java", "android/java/src/org/chromium/chrome/browser/util/ChromeAccessibilityUtil.java", "android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java", "android/java/src/org/chromium/chrome/browser/util/FileSizeUtil.java",
diff --git a/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/BrowserUiUtils.java b/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/BrowserUiUtils.java new file mode 100644 index 0000000..75c7a2c --- /dev/null +++ b/chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/BrowserUiUtils.java
@@ -0,0 +1,78 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.util; + +import androidx.annotation.IntDef; + +import org.chromium.base.metrics.RecordHistogram; + +/** + * Deals with multiple parts of browser UI code calls. + */ +public class BrowserUiUtils { + /** + * ModuleTypeOnStartAndNTP defined in tools/metrics/histograms/enums.xml. + * + * Do not reorder or remove items, only add new items before NUM_ENTRIES. + */ + @IntDef({ModuleTypeOnStartAndNTP.MOST_VISITED_TILES, ModuleTypeOnStartAndNTP.OMNIBOX, + ModuleTypeOnStartAndNTP.SINGLE_TAB_CARD, ModuleTypeOnStartAndNTP.FEED, + ModuleTypeOnStartAndNTP.TAB_SWITCHER_BUTTON, ModuleTypeOnStartAndNTP.NUM_ENTRIES}) + public @interface ModuleTypeOnStartAndNTP { + int MOST_VISITED_TILES = 0; + int OMNIBOX = 1; + int SINGLE_TAB_CARD = 2; + int FEED = 3; + int TAB_SWITCHER_BUTTON = 4; + + // Be sure to also update enums.xml when updating these values. + int NUM_ENTRIES = 5; + } + + /** + * Do not reorder or remove items, only add new items before NUM_ENTRIES. + */ + @IntDef({HostSurface.NOT_SET, HostSurface.NEW_TAB_PAGE, HostSurface.START_SURFACE, + HostSurface.NUM_ENTRIES}) + public @interface HostSurface { + int NOT_SET = 0; + int NEW_TAB_PAGE = 1; + int START_SURFACE = 2; + + // Be sure to also update enums.xml when updating these values. + int NUM_ENTRIES = 3; + } + + /** + * Returns the host name for histograms. + * @param hostSurface The corresponding item of the host name in {@link HostSurface}. + * @return The host name used for the histograms like the "NewTabPage" in + * "NewTabPage.Module.Click" and "StartSurface" in "StartSurface.Module.Click". + */ + public static String getHostName(int hostSurface) { + switch (hostSurface) { + case HostSurface.NEW_TAB_PAGE: + return "NewTabPage"; + case HostSurface.START_SURFACE: + return "StartSurface"; + case HostSurface.NOT_SET: + return ""; + default: + throw new AssertionError("The host surface item provided here is wrong."); + } + } + + /** + * Records user clicking on different modules in New tab page or Start surface. + * @param hostSurface The corresponding item of the host name in {@link HostSurface} + * which indicates the page where the recording action happened. + * @param sample Sample to be recorded in the enumerated histogram. + */ + public static void recordModuleClickHistogram( + @HostSurface int hostSurface, @ModuleTypeOnStartAndNTP int sample) { + RecordHistogram.recordEnumeratedHistogram(getHostName(hostSurface) + ".Module.Click", + sample, ModuleTypeOnStartAndNTP.NUM_ENTRIES); + } +}
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc index ea29fc2..58b2513 100644 --- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc +++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.cc
@@ -11,9 +11,11 @@ #include "base/check.h" #include "base/containers/flat_set.h" +#include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" +#include "base/functional/overloaded.h" #include "base/memory/ptr_util.h" #include "base/sequence_checker.h" #include "base/strings/strcat.h" @@ -22,6 +24,10 @@ #include "base/types/expected.h" #include "base/values.h" #include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_trust_checker.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_validator.h" #include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h" #include "chrome/browser/web_applications/isolation_data.h" #include "chrome/browser/web_applications/locks/app_lock.h" @@ -34,12 +40,15 @@ #include "chrome/browser/web_applications/web_app_install_utils.h" #include "chrome/browser/web_applications/web_app_url_loader.h" #include "chrome/browser/web_applications/web_app_utils.h" +#include "components/prefs/pref_service.h" +#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/webapps/browser/install_result_code.h" #include "components/webapps/browser/installable/installable_logging.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/manifest/manifest_util.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" #include "url/gurl.h" @@ -63,6 +72,20 @@ return dest; } +std::unique_ptr<IsolatedWebAppResponseReaderFactory> +CreateDefaultResponseReaderFactory(content::BrowserContext& browser_context) { + Profile& profile = *Profile::FromBrowserContext(&browser_context); + PrefService& pref_service = *profile.GetPrefs(); + + auto trust_checker = + std::make_unique<IsolatedWebAppTrustChecker>(pref_service); + auto validator = + std::make_unique<IsolatedWebAppValidator>(std::move(trust_checker)); + + return std::make_unique<IsolatedWebAppResponseReaderFactory>( + std::move(validator)); +} + } // namespace InstallIsolatedWebAppCommand::InstallIsolatedWebAppCommand( @@ -74,11 +97,32 @@ base::OnceCallback<void(base::expected<InstallIsolatedWebAppCommandSuccess, InstallIsolatedWebAppCommandError>)> callback) + : InstallIsolatedWebAppCommand( + isolation_info, + isolation_data, + std::move(web_contents), + std::move(url_loader), + browser_context, + std::move(callback), + CreateDefaultResponseReaderFactory(browser_context)) {} + +InstallIsolatedWebAppCommand::InstallIsolatedWebAppCommand( + const IsolatedWebAppUrlInfo& isolation_info, + const IsolationData& isolation_data, + std::unique_ptr<content::WebContents> web_contents, + std::unique_ptr<WebAppUrlLoader> url_loader, + content::BrowserContext& browser_context, + base::OnceCallback<void(base::expected<InstallIsolatedWebAppCommandSuccess, + InstallIsolatedWebAppCommandError>)> + callback, + std::unique_ptr<IsolatedWebAppResponseReaderFactory> + response_reader_factory) : WebAppCommandTemplate<AppLock>("InstallIsolatedWebAppCommand"), lock_description_( std::make_unique<AppLockDescription>(isolation_info.app_id())), isolation_info_(isolation_info), isolation_data_(isolation_data), + response_reader_factory_(std::move(response_reader_factory)), web_contents_(std::move(web_contents)), url_loader_(std::move(url_loader)), browser_context_(browser_context), @@ -125,6 +169,73 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); lock_ = std::move(lock); + CheckTrustAndSignatures(); +} + +void InstallIsolatedWebAppCommand::CheckTrustAndSignatures() { + absl::visit( + base::Overloaded{ + [&](const IsolationData::InstalledBundle& content) { + DCHECK_EQ(isolation_info_.web_bundle_id().type(), + web_package::SignedWebBundleId::Type::kEd25519PublicKey); + CheckTrustAndSignaturesOfBundle(content.path); + }, + [&](const IsolationData::DevModeBundle& content) { + DCHECK_EQ(isolation_info_.web_bundle_id().type(), + web_package::SignedWebBundleId::Type::kEd25519PublicKey); + CheckTrustAndSignaturesOfBundle(content.path); + }, + [&](const IsolationData::DevModeProxy& content) { + DCHECK_EQ(isolation_info_.web_bundle_id().type(), + web_package::SignedWebBundleId::Type::kDevelopment); + // Dev mode proxy mode does not use Web Bundles, hence there is no + // bundle to validate / trust and no signatures to check. + OnTrustAndSignaturesChecked(absl::nullopt); + }}, + isolation_data_.content); +} + +void InstallIsolatedWebAppCommand::CheckTrustAndSignaturesOfBundle( + const base::FilePath& path) { + // To check whether the bundle is valid and trusted, we attempt to create a + // `IsolatedWebAppResponseReader`. If a response reader is created + // successfully, then this means that the Signed Web Bundle... + // - ...is well formatted and uses a supported Web Bundle version. + // - ...contains a valid integrity block with a trusted public key. + // - ...has signatures that were verified successfully (as long as + // `skip_signature_verification` below is set to `false`). + // - ...contains valid metadata / no invalid URLs. + response_reader_factory_->CreateResponseReader( + path, isolation_info_.web_bundle_id(), + // During installation, we always want to verify signatures, regardless + // of the OS. + /*skip_signature_verification=*/false, + base::BindOnce( + [](base::expected<std::unique_ptr<IsolatedWebAppResponseReader>, + IsolatedWebAppResponseReaderFactory::Error> reader) + -> absl::optional<IsolatedWebAppResponseReaderFactory::Error> { + // Convert expected<Reader,Error> into optional<Error> to match the + // signature of `OnTrustAndSignaturesChecked`. This is necessary for + // compatibility with the dev mode proxy case, where + // `OnTrustAndSignaturesChecked` is called with `absl::nullopt` to + // indicate success. + if (!reader.has_value()) { + return std::move(reader.error()); + } + return absl::nullopt; + }) + .Then(base::BindOnce( + &InstallIsolatedWebAppCommand::OnTrustAndSignaturesChecked, + weak_factory_.GetWeakPtr()))); +} + +void InstallIsolatedWebAppCommand::OnTrustAndSignaturesChecked( + absl::optional<IsolatedWebAppResponseReaderFactory::Error> error) { + if (error) { + ReportFailure(IsolatedWebAppResponseReaderFactory::ErrorToString(*error)); + return; + } + CreateStoragePartition(); LoadUrl(); }
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h index 444ab3e..a24789c 100644 --- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h +++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command.h
@@ -17,6 +17,7 @@ #include "base/types/expected.h" #include "base/values.h" #include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" #include "chrome/browser/web_applications/os_integration/os_integration_manager.h" #include "chrome/browser/web_applications/web_app_id.h" @@ -83,6 +84,20 @@ void(base::expected<InstallIsolatedWebAppCommandSuccess, InstallIsolatedWebAppCommandError>)> callback); + // Same constructor as above, but additionally exposes the + // `response_reader_factory` for providing a mock factory in testing. + explicit InstallIsolatedWebAppCommand( + const IsolatedWebAppUrlInfo& isolation_info, + const IsolationData& isolation_data, + std::unique_ptr<content::WebContents> web_contents, + std::unique_ptr<WebAppUrlLoader> url_loader, + content::BrowserContext& browser_context, + base::OnceCallback< + void(base::expected<InstallIsolatedWebAppCommandSuccess, + InstallIsolatedWebAppCommandError>)> callback, + std::unique_ptr<IsolatedWebAppResponseReaderFactory> + response_reader_factory); + InstallIsolatedWebAppCommand(const InstallIsolatedWebAppCommand&) = delete; InstallIsolatedWebAppCommand& operator=(const InstallIsolatedWebAppCommand&) = delete; @@ -113,6 +128,11 @@ std::map<GURL, std::vector<SkBitmap>> icons_map, std::map<GURL, int /*http_status_code*/> icons_http_results); + void CheckTrustAndSignatures(); + void CheckTrustAndSignaturesOfBundle(const base::FilePath& path); + void OnTrustAndSignaturesChecked( + absl::optional<IsolatedWebAppResponseReaderFactory::Error> error); + void CreateStoragePartition(); void LoadUrl(); @@ -140,6 +160,8 @@ IsolatedWebAppUrlInfo isolation_info_; IsolationData isolation_data_; + std::unique_ptr<IsolatedWebAppResponseReaderFactory> response_reader_factory_; + std::unique_ptr<content::WebContents> web_contents_; std::unique_ptr<WebAppUrlLoader> url_loader_;
diff --git a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command_unittest.cc index 9d09787..b86f16c 100644 --- a/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/install_isolated_web_app_command_unittest.cc
@@ -13,6 +13,7 @@ #include <vector> #include "base/check_op.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback_forward.h" @@ -25,8 +26,12 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/test_future.h" #include "base/types/expected.h" +#include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_validator.h" #include "chrome/browser/web_applications/isolated_web_apps/pending_install_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_reader.h" #include "chrome/browser/web_applications/isolation_data.h" #include "chrome/browser/web_applications/locks/lock.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" @@ -43,6 +48,7 @@ #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_url_loader.h" #include "chrome/test/base/testing_profile.h" +#include "components/web_package/signed_web_bundles/ed25519_public_key.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/webapps/browser/installable/installable_logging.h" #include "components/webapps/browser/installable/installable_metrics.h" @@ -99,6 +105,20 @@ return url_info.value(); } +IsolatedWebAppUrlInfo CreateEd25519IsolatedWebAppUrlInfo() { + web_package::SignedWebBundleId signed_web_bundle_id = + web_package::SignedWebBundleId::CreateForEd25519PublicKey( + web_package::Ed25519PublicKey::Create( + base::make_span(kTestPublicKey))); + base::expected<IsolatedWebAppUrlInfo, std::string> url_info = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(signed_web_bundle_id); + if (!url_info.has_value()) { + CHECK(false) << "Failed to create testing web app url info: " + << url_info.error(); + } + return url_info.value(); +} + IsolationData CreateIsolationDataDevProxy( base::StringPiece dev_mode_proxy_url = "http://default-proxy-url.org/") { return IsolationData{IsolationData::DevModeProxy{ @@ -159,6 +179,34 @@ return fake_data_retriever; } +class FakeResponseReaderFactory : public IsolatedWebAppResponseReaderFactory { + public: + explicit FakeResponseReaderFactory( + absl::optional<IsolatedWebAppResponseReaderFactory::Error> bundle_error) + : IsolatedWebAppResponseReaderFactory( + nullptr, + base::BindRepeating( + []() -> std::unique_ptr< + web_package::SignedWebBundleSignatureVerifier> { + return nullptr; + })), + bundle_error_(std::move(bundle_error)) {} + + void CreateResponseReader(const base::FilePath& web_bundle_path, + const web_package::SignedWebBundleId& web_bundle_id, + bool skip_signature_verification, + Callback callback) override { + if (bundle_error_) { + std::move(callback).Run(base::unexpected(std::move(*bundle_error_))); + } else { + std::move(callback).Run(nullptr); + } + } + + private: + absl::optional<IsolatedWebAppResponseReaderFactory::Error> bundle_error_; +}; + class InstallIsolatedWebAppCommandTest : public ::testing::Test { public: void SetUp() override { @@ -200,6 +248,7 @@ std::unique_ptr<content::WebContents> web_contents; absl::optional<IsolationData> isolation_data; raw_ptr<WebAppInstallFinalizer> install_finalizer = nullptr; + absl::optional<IsolatedWebAppResponseReaderFactory::Error> bundle_error; }; base::expected<InstallIsolatedWebAppCommandSuccess, @@ -232,7 +281,8 @@ auto command = CreateCommand( parameters.url_info, std::move(web_contents), parameters.isolation_data, - std::move(url_loader), test_future.GetCallback()); + std::move(url_loader), test_future.GetCallback(), + std::move(parameters.bundle_error)); command->SetDataRetrieverForTesting( data_retriever != nullptr ? std::move(data_retriever) @@ -249,14 +299,17 @@ std::unique_ptr<WebAppUrlLoader> url_loader, base::OnceCallback< void(base::expected<InstallIsolatedWebAppCommandSuccess, - InstallIsolatedWebAppCommandError>)> callback) { + InstallIsolatedWebAppCommandError>)> callback, + absl::optional<IsolatedWebAppResponseReaderFactory::Error> bundle_error = + absl::nullopt) { if (!isolation_data.has_value()) { isolation_data = CreateIsolationDataDevProxy(); } return std::make_unique<InstallIsolatedWebAppCommand>( url_info, isolation_data.value(), std::move(web_contents), - std::move(url_loader), *profile(), std::move(callback)); + std::move(url_loader), *profile(), std::move(callback), + std::make_unique<FakeResponseReaderFactory>(std::move(bundle_error))); } base::expected<InstallIsolatedWebAppCommandSuccess, @@ -957,7 +1010,7 @@ TEST_F(InstallIsolatedWebAppCommandTest, SetInstalledBundleIsolationDataBeforeUrlLoading) { - IsolatedWebAppUrlInfo url_info = CreateRandomIsolatedWebAppUrlInfo(); + IsolatedWebAppUrlInfo url_info = CreateEd25519IsolatedWebAppUrlInfo(); auto url_loader = std::make_unique<TestWebAppUrlLoader>(); url_loader->SetNextLoadUrlResult( url_info.origin().GetURL().Resolve( @@ -1099,5 +1152,51 @@ BucketsAre(base::Bucket(false, 1))); } +class InstallIsolatedWebAppCommandBundleTest + : public InstallIsolatedWebAppCommandTest, + public ::testing::WithParamInterface<bool> { + public: + InstallIsolatedWebAppCommandBundleTest() + : isolation_data_(GetParam() + ? IsolationData{IsolationData::InstalledBundle{ + .path = base::FilePath{FILE_PATH_LITERAL( + "/testing/path/to/a/bundle")}, + }} + : IsolationData{IsolationData::DevModeBundle{ + .path = base::FilePath{FILE_PATH_LITERAL( + "/testing/path/to/a/bundle")}, + }}) {} + + protected: + IsolationData isolation_data_; +}; + +TEST_P(InstallIsolatedWebAppCommandBundleTest, InstallsWhenThereIsNoError) { + IsolatedWebAppUrlInfo url_info = CreateEd25519IsolatedWebAppUrlInfo(); + EXPECT_THAT(ExecuteCommand(Parameters{ + .url_info = url_info, + .isolation_data = isolation_data_, + .bundle_error = absl::nullopt, + }), + IsInstallationOk()); +} + +TEST_P(InstallIsolatedWebAppCommandBundleTest, ErrorsOnBundleError) { + IsolatedWebAppUrlInfo url_info = CreateEd25519IsolatedWebAppUrlInfo(); + EXPECT_THAT( + ExecuteCommand(Parameters{.url_info = url_info, + .isolation_data = isolation_data_, + .bundle_error = MetadataError("test error")}), + IsInstallationError(HasSubstr("test error"))); +} + +INSTANTIATE_TEST_SUITE_P(All, + InstallIsolatedWebAppCommandBundleTest, + ::testing::Bool(), + [](::testing::TestParamInfo<bool> param_info) { + return param_info.param ? "InstalledBundle" + : "DevModeBundle"; + }); + } // namespace } // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc index e119c65..a05c6ea 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc
@@ -9,7 +9,6 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" -#include "base/functional/overloaded.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" @@ -225,31 +224,8 @@ IsolatedWebAppReaderRegistry::ReadResponseError IsolatedWebAppReaderRegistry::ReadResponseError::ForError( const IsolatedWebAppResponseReaderFactory::Error& error) { - return ForOtherError(absl::visit( - base::Overloaded{ - [](const web_package::mojom::BundleIntegrityBlockParseErrorPtr& - error) { - return base::StringPrintf("Failed to parse integrity block: %s", - error->message.c_str()); - }, - [](const IntegrityBlockError& error) { - return base::StringPrintf("Failed to validate integrity block: %s", - error.message.c_str()); - }, - [](const web_package::SignedWebBundleSignatureVerifier::Error& - error) { - return base::StringPrintf("Failed to verify signatures: %s", - error.message.c_str()); - }, - [](const web_package::mojom::BundleMetadataParseErrorPtr& error) { - return base::StringPrintf("Failed to parse metadata: %s", - error->message.c_str()); - }, - [](const MetadataError& error) { - return base::StringPrintf("Failed to validate metadata: %s", - error.message.c_str()); - }}, - error)); + return ForOtherError( + IsolatedWebAppResponseReaderFactory::ErrorToString(error)); } // static
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.cc index a2b5dada..4a7cab85 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.cc
@@ -10,6 +10,7 @@ #include "base/functional/overloaded.h" #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" +#include "base/strings/stringprintf.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_validator.h" #include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_reader.h" #include "chrome/common/url_constants.h" @@ -62,6 +63,36 @@ web_bundle_id, std::move(callback))); } +// static +std::string IsolatedWebAppResponseReaderFactory::ErrorToString( + const Error& error) { + return (absl::visit( + base::Overloaded{ + [](const web_package::mojom::BundleIntegrityBlockParseErrorPtr& + error) { + return base::StringPrintf("Failed to parse integrity block: %s", + error->message.c_str()); + }, + [](const IntegrityBlockError& error) { + return base::StringPrintf("Failed to validate integrity block: %s", + error.message.c_str()); + }, + [](const web_package::SignedWebBundleSignatureVerifier::Error& + error) { + return base::StringPrintf("Failed to verify signatures: %s", + error.message.c_str()); + }, + [](const web_package::mojom::BundleMetadataParseErrorPtr& error) { + return base::StringPrintf("Failed to parse metadata: %s", + error->message.c_str()); + }, + [](const MetadataError& error) { + return base::StringPrintf("Failed to validate metadata: %s", + error.message.c_str()); + }}, + error)); +} + void IsolatedWebAppResponseReaderFactory::OnIntegrityBlockRead( const web_package::SignedWebBundleId& web_bundle_id, bool skip_signature_verification,
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h index d51c60e..77d9747 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_response_reader_factory.h
@@ -53,12 +53,15 @@ // `skip_signature_verification` is set). class IsolatedWebAppResponseReaderFactory { public: - IsolatedWebAppResponseReaderFactory( + explicit IsolatedWebAppResponseReaderFactory( std::unique_ptr<IsolatedWebAppValidator> validator, base::RepeatingCallback< std::unique_ptr<web_package::SignedWebBundleSignatureVerifier>()> - signature_verifier_factory); - ~IsolatedWebAppResponseReaderFactory(); + signature_verifier_factory = base::BindRepeating([]() { + return std::make_unique< + web_package::SignedWebBundleSignatureVerifier>(); + })); + virtual ~IsolatedWebAppResponseReaderFactory(); IsolatedWebAppResponseReaderFactory( const IsolatedWebAppResponseReaderFactory&) = delete; @@ -82,10 +85,13 @@ using Callback = base::OnceCallback<void( base::expected<std::unique_ptr<IsolatedWebAppResponseReader>, Error>)>; - void CreateResponseReader(const base::FilePath& web_bundle_path, - const web_package::SignedWebBundleId& web_bundle_id, - bool skip_signature_verification, - Callback callback); + virtual void CreateResponseReader( + const base::FilePath& web_bundle_path, + const web_package::SignedWebBundleId& web_bundle_id, + bool skip_signature_verification, + Callback callback); + + static std::string ErrorToString(const Error& error); // This enum represents every error type that can occur during integrity block // and metadata parsing, before responses are read from Signed Web Bundles.
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc index b3b557bc..d2ac81c 100644 --- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc +++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
@@ -16,6 +16,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/no_destructor.h" +#include "base/strings/string_util.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" @@ -179,7 +180,8 @@ for (const auto& file_handler : *file_handlers) { std::set<std::string> supported_file_extensions = apps::GetFileExtensionsFromFileHandlers({file_handler}); - if (base::Contains(supported_file_extensions, file_extension)) { + if (base::Contains(supported_file_extensions, + base::ToLowerASCII(file_extension))) { launch_handlers[&file_handler].push_back(file_path); break; }
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc index ded315d..74489b4 100644 --- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc +++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
@@ -287,6 +287,20 @@ EXPECT_EQ(url, std::get<GURL>(launch_infos[0])); } +TEST_F(WebAppFileHandlerManagerTest, ExtensionCaseInsensitive) { + const GURL url("https://app.site/handle-foo"); + + file_handler_manager().InstallFileHandler( + app_id(), url, {{"application/foo", {".foo"}}}, absl::nullopt); + + // Matches on single valid extension. + const base::FilePath path(FILE_PATH_LITERAL("file.FOO")); + WebAppFileHandlerManager::LaunchInfos launch_infos = + file_handler_manager().GetMatchingFileHandlerUrls(app_id(), {path}); + ASSERT_EQ(1u, launch_infos.size()); + EXPECT_EQ(url, std::get<GURL>(launch_infos[0])); +} + TEST_F(WebAppFileHandlerManagerTest, SingleInvalidExtensionSingleExtensionHandler) { const GURL url("https://app.site/handle-foo");
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm index 5e0cb8a..4484d99 100644 --- a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm +++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm
@@ -26,7 +26,7 @@ #include "base/logging.h" #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" -#import "base/mac/launch_services_util.h" +#import "base/mac/launch_application.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" @@ -442,9 +442,8 @@ mojo::core::kMojoIpcz.name); } - base::mac::OpenApplication( - shim_path, command_line, /*url_specs=*/{}, - /*options=*/{.activate = false}, + base::mac::LaunchApplication( + shim_path, command_line, /*url_specs=*/{}, {.activate = false}, base::BindOnce( [](base::FilePath shim_path, std::vector<base::FilePath> remaining_shim_paths, @@ -1467,8 +1466,8 @@ url_specs.push_back(url.spec()); } - base::mac::OpenApplication( - shim_path, command_line, url_specs, /*options=*/{.activate = false}, + base::mac::LaunchApplication( + shim_path, command_line, url_specs, {.activate = false}, base::BindOnce( [](const base::FilePath& shim_path, ShimLaunchedCallback launched_callback,
diff --git a/chrome/browser/web_applications/web_app_helpers.cc b/chrome/browser/web_applications/web_app_helpers.cc index b679fd8..253f245d 100644 --- a/chrome/browser/web_applications/web_app_helpers.cc +++ b/chrome/browser/web_applications/web_app_helpers.cc
@@ -54,6 +54,10 @@ AppId GenerateAppIdFromUnhashed(std::string unhashed_app_id) { DCHECK_EQ(GURL(unhashed_app_id).spec(), unhashed_app_id); + // The app ID is hashed twice: here and in GenerateId. + // The double-hashing is for historical reasons and it needs to stay + // this way for backwards compatibility. (Back then, a web app's input to the + // hash needed to be formatted like an extension public key.) return crx_file::id_util::GenerateId( crypto::SHA256HashString(unhashed_app_id)); }
diff --git a/chrome/browser/webshare/share_service_browsertest.cc b/chrome/browser/webshare/share_service_browsertest.cc index 80d84bd2..56526b3 100644 --- a/chrome/browser/webshare/share_service_browsertest.cc +++ b/chrome/browser/webshare/share_service_browsertest.cc
@@ -40,14 +40,6 @@ feature_list_.InitAndEnableFeature(features::kWebShare); } - void SetUp() override { -#if BUILDFLAG(IS_WIN) - if (!webshare::ScopedShareOperationFakeComponents::IsSupportedEnvironment()) - GTEST_SKIP(); -#endif - InProcessBrowserTest::SetUp(); - } - void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/webshare/share_service_unittest.cc b/chrome/browser/webshare/share_service_unittest.cc index d7a1668..6270237 100644 --- a/chrome/browser/webshare/share_service_unittest.cc +++ b/chrome/browser/webshare/share_service_unittest.cc
@@ -62,9 +62,6 @@ base::BindRepeating(&ShareServiceUnitTest::AcceptShareRequest)); #endif #if BUILDFLAG(IS_WIN) - if (!webshare::ScopedShareOperationFakeComponents::IsSupportedEnvironment()) - GTEST_SKIP(); - ASSERT_NO_FATAL_FAILURE(scoped_fake_components_.SetUp()); #endif }
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager.cc b/chrome/browser/webshare/win/fake_data_transfer_manager.cc index 3965fd9..c3a3031 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager.cc +++ b/chrome/browser/webshare/win/fake_data_transfer_manager.cc
@@ -12,7 +12,6 @@ #include "base/win/core_winrt_util.h" #include "base/win/scoped_hstring.h" #include "base/win/vector.h" -#include "base/win/windows_version.h" #include "testing/gtest/include/gtest/gtest.h" using ABI::Windows::ApplicationModel::DataTransfer::DataPackage; @@ -403,10 +402,6 @@ } // namespace // static -bool FakeDataTransferManager::IsSupportedEnvironment() { - return base::win::GetVersion() >= base::win::Version::WIN10; -} - FakeDataTransferManager::FakeDataTransferManager() { post_data_requested_callback_ = base::DoNothing(); }
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager.h b/chrome/browser/webshare/win/fake_data_transfer_manager.h index eb79a55..02cc880 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager.h +++ b/chrome/browser/webshare/win/fake_data_transfer_manager.h
@@ -48,8 +48,6 @@ using PostDataRequestedCallback = base::RepeatingCallback<void(const DataRequestedContent&)>; - static bool IsSupportedEnvironment(); - FakeDataTransferManager(); FakeDataTransferManager(const FakeDataTransferManager&) = delete; FakeDataTransferManager& operator=(const FakeDataTransferManager&) = delete;
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager_interop.cc b/chrome/browser/webshare/win/fake_data_transfer_manager_interop.cc index b567168..050d65f2 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager_interop.cc +++ b/chrome/browser/webshare/win/fake_data_transfer_manager_interop.cc
@@ -13,11 +13,6 @@ namespace webshare { -// static -bool FakeDataTransferManagerInterop::IsSupportedEnvironment() { - return FakeDataTransferManager::IsSupportedEnvironment(); -} - FakeDataTransferManagerInterop::FakeDataTransferManagerInterop() = default; FakeDataTransferManagerInterop::~FakeDataTransferManagerInterop() {
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager_interop.h b/chrome/browser/webshare/win/fake_data_transfer_manager_interop.h index ec01e65..a78f84c 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager_interop.h +++ b/chrome/browser/webshare/win/fake_data_transfer_manager_interop.h
@@ -47,8 +47,6 @@ SucceedWithoutAction }; - static bool IsSupportedEnvironment(); - FakeDataTransferManagerInterop(); FakeDataTransferManagerInterop(const FakeDataTransferManagerInterop&) = delete;
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager_interop_unittest.cc b/chrome/browser/webshare/win/fake_data_transfer_manager_interop_unittest.cc index 6ee684f9..7046ad2c 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager_interop_unittest.cc +++ b/chrome/browser/webshare/win/fake_data_transfer_manager_interop_unittest.cc
@@ -55,8 +55,6 @@ class FakeDataTransferManagerInteropTest : public ::testing::Test { protected: void SetUp() override { - if (!FakeDataTransferManagerInterop::IsSupportedEnvironment()) - GTEST_SKIP(); fake_data_transfer_manager_interop_ = Microsoft::WRL::Make<FakeDataTransferManagerInterop>(); }
diff --git a/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc b/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc index 219322a3..2f6c5a6 100644 --- a/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc +++ b/chrome/browser/webshare/win/fake_data_transfer_manager_unittest.cc
@@ -93,9 +93,6 @@ class FakeDataTransferManagerTest : public ::testing::Test { protected: void SetUp() override { - if (!FakeDataTransferManager::IsSupportedEnvironment()) - GTEST_SKIP(); - winrt_initializer_.emplace(); ASSERT_TRUE(winrt_initializer_->Succeeded()); fake_data_transfer_manager_ =
diff --git a/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.cc b/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.cc index a55d6e1..b93004a 100644 --- a/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.cc +++ b/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.cc
@@ -38,11 +38,6 @@ } // namespace -// static -bool ScopedFakeDataTransferManagerInterop::IsSupportedEnvironment() { - return FakeDataTransferManagerInterop::IsSupportedEnvironment(); -} - ScopedFakeDataTransferManagerInterop::ScopedFakeDataTransferManagerInterop() = default; @@ -56,7 +51,6 @@ void ScopedFakeDataTransferManagerInterop::SetUp() { ASSERT_FALSE(set_up_); - ASSERT_TRUE(IsSupportedEnvironment()); base::win::AssertComInitialized(); instance_ = Microsoft::WRL::Make<FakeDataTransferManagerInterop>();
diff --git a/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.h b/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.h index 87b9785..92429b1a 100644 --- a/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.h +++ b/chrome/browser/webshare/win/scoped_fake_data_transfer_manager_interop.h
@@ -16,8 +16,6 @@ // for the Share contract. class ScopedFakeDataTransferManagerInterop { public: - static bool IsSupportedEnvironment(); - ScopedFakeDataTransferManagerInterop(); ScopedFakeDataTransferManagerInterop( const ScopedFakeDataTransferManagerInterop&) = delete;
diff --git a/chrome/browser/webshare/win/scoped_share_operation_fake_components.cc b/chrome/browser/webshare/win/scoped_share_operation_fake_components.cc index b5d80978..99c8156 100644 --- a/chrome/browser/webshare/win/scoped_share_operation_fake_components.cc +++ b/chrome/browser/webshare/win/scoped_share_operation_fake_components.cc
@@ -54,11 +54,6 @@ } // namespace -// static -bool ScopedShareOperationFakeComponents::IsSupportedEnvironment() { - return ScopedFakeDataTransferManagerInterop::IsSupportedEnvironment(); -} - ScopedShareOperationFakeComponents::ScopedShareOperationFakeComponents() = default; @@ -71,7 +66,6 @@ } void ScopedShareOperationFakeComponents::SetUp() { - ASSERT_TRUE(IsSupportedEnvironment()); base::win::AssertComInitialized(); ASSERT_NO_FATAL_FAILURE(scoped_fake_data_transfer_manager_interop_.SetUp());
diff --git a/chrome/browser/webshare/win/scoped_share_operation_fake_components.h b/chrome/browser/webshare/win/scoped_share_operation_fake_components.h index 67eae30..9d29fdd 100644 --- a/chrome/browser/webshare/win/scoped_share_operation_fake_components.h +++ b/chrome/browser/webshare/win/scoped_share_operation_fake_components.h
@@ -21,8 +21,6 @@ // ShareOperation. class ScopedShareOperationFakeComponents final { public: - static bool IsSupportedEnvironment(); - ScopedShareOperationFakeComponents(); ScopedShareOperationFakeComponents( const ScopedShareOperationFakeComponents&) = delete;
diff --git a/chrome/browser/webshare/win/share_operation_unittest.cc b/chrome/browser/webshare/win/share_operation_unittest.cc index 0937bf8..b4aaa46 100644 --- a/chrome/browser/webshare/win/share_operation_unittest.cc +++ b/chrome/browser/webshare/win/share_operation_unittest.cc
@@ -66,9 +66,6 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - if (!ScopedShareOperationFakeComponents::IsSupportedEnvironment()) - GTEST_SKIP(); - ASSERT_NO_FATAL_FAILURE(scoped_fake_components_.SetUp()); ShareOperation::SetMaxFileBytesForTesting(kMaxSharedFileBytesForTest); } @@ -468,29 +465,4 @@ kMaxSharedFileBytesForTest + 1); } -class ShareOperationInUnsupportedEnvironmentUnitTest - : public ShareOperationUnitTest { - public: - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - - if (ScopedShareOperationFakeComponents::IsSupportedEnvironment()) - GTEST_SKIP(); - } -}; - -TEST_F(ShareOperationInUnsupportedEnvironmentUnitTest, GracefullyFails) { - base::RunLoop run_loop; - std::vector<blink::mojom::SharedFilePtr> files; - ShareOperation operation{"shared title", "shared text", - GURL("https://www.contoso.com"), std::move(files), - web_contents()}; - operation.Run( - base::BindLambdaForTesting([&run_loop](blink::mojom::ShareError error) { - ASSERT_EQ(error, blink::mojom::ShareError::INTERNAL_ERROR); - run_loop.Quit(); - })); - run_loop.Run(); -} - } // namespace webshare
diff --git a/chrome/browser/webshare/win/show_share_ui_for_window_operation.cc b/chrome/browser/webshare/win/show_share_ui_for_window_operation.cc index e05b26b..a48308ac4 100644 --- a/chrome/browser/webshare/win/show_share_ui_for_window_operation.cc +++ b/chrome/browser/webshare/win/show_share_ui_for_window_operation.cc
@@ -9,10 +9,13 @@ #include <windows.applicationmodel.datatransfer.h> #include <wrl/event.h> +#include <utility> + #include "base/functional/callback.h" +#include "base/strings/string_piece.h" #include "base/task/single_thread_task_runner.h" #include "base/win/core_winrt_util.h" -#include "base/win/windows_version.h" +#include "base/win/scoped_hstring.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -37,12 +40,8 @@ HWND hwnd, IDataTransferManagerInterop** data_transfer_manager_interop, IDataTransferManager** data_transfer_manager) { - // If the required WinRT functionality is not available, fail the operation - // Note: Though the Share APIs are present starting in Windows 8, they are - // only fulfilled when invoked from within a UWP app container. Starting in - // Windows 10 they are fulfilled for all callers. - if ((base::win::GetVersion() < base::win::Version::WIN10) || - !base::win::ResolveCoreWinRTDelayload() || + // If the required WinRT functionality is not available, fail the operation. + if (!base::win::ResolveCoreWinRTDelayload() || !base::win::ScopedHString::ResolveCoreWinRTStringDelayload()) { return E_FAIL; }
diff --git a/chrome/browser/webshare/win/show_share_ui_for_window_operation_unittest.cc b/chrome/browser/webshare/win/show_share_ui_for_window_operation_unittest.cc index a63c520c7..942a398 100644 --- a/chrome/browser/webshare/win/show_share_ui_for_window_operation_unittest.cc +++ b/chrome/browser/webshare/win/show_share_ui_for_window_operation_unittest.cc
@@ -41,8 +41,6 @@ enum TestCallbackState { NotRun = 0, RunWithoutValue, RunWithValue }; void SetUp() override { - if (!ScopedFakeDataTransferManagerInterop::IsSupportedEnvironment()) - GTEST_SKIP(); ASSERT_NO_FATAL_FAILURE(scoped_interop_.SetUp()); operation_ = std::make_unique<ShowShareUIForWindowOperation>(hwnd_); auto weak_ptr = weak_factory_.GetWeakPtr();
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 7b6464d..70d37e2 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1674646908-1a2d9a197184ed4b416c08a6181483277cb38b8f.profdata +chrome-linux-main-1674733883-9c55d134bf9d2b7c041e10d4cb02824d06d7eafe.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index bd48743..12948ad 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1674646908-a2d994ed1749852d4163793acba88863a3bd0db4.profdata +chrome-mac-arm-main-1674733883-cc7c971f5ea5f50d9802e8e70437e598618ef313.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 11c5598..0193e3d 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1674646908-6581c73c66d969ff1fa5207cc95448dfbe304661.profdata +chrome-mac-main-1674733883-8409d685367724af00ee0a1b815b8434f4a78b95.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 9747b2a..c3dbd0a 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1674635826-61327aa41d1d20f1514dcd09bbb557ed8b02aa3f.profdata +chrome-win32-main-1674744966-1b00cf0c65890c7cff7f04c9f89f02da2443a63e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 3e76a8c..643611c8 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1674635826-88ea6c4857218afde61b53f2e8d382a84c2450fb.profdata +chrome-win64-main-1674733883-c180c826dfb1e2952c9fc69ecf3a0f39d51c214a.profdata
diff --git a/chrome/chrome_cleaner/test/cleaner_test.cc b/chrome/chrome_cleaner/test/cleaner_test.cc index 997eaee1..6326ce89 100644 --- a/chrome/chrome_cleaner/test/cleaner_test.cc +++ b/chrome/chrome_cleaner/test/cleaner_test.cc
@@ -22,7 +22,6 @@ #include "base/task/thread_pool.h" #include "base/test/task_environment.h" #include "base/test/test_timeouts.h" -#include "base/win/windows_version.h" #include "chrome/chrome_cleaner/buildflags.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" #include "chrome/chrome_cleaner/ipc/chrome_prompt_test_util.h" @@ -550,13 +549,6 @@ } TEST_P(CleanerTest, NoUnsanitizedPaths) { - // Fails on Windows7/8/8.1 - // TODO(crbug/1405033): This is temporary while we disable these tests in - // pre-M110 branches. - if (base::win::GetVersion() <= base::win::Version::WIN8_1) { - return; - } - CreateRemovableUwS(); base::CommandLine command_line = BuildCommandLine(kCleanerExecutable);
diff --git a/chrome/chrome_elf/hook_util/hook_util.cc b/chrome/chrome_elf/hook_util/hook_util.cc index faed9bf..565221af2 100644 --- a/chrome/chrome_elf/hook_util/hook_util.cc +++ b/chrome/chrome_elf/hook_util/hook_util.cc
@@ -10,7 +10,6 @@ #include "chrome/chrome_elf/nt_registry/nt_registry.h" // utils #include "sandbox/win/src/interception_internal.h" #include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/sandbox_utils.h" namespace {
diff --git a/chrome/common/chromeos/extensions/api/telemetry.idl b/chrome/common/chromeos/extensions/api/telemetry.idl index bf531ab0..4823150f 100644 --- a/chrome/common/chromeos/extensions/api/telemetry.idl +++ b/chrome/common/chromeos/extensions/api/telemetry.idl
@@ -5,6 +5,33 @@ // Use the <code>chrome.os.telemetry</code> API to get telemetry data. [implemented_in = "chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h"] namespace os.telemetry { + dictionary AudioInputNodeInfo { + double? id; + DOMString? name; + DOMString? deviceName; + boolean? active; + long? nodeGain; + }; + + dictionary AudioOutputNodeInfo { + double? id; + DOMString? name; + DOMString? deviceName; + boolean? active; + long? nodeVolume; + }; + + dictionary AudioInfo { + boolean? outputMute; + boolean? inputMute; + long? underruns; + long? severeUnderruns; + AudioOutputNodeInfo[] outputNodes; + AudioInputNodeInfo[] inputNodes; + }; + + callback AudioInfoCallback = void (AudioInfo audioInfo); + dictionary BatteryInfo { double? cycleCount; double? voltageNow; @@ -76,6 +103,12 @@ callback CpuInfoCallback = void (CpuInfo cpuInfo); + dictionary MarketingInfo { + DOMString? marketingName; + }; + + callback MarketingInfoCallback = void (MarketingInfo marketingInfo); + dictionary MemoryInfo { long? totalMemoryKiB; long? freeMemoryKiB; @@ -225,6 +258,8 @@ callback TpmInfoCallback = void (TpmInfo tpmInfo); interface Functions { + [supportsPromises] static void getAudioInfo(AudioInfoCallback callback); + [supportsPromises] static void getBatteryInfo(BatteryInfoCallback callback); [supportsPromises] static void getNonRemovableBlockDevicesInfo(NonRemovableBlockDevicesInfoCallback callback); @@ -233,6 +268,8 @@ [supportsPromises] static void getInternetConnectivityInfo(InternetConnectivityInfoCallback callback); + [supportsPromises] static void getMarketingInfo(MarketingInfoCallback callback); + [supportsPromises] static void getMemoryInfo(MemoryInfoCallback callback); [supportsPromises] static void getOemData(OemDataCallback callback);
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index 3af2082..2d18488 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -661,7 +661,9 @@ // Whether the frame sink is the root. boolean isRoot; - // Number of presented frames grouped by seconds, i.e. fps. + // Number of presented frames grouped using `bucketSizeInSeconds` arg in + // startFrameCounting call. It would be fps if the `bucketSizeInSeconds` is + // 1s. long[] presentedFrames; };
diff --git a/chrome/common/extensions/api/privacy.json b/chrome/common/extensions/api/privacy.json index 4cd30d24..3a24fae 100644 --- a/chrome/common/extensions/api/privacy.json +++ b/chrome/common/extensions/api/privacy.json
@@ -103,6 +103,7 @@ "privacySandboxEnabled": { "$ref": "types.ChromeSetting", "value": ["privacySandboxEnabled", {"type": "boolean"}], + "deprecated": "We’re deprecating the API <code><a href='#property-websites-privacySandboxEnabled'>chrome.privacy.websites.privacySandboxEnabled</a></code>, though it will remain active for backward compatibility until release M113. Instead, please use <code><a href='#property-websites-topicsEnabled'>chrome.privacy.websites.topicsEnabled</a></code>, <code><a href='#property-websites-fledgeEnabled'>chrome.privacy.websites.fledgeEnabled</a></code> and <code><a href='#property-websites-adMeasurementEnabled'>chrome.privacy.websites.adMeasurementEnabled</a></code>.", "description": "If enabled, the experimental <a href=”https://www.chromium.org/Home/chromium-privacy/privacy-sandbox”>Privacy Sandbox</a> features are active. The value of this preference is of type boolean, and the default value is <code>true</code>. PLEASE NOTE: The schema of this API may change in the future as the Privacy Sandbox features crystallize. In that case, we will provide prior notice." }, "topicsEnabled": {
diff --git a/chrome/common/media/cdm_registration.cc b/chrome/common/media/cdm_registration.cc index de372eb..21718760 100644 --- a/chrome/common/media/cdm_registration.cc +++ b/chrome/common/media/cdm_registration.cc
@@ -14,6 +14,7 @@ #include "content/public/common/cdm_info.h" #include "media/cdm/cdm_capability.h" #include "media/cdm/cdm_type.h" +#include "media/cdm/clear_key_cdm_common.h" #include "third_party/widevine/cdm/buildflags.h" #if BUILDFLAG(ENABLE_LIBRARY_CDMS) @@ -260,33 +261,26 @@ if (clear_key_cdm_path.empty() || !base::PathExists(clear_key_cdm_path)) return; - // TODO(crbug.com/764480): Remove these after we have a central place for - // External Clear Key (ECK) related information. - // Normal External Clear Key key system. - const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; - // A variant of ECK key system that has a different CDM type. - const char kkExternalClearKeyDifferentCdmTypeTestKeySystem[] = - "org.chromium.externalclearkey.differentcdmtype"; - // Supported codecs are hard-coded in ExternalClearKeySystemInfo. media::CdmCapability capability( {}, {}, {media::EncryptionScheme::kCenc, media::EncryptionScheme::kCbcs}, {media::CdmSessionType::kTemporary, media::CdmSessionType::kPersistentLicense}); - // Register kkExternalClearKeyDifferentCdmTypeTestKeySystem first separately. - // Otherwise, it'll be treated as a sub-key-system of normal - // kExternalClearKeyKeySystem. See MultipleCdmTypes test in + // Register media::kExternalClearKeyDifferentCdmTypeTestKeySystem first + // separately. Otherwise, it'll be treated as a sub-key-system of normal + // media::kExternalClearKeyKeySystem. See MultipleCdmTypes test in // ECKEncryptedMediaTest. cdms->push_back(content::CdmInfo( - kkExternalClearKeyDifferentCdmTypeTestKeySystem, + media::kExternalClearKeyDifferentCdmTypeTestKeySystem, Robustness::kSoftwareSecure, capability, /*supports_sub_key_systems=*/false, media::kClearKeyCdmDisplayName, media::kClearKeyCdmDifferentCdmType, base::Version("0.1.0.0"), clear_key_cdm_path)); cdms->push_back(content::CdmInfo( - kExternalClearKeyKeySystem, Robustness::kSoftwareSecure, capability, + media::kExternalClearKeyKeySystem, Robustness::kSoftwareSecure, + capability, /*supports_sub_key_systems=*/true, media::kClearKeyCdmDisplayName, media::kClearKeyCdmType, base::Version("0.1.0.0"), clear_key_cdm_path)); }
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index c5509e98..0610d02 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -143,78 +143,6 @@ const char kSupervisedUserMetricsDayId[] = "supervised_user.metrics.day_id"; #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) -// Stores the email address associated with the google account of the custodian -// of the supervised user, set when the supervised user is created. -const char kSupervisedUserCustodianEmail[] = "profile.managed.custodian_email"; - -// Stores the display name associated with the google account of the custodian -// of the supervised user, updated (if possible) each time the supervised user -// starts a session. -const char kSupervisedUserCustodianName[] = "profile.managed.custodian_name"; - -// Stores the obfuscated gaia id associated with the google account of the -// custodian of the supervised user, updated (if possible) each time the -// supervised user starts a session. -const char kSupervisedUserCustodianObfuscatedGaiaId[] = - "profile.managed.custodian_obfuscated_gaia_id"; - -// Stores the URL of the profile image associated with the google account of the -// custodian of the supervised user. -const char kSupervisedUserCustodianProfileImageURL[] = - "profile.managed.custodian_profile_image_url"; - -// Stores the URL of the profile associated with the google account of the -// custodian of the supervised user. -const char kSupervisedUserCustodianProfileURL[] = - "profile.managed.custodian_profile_url"; - -// Whether the supervised user may approve extension permission requests. If -// false, extensions should not be able to request new permissions, and new -// extensions should not be installable. -const char kSupervisedUserExtensionsMayRequestPermissions[] = - "profile.managed.extensions_may_request_permissions"; - -// Maps host names to whether the host is manually allowed or blocked. -const char kSupervisedUserManualHosts[] = "profile.managed.manual_hosts"; - -// Maps URLs to whether the URL is manually allowed or blocked. -const char kSupervisedUserManualURLs[] = "profile.managed.manual_urls"; - -// Stores whether the SafeSites filter is enabled. -const char kSupervisedUserSafeSites[] = "profile.managed.safe_sites"; - -// Stores the email address associated with the google account of the secondary -// custodian of the supervised user, set when the supervised user is created. -const char kSupervisedUserSecondCustodianEmail[] = - "profile.managed.second_custodian_email"; - -// Stores the display name associated with the google account of the secondary -// custodian of the supervised user, updated (if possible) each time the -// supervised user starts a session. -const char kSupervisedUserSecondCustodianName[] = - "profile.managed.second_custodian_name"; - -// Stores the obfuscated gaia id associated with the google account of the -// secondary custodian of the supervised user, updated (if possible) each time -// the supervised user starts a session. -const char kSupervisedUserSecondCustodianObfuscatedGaiaId[] = - "profile.managed.second_custodian_obfuscated_gaia_id"; - -// Stores the URL of the profile image associated with the google account of the -// secondary custodian of the supervised user. -const char kSupervisedUserSecondCustodianProfileImageURL[] = - "profile.managed.second_custodian_profile_image_url"; - -// Stores the URL of the profile associated with the google account of the -// secondary custodian of the supervised user. -const char kSupervisedUserSecondCustodianProfileURL[] = - "profile.managed.second_custodian_profile_url"; - -// Stores settings that can be modified both by a supervised user and their -// manager. See SupervisedUserSharedSettingsService for a description of -// the format. -const char kSupervisedUserSharedSettings[] = "profile.managed.shared_settings"; - #if BUILDFLAG(ENABLE_RLZ) // Integer. RLZ ping delay in seconds. const char kRlzPingDelaySeconds[] = "rlz_ping_delay";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 83ce4892..75aa359 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -55,21 +55,7 @@ #if BUILDFLAG(ENABLE_SUPERVISED_USERS) extern const char kSupervisedUserMetricsDayId[]; #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) -extern const char kSupervisedUserCustodianEmail[]; -extern const char kSupervisedUserCustodianName[]; -extern const char kSupervisedUserCustodianObfuscatedGaiaId[]; -extern const char kSupervisedUserCustodianProfileImageURL[]; -extern const char kSupervisedUserCustodianProfileURL[]; -extern const char kSupervisedUserExtensionsMayRequestPermissions[]; -extern const char kSupervisedUserManualHosts[]; -extern const char kSupervisedUserManualURLs[]; -extern const char kSupervisedUserSafeSites[]; -extern const char kSupervisedUserSecondCustodianEmail[]; -extern const char kSupervisedUserSecondCustodianName[]; -extern const char kSupervisedUserSecondCustodianObfuscatedGaiaId[]; -extern const char kSupervisedUserSecondCustodianProfileImageURL[]; -extern const char kSupervisedUserSecondCustodianProfileURL[]; -extern const char kSupervisedUserSharedSettings[]; + extern const char kURLsToRestoreOnStartup[]; extern const char kUserFeedbackAllowed[];
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 37939d89..69dddd0b 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -493,6 +493,7 @@ const char kOsUIHelpAppURL[] = "os://help-app"; const char kOsUIPrintManagementAppURL[] = "os://print-management"; const char kOsUIScanningAppURL[] = "os://scanning"; +const char kOsUIShortcutCustomizationAppURL[] = "os://shortcut-customization"; const char kOsUIVersionURL[] = "os://version"; #endif
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index df0804f62..431e915 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -415,6 +415,7 @@ extern const char kOsUIHelpAppURL[]; extern const char kOsUIPrintManagementAppURL[]; extern const char kOsUIScanningAppURL[]; +extern const char kOsUIShortcutCustomizationAppURL[]; extern const char kOsUIVersionURL[]; #endif
diff --git a/chrome/installer/util/taskbar_util.cc b/chrome/installer/util/taskbar_util.cc index da12e17..c1464a4 100644 --- a/chrome/installer/util/taskbar_util.cc +++ b/chrome/installer/util/taskbar_util.cc
@@ -110,11 +110,9 @@ } // namespace bool CanPinShortcutToTaskbar() { - // "Pin to taskbar" stopped being supported in Windows 10, but WIN10_RS5 has + // "Pin to taskbar" isn't directly supported in Windows 10, but WIN10_RS5 has // some undocumented interfaces to do pinning. - const auto version = base::win::GetVersion(); - return version < base::win::Version::WIN10 || - version >= base::win::Version::WIN10_RS5; + return base::win::GetVersion() >= base::win::Version::WIN10_RS5; } bool PinShortcutToTaskbar(const base::FilePath& shortcut) {
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 5eda0bb..c77cc2a 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -373,16 +373,8 @@ password3_ = kCarolPassword16; alternate_username3_ = kCarolAlternateUsername16; - FormFieldData username_field; - username_field.name = kUsernameName16; - username_field.value = username1_; - fill_data_.username_field = username_field; - - FormFieldData password_field; - password_field.name = kPasswordName16; - password_field.value = password1_; - password_field.form_control_type = "password"; - fill_data_.password_field = password_field; + fill_data_.preferred_login.username = username1_; + fill_data_.preferred_login.password = password1_; PasswordAndMetadata password2; password2.password = password2_; @@ -459,11 +451,11 @@ void UpdateRendererIDs() { if (!username_element_.IsNull()) { - fill_data_.username_field.unique_renderer_id = autofill::FieldRendererId( + fill_data_.username_element_renderer_id = autofill::FieldRendererId( username_element_.UniqueRendererFormControlId()); } ASSERT_FALSE(password_element_.IsNull()); - fill_data_.password_field.unique_renderer_id = autofill::FieldRendererId( + fill_data_.password_element_renderer_id = autofill::FieldRendererId( password_element_.UniqueRendererFormControlId()); WebFormElement form = password_element_.Form(); fill_data_.form_renderer_id = @@ -490,7 +482,7 @@ EXPECT_FALSE(element.IsNull()); username_element_ = element.To<WebInputElement>(); EXPECT_FALSE(username_element_.IsNull()); - fill_data_.username_field.unique_renderer_id = autofill::FieldRendererId( + fill_data_.username_element_renderer_id = autofill::FieldRendererId( username_element_.UniqueRendererFormControlId()); } @@ -815,11 +807,6 @@ ->DidFinishSameDocumentNavigation(); } - void ClearField(FormFieldData* field) { - field->unique_renderer_id = autofill::FieldRendererId(); - field->value.clear(); - } - FakeMojoPasswordManagerDriver fake_driver_; testing::NiceMock<FakePasswordGenerationDriver> fake_pw_client_; @@ -981,8 +968,8 @@ ASSERT_FALSE(element.IsNull()); username_element_ = element.To<WebInputElement>(); - fill_data_.username_field.unique_renderer_id = autofill::FieldRendererId(); - fill_data_.password_field.unique_renderer_id = autofill::FieldRendererId(); + fill_data_.username_element_renderer_id = autofill::FieldRendererId(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); WebFormElement form_element = document.GetElementById("LoginTestForm").To<WebFormElement>(); @@ -1984,8 +1971,8 @@ ASSERT_FALSE(element.IsNull()); username_element_ = element.To<WebInputElement>(); - fill_data_.username_field.unique_renderer_id = autofill::FieldRendererId(); - fill_data_.password_field.unique_renderer_id = autofill::FieldRendererId(); + fill_data_.username_element_renderer_id = autofill::FieldRendererId(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); WebFormElement form_element = document.GetElementById("LoginTestForm").To<WebFormElement>(); @@ -2652,7 +2639,8 @@ // Load a form with no username and update test data. LoadHTML(kVisibleFormWithNoUsernameHTML); UpdateOnlyPasswordElement(); - fill_data_.username_field = FormFieldData(); + fill_data_.preferred_login.username.clear(); + fill_data_.username_element_renderer_id = FieldRendererId(); UpdateUrlForHTML(kVisibleFormWithNoUsernameHTML); fill_data_.additional_logins.clear(); @@ -2679,7 +2667,8 @@ // Load a form with no username and update test data. LoadHTML(kVisibleFormWithNoUsernameHTML); UpdateOnlyPasswordElement(); - fill_data_.username_field = FormFieldData(); + fill_data_.preferred_login.username.clear(); + fill_data_.username_element_renderer_id = FieldRendererId(); UpdateUrlForHTML(kVisibleFormWithNoUsernameHTML); fill_data_.additional_logins.clear(); @@ -2706,7 +2695,8 @@ // Load a form with no username and update test data. LoadHTML(kVisibleFormWithNoUsernameHTML); UpdateOnlyPasswordElement(); - fill_data_.username_field = FormFieldData(); + fill_data_.preferred_login.username.clear(); + fill_data_.username_element_renderer_id = FieldRendererId(); UpdateUrlForHTML(kVisibleFormWithNoUsernameHTML); fill_data_.additional_logins.clear(); @@ -2870,8 +2860,8 @@ // the password manager didn't detect a username field so it will try to // show UI when the password field is focused. fill_data_.wait_for_username = true; - fill_data_.username_field = FormFieldData(); - fill_data_.password_field.name = u"new_password"; + fill_data_.preferred_login.username.clear(); + fill_data_.username_element_renderer_id = FieldRendererId(); UpdateUrlForHTML(kSignupFormHTML); SimulateOnFillPasswordForm(fill_data_); @@ -2960,7 +2950,8 @@ // Tests that only the password field is autocompleted when the browser sends // back data with only one credentials and empty username. TEST_F(PasswordAutofillAgentTest, NotAutofillNoUsername) { - ClearField(&fill_data_.username_field); + fill_data_.preferred_login.username.clear(); + fill_data_.username_element_renderer_id = autofill::FieldRendererId(); fill_data_.additional_logins.clear(); SimulateOnFillPasswordForm(fill_data_); @@ -2971,7 +2962,7 @@ // the empty username. TEST_F(PasswordAutofillAgentTest, AutofillNoUsernameWhenOtherCredentialsStored) { - fill_data_.username_field.value.clear(); + fill_data_.preferred_login.username.clear(); ASSERT_FALSE(fill_data_.additional_logins.empty()); SimulateOnFillPasswordForm(fill_data_); @@ -3276,9 +3267,6 @@ TEST_F(PasswordAutofillAgentTest, SuggestionsOnFormContainingAmbiguousOrEmptyNames) { const char kEmpty[] = ""; - const char16_t kEmpty16[] = u""; - const char16_t kDummyUsernameField[] = u"anonymous_username"; - const char16_t kDummyPasswordField[] = u"anonymous_password"; const char kFormContainsEmptyNamesHTML[] = "<FORM name='WithoutNameIdForm' action='http://www.bidule.com' >" " <INPUT type='text' placeholder='username'/>" @@ -3333,8 +3321,7 @@ const struct { const char* html_form; bool does_trigger_autocomplete_on_fill; - const char16_t* fill_data_username_field_name; - const char16_t* fill_data_password_field_name; + bool has_fillable_username; const char* expected_username_suggestions; const char* expected_password_suggestions; bool expected_is_username_autofillable; @@ -3342,45 +3329,41 @@ } test_cases[] = { // Password form without name or id attributes specified for the input // fields. - {kFormContainsEmptyNamesHTML, true, kDummyUsernameField, - kDummyPasswordField, kAliceUsername, kAlicePassword, true, true}, + {kFormContainsEmptyNamesHTML, true, true, kAliceUsername, kAlicePassword, + true, true}, // Password form with ambiguous name or id attributes specified for the // input fields. - {kFormContainsAmbiguousNamesHTML, true, u"credentials", u"credentials", - kAliceUsername, kAlicePassword, true, true}, + {kFormContainsAmbiguousNamesHTML, true, true, kAliceUsername, + kAlicePassword, true, true}, // Change password form without name or id attributes specified for the // input fields and |autocomplete='current-password'| attribute for old // password field. - {kChangePasswordFormContainsEmptyNamesHTML, true, kDummyUsernameField, - kDummyPasswordField, kAliceUsername, kAlicePassword, true, true}, + {kChangePasswordFormContainsEmptyNamesHTML, true, true, kAliceUsername, + kAlicePassword, true, true}, // Change password form without username field. - {kChangePasswordFormButNoUsername, true, kEmpty16, kDummyPasswordField, - kEmpty, kAlicePassword, false, true}, + {kChangePasswordFormButNoUsername, true, false, kEmpty, kAlicePassword, + false, true}, // Change password form without name or id attributes specified for the // input fields and |autocomplete='new-password'| attribute for new // password fields. This form *do not* trigger |OnFillPasswordForm| from // browser. - {kChangePasswordFormButNoOldPassword, false, kDummyUsernameField, - kDummyPasswordField, kEmpty, kEmpty, false, false}, + {kChangePasswordFormButNoOldPassword, false, true, kEmpty, kEmpty, false, + false}, // Change password form without name or id attributes specified for the // input fields but |autocomplete='current-password'| or // |autocomplete='new-password'| attributes are missing for old and new // password fields respectively. - {kChangePasswordFormButNoAutocompleteAttribute, true, kDummyUsernameField, - kDummyPasswordField, kAliceUsername, kAlicePassword, true, true}, + {kChangePasswordFormButNoAutocompleteAttribute, true, true, + kAliceUsername, kAlicePassword, true, true}, }; for (const auto& test_case : test_cases) { - SCOPED_TRACE(testing::Message() << "html_form: " << test_case.html_form - << ", fill_data_username_field_name: " - << test_case.fill_data_username_field_name - << ", fill_data_password_field_name: " - << test_case.fill_data_password_field_name); + SCOPED_TRACE(testing::Message() << "html_form: " << test_case.html_form); // Load a password form. LoadHTML(test_case.html_form); @@ -3391,9 +3374,7 @@ WebFormElement form_element = forms[0]; std::vector<blink::WebFormControlElement> control_elements = form_util::ExtractAutofillableElementsInForm(form_element); - bool has_fillable_username = - (kEmpty16 != test_case.fill_data_username_field_name); - if (has_fillable_username) { + if (test_case.has_fillable_username) { username_element_ = control_elements[0].To<WebInputElement>(); password_element_ = control_elements[1].To<WebInputElement>(); } else { @@ -3403,8 +3384,12 @@ UpdateUrlForHTML(test_case.html_form); if (test_case.does_trigger_autocomplete_on_fill) { // Prepare |fill_data_| to trigger autocomplete. - fill_data_.username_field.name = test_case.fill_data_username_field_name; - fill_data_.password_field.name = test_case.fill_data_password_field_name; + fill_data_.username_element_renderer_id = + test_case.has_fillable_username + ? FieldRendererId(username_element_.UniqueRendererFormControlId()) + : FieldRendererId(); + fill_data_.password_element_renderer_id = + FieldRendererId(password_element_.UniqueRendererFormControlId()); fill_data_.additional_logins.clear(); ClearUsernameAndPasswordFields(); @@ -3413,7 +3398,7 @@ // autocomplete. SimulateOnFillPasswordForm(fill_data_); - if (has_fillable_username) { + if (test_case.has_fillable_username) { SimulateSuggestionChoice(username_element_); } else { SimulateSuggestionChoice(password_element_); @@ -3450,8 +3435,7 @@ // fields. TEST_F(PasswordAutofillAgentTest, ShowSuggestionForNonUsernameFieldForms) { LoadHTML(kTwoNoUsernameFormsHTML); - fill_data_.username_field.name.clear(); - fill_data_.username_field.value.clear(); + fill_data_.preferred_login.username.clear(); UpdateUrlForHTML(kTwoNoUsernameFormsHTML); SimulateOnFillPasswordForm(fill_data_); @@ -3634,30 +3618,6 @@ } } -// Tests that a suggestion dropdown is shown even if JavaScripts updated field -// names. -TEST_F(PasswordAutofillAgentTest, SuggestWhenJavaScriptUpdatesFieldNames) { - SimulateClosingTouchToFillIfAndroid(kUsernameName); - - // Simulate that JavaScript updated field names. - auto fill_data = fill_data_; - fill_data.username_field.name += u"1"; - fill_data.password_field.name += u"1"; - // Simulate the browser sending back the login info. - SimulateOnFillPasswordForm(fill_data); - - // Call SimulateElementClick() to produce a user gesture on the page so - // autofill will actually fill. - SimulateElementClick(kUsernameName); - EXPECT_CALL(fake_driver_, ShowPasswordSuggestions); - base::RunLoop().RunUntilIdle(); - - // Simulate a user clicking on the password element. This should produce a - // dropdown with suggestion of all available usernames. - autofill_agent_->FormControlElementClicked(password_element_); - CheckSuggestions(u"", true); -} - // Checks that a same-document navigation form submission could have an empty // username. TEST_F(PasswordAutofillAgentTest, @@ -3864,7 +3824,7 @@ CheckTextFieldsSuggestedState(kAliceUsername, true, kAlicePassword, true); // Change fill data - fill_data_.password_field.value = u"a-changed-password"; + fill_data_.preferred_login.password = u"a-changed-password"; // Supply changed fill data password_autofill_agent_->SetPasswordFillData(fill_data_); CheckTextFieldsSuggestedState(kAliceUsername, true, "a-changed-password", @@ -3880,7 +3840,7 @@ base::RunLoop().RunUntilIdle(); // Change fill data - fill_data_.username_field.value = u"a-changed-username"; + fill_data_.preferred_login.username = u"a-changed-username"; password_autofill_agent_->SetPasswordFillData(fill_data_); SimulateElementClick(kPasswordName); @@ -3929,17 +3889,6 @@ CheckFirstFillingResult(FillingResult::kSuccess); } -// Tests that the password form is filled as expected on load even if form/field -// attributes were changed between from load and filling. -TEST_F(PasswordAutofillAgentTest, FillOnLoadFormChanged) { - // Simulate JavaScript changed field names. - fill_data_.username_field.name += u"1"; - fill_data_.password_field.name += u"1"; - - SimulateOnFillPasswordForm(fill_data_); - CheckTextFieldsSuggestedState(kAliceUsername, true, kAlicePassword, true); -} - TEST_F(PasswordAutofillAgentTest, FillOnLoadNoForm) { LoadHTML(kNoFormHTML); UpdateUsernameAndPasswordElements(); @@ -3951,7 +3900,7 @@ TEST_F(PasswordAutofillAgentTest, FillOnLoadNoUsername) { LoadHTML(kTwoNoUsernameFormsHTML); username_element_.Reset(); - fill_data_.username_field.value.clear(); + fill_data_.preferred_login.username.clear(); password_element_ = GetInputElementByID("password2"); UpdateRendererIDs(); SimulateOnFillPasswordForm(fill_data_); @@ -4002,7 +3951,7 @@ password_autofill_agent_->ReadyToCommitNavigation(nullptr); fill_data_.username_may_use_prefilled_placeholder = true; - fill_data_.password_field.value = kBobPassword16; + fill_data_.preferred_login.password = kBobPassword16; SimulateOnFillPasswordForm(fill_data_); CheckTextFieldsStateForElements( @@ -4051,7 +4000,8 @@ // after user gesture. TEST_F(PasswordAutofillAgentTest, FillOnLoadSingleUsername) { // Simulate filling single username by clearing password fill data. - ClearField(&fill_data_.password_field); + fill_data_.preferred_login.password.clear(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); SimulateOnFillPasswordForm(fill_data_); @@ -4069,7 +4019,8 @@ // Tests that |PreviewSuggestion| properly previews the single username. TEST_F(PasswordAutofillAgentTest, SingleUsernamePreviewSuggestion) { - ClearField(&fill_data_.password_field); + fill_data_.preferred_login.password.clear(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); // Simulate the browser sending the login info, but set |wait_for_username| to // prevent the form from being immediately filled. fill_data_.wait_for_username = true; @@ -4091,7 +4042,8 @@ // Tests that |FillSuggestion| properly fills the single username. TEST_F(PasswordAutofillAgentTest, SingleUsernameFillSuggestion) { - ClearField(&fill_data_.password_field); + fill_data_.preferred_login.password.clear(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); // Simulate the browser sending the login info, but set |wait_for_username| // to prevent the form from being immediately filled. fill_data_.wait_for_username = true; @@ -4118,7 +4070,8 @@ // Tests that |ClearPreview| properly clears previewed single username. TEST_F(PasswordAutofillAgentTest, SingleUsernameClearPreview) { - ClearField(&fill_data_.password_field); + fill_data_.preferred_login.password.clear(); + fill_data_.password_element_renderer_id = autofill::FieldRendererId(); ResetFieldState(&username_element_, "ali", WebAutofillState::kPreviewed); username_element_.SetSelectionRange(3, 3);
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 6c9d906d..eab276d 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -180,7 +180,6 @@ #endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) #if BUILDFLAG(IS_WIN) -#include "base/win/windows_version.h" #include "chrome/renderer/render_frame_font_family_accessor.h" #endif @@ -328,12 +327,6 @@ // made available in other clients of content/ that do not have a Web Share // Mojo implementation (e.g. WebView). void MaybeEnableWebShare() { -#if BUILDFLAG(IS_WIN) - if (base::win::GetVersion() < base::win::Version::WIN10) { - // Web Share API is not functional for non-UWP apps prior to Windows 10. - return; - } -#endif #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) if (base::FeatureList::IsEnabled(features::kWebShare)) #endif
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc index 56533ee5..7711832 100644 --- a/chrome/renderer/media/chrome_key_systems.cc +++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -25,6 +25,7 @@ #include "media/base/eme_constants.h" #include "media/base/key_system_info.h" #include "media/cdm/cdm_capability.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "third_party/widevine/cdm/buildflags.h" @@ -403,8 +404,6 @@ } #endif // BUILDFLAG(ENABLE_WIDEVINE) -const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; - void AddExternalClearKey( const media::mojom::KeySystemCapabilityPtr& /*capability*/, KeySystemInfos* key_systems) { @@ -433,7 +432,7 @@ } #endif // BUILDFLAG(ENABLE_WIDEVINE) - if (key_system == kExternalClearKeyKeySystem) { + if (key_system == media::kExternalClearKeyKeySystem) { AddExternalClearKey(capability, &key_systems); continue; }
diff --git a/chrome/services/keymanagement/public/mojom/OWNERS b/chrome/services/keymanagement/public/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/chrome/services/keymanagement/public/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/keymint/public/mojom/OWNERS b/chrome/services/keymint/public/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/chrome/services/keymint/public/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/sharing/nearby/platform/ble_medium.cc b/chrome/services/sharing/nearby/platform/ble_medium.cc index 781051e87..e4c4102 100644 --- a/chrome/services/sharing/nearby/platform/ble_medium.cc +++ b/chrome/services/sharing/nearby/platform/ble_medium.cc
@@ -168,7 +168,7 @@ // A different DiscoveredPeripheralCallback is being passed on each call, so // each must be captured and associated with its service UUID. discovered_peripheral_callbacks_map_.insert( - {service_uuid, discovered_peripheral_callback}); + {service_uuid, std::move(discovered_peripheral_callback)}); discovery_service_id_to_fast_advertisement_service_uuid_map_.insert( {service_id, service_uuid});
diff --git a/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc b/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc index 6d6f451..e072d69 100644 --- a/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc +++ b/chrome/services/sharing/nearby/platform/ble_medium_unittest.cc
@@ -81,9 +81,19 @@ EXPECT_EQ(!scanning_service_ids_set_.empty(), fake_adapter_->IsDiscoverySessionActive()); scanning_service_ids_set_.insert(service_id); - EXPECT_TRUE(ble_medium_->StartScanning(service_id, - fast_advertisement_service_uuid, - discovered_peripheral_callback_)); + EXPECT_TRUE(ble_medium_->StartScanning( + service_id, fast_advertisement_service_uuid, + {.peripheral_discovered_cb = + [this](api::BlePeripheral& peripheral, + const std::string& service_id, bool fast_advertisement) { + EXPECT_TRUE(fast_advertisement); + OnPeripheralDiscovered(peripheral, service_id); + }, + .peripheral_lost_cb = + [this](api::BlePeripheral& peripheral, + const std::string& service_id) { + OnPeripheralLost(peripheral, service_id); + }})); EXPECT_TRUE(fake_adapter_->IsDiscoverySessionActive()); }
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc index 16e61bf..fed4daba 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc +++ b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium_unittest.cc
@@ -75,7 +75,8 @@ protected: void StartDiscovery() { EXPECT_FALSE(fake_adapter_->IsDiscoverySessionActive()); - EXPECT_TRUE(bluetooth_classic_medium_->StartDiscovery(discovery_callback_)); + EXPECT_TRUE(bluetooth_classic_medium_->StartDiscovery( + std::move(discovery_callback_))); EXPECT_TRUE(fake_adapter_->IsDiscoverySessionActive()); } @@ -137,21 +138,11 @@ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; }; -TEST_F(BluetoothClassicMediumTest, TestDiscovery_StartDiscoveryIsIdempotent) { - EXPECT_FALSE(fake_adapter_->IsDiscoverySessionActive()); - EXPECT_TRUE(bluetooth_classic_medium_->StartDiscovery(discovery_callback_)); - EXPECT_TRUE(fake_adapter_->IsDiscoverySessionActive()); - - EXPECT_TRUE(bluetooth_classic_medium_->StartDiscovery(discovery_callback_)); - EXPECT_TRUE(fake_adapter_->IsDiscoverySessionActive()); - - StopDiscovery(); -} - TEST_F(BluetoothClassicMediumTest, TestDiscovery_StartDiscoveryError) { fake_adapter_->SetShouldDiscoverySucceed(false); EXPECT_FALSE(fake_adapter_->IsDiscoverySessionActive()); - EXPECT_FALSE(bluetooth_classic_medium_->StartDiscovery(discovery_callback_)); + EXPECT_FALSE(bluetooth_classic_medium_->StartDiscovery( + std::move(discovery_callback_))); EXPECT_FALSE(fake_adapter_->IsDiscoverySessionActive()); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 18ca933..e4e7222 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -102,55 +102,6 @@ } } -if (is_fuchsia) { - # TODO(crbug.com/931218): Ninja cannot handle certain characters appearing - # in filenames in depfiles, so temporarily exclude affected files. - fuchsia_package_exclusions = [ "chrome/test/data/ie@cookie[[]1[]].txt" ] - - # The chrome/test/data directory is a bit of a mess. - # There are a lot of files that are included in the data list which serve - # no productive purpose. - # - # Until chrome/test/data can be refactored into finer-grained source lists - # which can be added or redacted, this excises major contributors to - # test archive size (which slows down test runtime on Fuchsia.) - fuchsia_package_exclusions += [ - # Typescript sources. Given that they require compilation to be usable, - # there is no point in deploying them alongside tests. - "*.ts", - - # Markdown documentation. - "*.md", - - # Test data for unsupported features. - "chrome/test/data/android/*", - "chrome/test/data/chromeos/*", - "chrome/test/data/gpu/*", - "chrome/test/data/import/firefox/*", - "chrome/test/data/import/safari/*", - "chrome/test/data/nacl/*", - "chrome/test/data/pdf/*", - "chrome/test/data/perf/*", - "chrome/test/data/xr/*", - - # Not used by `unit_tests` or `browser_tests`. - "chrome/test/data/dromaeo/*", - "chrome/test/data/optimization_guide/*", - "chrome/test/data/page_cycler/*", - "chrome/test/data/sunspider/*", - "chrome/test/data/third_party/kraken/*", - "content/test/data/gpu/*", - - # WebUI test assets are accessed from PAK files and should not be used - # as standalone files. - "chrome/test/data/webui/*", - ] - - if (enable_library_cdms) { - fuchsia_package_exclusions += [ "lib.unstripped/libclearkeycdm.so" ] - } -} - # Use a static library here because many test binaries depend on this but don't # require many files from it. This makes linking more efficient. static_library("test_support") { @@ -345,6 +296,7 @@ "//components/subresource_filter/content/browser", "//components/subresource_filter/content/browser:test_support", "//components/subresource_filter/core/common", + "//components/supervised_user/core/common", "//components/sync:test_support", "//components/sync_preferences", "//components/sync_preferences:test_support", @@ -2291,6 +2243,7 @@ "../browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc", "../browser/ui/views/web_apps/web_app_detailed_install_dialog_browsertest.cc", "../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc", + "../browser/ui/views/web_apps/web_ui_web_app_browsertest.cc", "../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc", "../browser/ui/views/webid/fake_delegate.cc", "../browser/ui/views/webid/fake_delegate.h", @@ -2428,14 +2381,16 @@ "../browser/safe_browsing/download_protection/deep_scanning_browsertest.cc", # Lacros does not seem to have any actual WebView-based UI to test. - "../browser/accessibility/live_caption_unavailability_notifier_browsertest.cc", "../browser/accessibility/live_translate_controller_browsertest.cc", "../browser/ui/webui/webui_webview_browsertest.cc", - # These tests also run on Lacros, as part of - # lacros_chrome_browsertests_run_in_series below. + # Lacros shouldn't be rendering captions at all; this should be + # delegated to Ash. "../browser/accessibility/live_caption_controller_browsertest.cc", "../browser/accessibility/live_caption_speech_recognition_host_browsertest.cc", + + # These tests also run on Lacros, as part of + # lacros_chrome_browsertests_run_in_series below. "../browser/media/webrtc/capture_handle_browsertest.cc", "../browser/media/webrtc/conditional_focus_browsertest.cc", "../browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc", @@ -2453,6 +2408,7 @@ if (is_win) { sources += [ + "../browser/accessibility/live_caption_unavailability_notifier_browsertest.cc", "../browser/ui/views/web_apps/web_app_integration_browsertest_win.cc", ] } @@ -3056,6 +3012,7 @@ "../browser/extensions/content_verifier_browsertest.cc", "../browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc", "../browser/extensions/content_verifier_test_utils.cc", + "../browser/extensions/content_verifier_test_utils.h", "../browser/extensions/corb_and_cors_extension_browsertest.cc", "../browser/extensions/cross_origin_isolation_browsertest.cc", "../browser/extensions/cross_origin_xhr_apitest.cc", @@ -3990,6 +3947,7 @@ "../browser/ash/shutdown_policy_browsertest.cc", "../browser/ash/startup_settings_cache_browsertest.cc", "../browser/ash/system/device_disabling_browsertest.cc", + "../browser/ash/system/timezone_resolver_manager_browsertest.cc", "../browser/ash/system/tray_accessibility_browsertest.cc", "../browser/ash/video_conference/video_conference_app_service_client_browsertest.cc", "../browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc", @@ -4624,7 +4582,6 @@ use_test_server = true test_runner_shard = "//build/config/fuchsia/test/elf_test_ambient_exec_runner.shard.test-cml" - excluded_paths = fuchsia_package_exclusions additional_manifest_fragments = [ "//build/config/fuchsia/test/audio_output.shard.test-cml", "//build/config/fuchsia/test/fonts.shard.test-cml", @@ -4633,6 +4590,18 @@ "//third_party/fuchsia-sdk/sdk/pkg/vulkan/client.shard.cml", ] + # TODO(crbug.com/931218): Ninja cannot handle certain characters appearing + # in filenames in depfiles, so temporarily exclude affected files. + excluded_files = [ + "chrome/test/data/ie@cookie[1].txt", + "chrome/test/data/android/download/[large]wallpaper.dm", + "chrome/test/data/perf/frame_rate/content/googleblog/images/bse%e2%80%99s+solar+energy+development+center..jpg", + ] + + if (enable_library_cdms) { + excluded_files += [ "lib.unstripped/libclearkeycdm.so" ] + } + # Tests depend on having a Python interpreter present on-device. # TODO(crbug.com/1292144): Determine whether a solution can be devised # for Fuchsia. @@ -4694,6 +4663,7 @@ "../browser/ui/views/web_apps/protocol_handler_launch_dialog_browsertest.cc", "../browser/ui/views/web_apps/web_app_integration_browsertest.cc", "../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc", + "../browser/ui/views/web_apps/web_ui_web_app_browsertest.cc", "../browser/web_applications/alternative_error_page_override_info_browsertest.cc", ] if (enable_extensions) { @@ -4775,6 +4745,7 @@ # dlp_content_manager_lacros_browsertest.cc should become a unit test. "../browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc", "../browser/extensions/api/shared_storage/shared_storage_private_apitest.cc", + "../browser/lacros/desk_template_client_lacros_browsertest.cc", "../browser/lacros/device_attributes_lacros_browsertest.cc", # download_controller_client_lacros_browsertest.cc should become a unit @@ -4837,8 +4808,6 @@ ] sources = [ - "../browser/accessibility/live_caption_controller_browsertest.cc", - "../browser/accessibility/live_caption_speech_recognition_host_browsertest.cc", "../browser/apps/intent_helper/supported_links_infobar_delegate_browsertest.cc", "../browser/chromeos/extensions/login_screen/login_screen_storage/login_screen_storage_apitest.cc", "../browser/chromeos/extensions/wallpaper_apitest.cc", @@ -5354,6 +5323,7 @@ "../browser/download/offline_item_utils_unittest.cc", "../browser/engagement/important_sites_util_unittest.cc", "../browser/engagement/site_engagement_service_unittest.cc", + "../browser/enterprise/connectors/interstitials/enterprise_page_unittest.cc", "../browser/enterprise/identifiers/profile_id_service_factory_unittest.cc", "../browser/enterprise/reporting/browser_report_generator_unittest.cc", "../browser/enterprise/reporting/policy_info_unittest.cc", @@ -6368,8 +6338,14 @@ deps += [ "//chrome/browser/paint_preview:services" ] } + # TODO(crbug.com/931218): Ninja cannot handle certain characters appearing + # in filenames in depfiles, so temporarily exclude affected files. if (is_fuchsia) { - excluded_paths = fuchsia_package_exclusions + excluded_files = [ + "chrome/test/data/ie@cookie[1].txt", + "chrome/test/data/android/download/[large]wallpaper.dm", + "chrome/test/data/perf/frame_rate/content/googleblog/images/bse%e2%80%99s+solar+energy+development+center..jpg", + ] } if (is_win || is_chromeos || is_mac) { @@ -6824,6 +6800,7 @@ "../browser/ui/autofill/payments/local_card_migration_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/payments/offer_notification_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc", + "../browser/ui/autofill/payments/save_iban_bubble_controller_impl_unittest.cc", "../browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc", "../browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc", "../browser/ui/bookmarks/bookmark_drag_drop_unittest.cc", @@ -8901,10 +8878,10 @@ "../browser/supervised_user/kids_management_url_checker_client_unittest.cc", "../browser/supervised_user/parental_control_metrics_unittest.cc", "../browser/supervised_user/supervised_user_metrics_service_unittest.cc", - "../browser/supervised_user/supervised_user_model_type_controller_unittest.cc", "../browser/supervised_user/supervised_user_pref_store_unittest.cc", "../browser/supervised_user/supervised_user_service_unittest.cc", "../browser/supervised_user/supervised_user_settings_service_unittest.cc", + "../browser/supervised_user/supervised_user_sync_model_type_controller_unittest.cc", "../browser/supervised_user/supervised_user_url_filter_unittest.cc", "../browser/supervised_user/web_approvals_manager_unittest.cc", ] @@ -9426,8 +9403,8 @@ "../browser/ui/test/test_browser_dialog.cc", "../browser/ui/test/test_browser_dialog.h", "../browser/ui/thumbnails/thumbnail_tab_helper_interactive_uitest.cc", - "../browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc", "../browser/ui/views/autofill/payments/local_card_migration_uitest.cc", + "../browser/ui/views/autofill/payments/save_iban_bubble_view_uitest.cc", "../browser/ui/views/collected_cookies_view_interactive_uitest.cc", "../browser/ui/views/content_test_utils.cc", "../browser/ui/views/content_test_utils.h", @@ -9572,6 +9549,7 @@ "//ui/events:events_interactive_ui_tests", "//ui/events:gesture_detection", "//ui/events:test_support", + "//ui/strings:ui_strings_grit", "//ui/views", "//ui/web_dialogs:test_support", ] @@ -10034,6 +10012,10 @@ ] } + if (!is_chromeos_lacros) { + sources += [ "../browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc" ] + } + if (is_chromeos_lacros && !is_chromeos_device) { # For support version skew testing. data_deps += [ "//build:version_metadata" ] @@ -10518,6 +10500,7 @@ "//base", "//base/test:test_support_perf", "//media:media_buildflags", + "//media/cdm:clear_key_cdm_common", "//testing/gtest", "//testing/perf", "//third_party/widevine/cdm:buildflags",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS index f5f06296..25500c57 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS
@@ -68,6 +68,7 @@ "+components/storage_monitor", "+components/subresource_filter/content/browser", "+components/federated_learning", + "+components/supervised_user/core/common", "+components/sync/test", "+components/sync_preferences", "+components/unified_consent",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/OWNERS b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/OWNERS index 7b6517c..3f3a939 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/OWNERS +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/webapps/OWNERS
@@ -1 +1 @@ -file://chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/chrome/test/base/scoped_bundle_swizzler_mac.mm b/chrome/test/base/scoped_bundle_swizzler_mac.mm index fce6ee6..f9a6851 100644 --- a/chrome/test/base/scoped_bundle_swizzler_mac.mm +++ b/chrome/test/base/scoped_bundle_swizzler_mac.mm
@@ -25,6 +25,7 @@ @implementation TestBundle { base::scoped_nsobject<NSBundle> _mainBundle; + base::scoped_nsobject<NSString> _bundleID; } + (NSBundle*)mainBundle { @@ -33,11 +34,13 @@ - (instancetype)initWithRealBundle:(NSBundle*)bundle { _mainBundle.reset([bundle retain]); + _bundleID.reset(base::SysUTF8ToNSString(base::mac::BaseBundleID()), + base::scoped_policy::RETAIN); return self; } - (NSString*)bundleIdentifier { - return base::SysUTF8ToNSString(base::mac::BaseBundleID()); + return _bundleID.get(); } - (void)forwardInvocation:(NSInvocation*)invocation {
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc index 78684f63..d2cf8b3 100644 --- a/chrome/test/base/test_browser_window.cc +++ b/chrome/test/base/test_browser_window.cc
@@ -293,6 +293,9 @@ views::Button* TestBrowserWindow::GetSharingHubIconButton() { return nullptr; } +void TestBrowserWindow::ToggleMultitaskMenu() const { + return; +} #else sharing_hub::SharingHubBubbleView* TestBrowserWindow::ShowSharingHubBubble( share::ShareAttempt attempt) {
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index e2a2b46..dd90fb3 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h
@@ -83,7 +83,6 @@ void SetTopControlsGestureScrollInProgress(bool in_progress) override; StatusBubble* GetStatusBubble() override; void UpdateTitleBar() override {} - void UpdateFrameColor() override {} void BookmarkBarStateChanged( BookmarkBar::AnimateChangeType change_type) override {} void UpdateDevTools() override {} @@ -172,6 +171,7 @@ bool show_signin_button) override; #if BUILDFLAG(IS_CHROMEOS) views::Button* GetSharingHubIconButton() override; + void ToggleMultitaskMenu() const override; #else sharing_hub::SharingHubBubbleView* ShowSharingHubBubble( share::ShareAttempt attempt) override;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index baf3208..65f7bd9 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -136,9 +136,9 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif using base::Time;
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc index 48ed129..09b483f 100644 --- a/chrome/test/base/testing_profile_manager.cc +++ b/chrome/test/base/testing_profile_manager.cc
@@ -40,7 +40,7 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_constants.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" #endif const char kGuestProfileName[] = "Guest";
diff --git a/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback.html b/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback.html new file mode 100644 index 0000000..389b1929 --- /dev/null +++ b/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback.html
@@ -0,0 +1,12 @@ +<head> + <meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> + <script> + function openApp() { + location.href = 'PARAM_SELF_URL'; + }; + </script> +</head> +<body style='height:10000px;' onclick='openApp();'> + Click page to open App!! +</body>
diff --git a/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback_parent.html b/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback_parent.html new file mode 100644 index 0000000..bb7d53e --- /dev/null +++ b/chrome/test/data/android/url_overriding/navigation_to_self_with_fallback_parent.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/> +<body style='height:10000px'> +<p>Hello World</p> +<iframe src="navigation_to_self_with_fallback.html?replace_text=PARAM_BASE64_NAME:PARAM_BASE64_VALUE" + width="100%" height="99%"></iframe> +</body>
diff --git a/chrome/test/data/notifications/platform_notification_service.html b/chrome/test/data/notifications/platform_notification_service.html index 6115221..533a5757 100644 --- a/chrome/test/data/notifications/platform_notification_service.html +++ b/chrome/test/data/notifications/platform_notification_service.html
@@ -150,6 +150,28 @@ }); } + // Displays a persistent notification with scenario set to incoming-call. + function DisplayIncomingCallNotification() { + DisplayPersistentNotification('Title', { + body: 'Contents', + image: 'icon.png', + scenario: 'incoming-call', + }); + } + + // Displays a persistent notification with scenario set to incoming-call + // with an action button. + function DisplayIncomingCallNotificationWithActionButton() { + DisplayPersistentNotification('Title', { + body: 'Contents', + image: 'icon.png', + scenario: 'incoming-call', + actions: [ + { action: 'actionId1', title: 'actionTitle1', icon: 'icon.png' } + ] + }); + } + // Gets a comma separated list of currently displayed notification titles function GetDisplayedNotifications() { GetActivatedServiceWorker('platform_notification_service.js',
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 1aae00d..6e832b57 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -1,5 +1,5 @@ { - "-- Instructions --": "See https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/enterprise/policy_pref_mapping_test.md (This file is interpreted by //chrome/browser/policy/policy_prefs_browsertest.cc)", + "-- Instructions --": "See https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/enterprise/policy_pref_mapping_test.md (This file is interpreted by //chrome/browser/policy/policy_prefs_browsertest.cc / browser_test --gtest_filter=*PolicyPrefsTest*)", "OverrideSecurityRestrictionsOnInsecureOrigin": { "os": [ "win", @@ -4082,7 +4082,7 @@ } }, { - "note": "DeveloperToolsAvailability overwrites DeveloperToolsDisabled if both are set", + "note": "DeveloperToolsAvailability (2) overwrites DeveloperToolsDisabled (false->1) if both are set", "policies": { "DeveloperToolsDisabled": false, "DeveloperToolsAvailability": 2 @@ -4092,6 +4092,18 @@ "value": 2 } } + }, + { + "note": "DeveloperToolsAvailability (1) overwrites DeveloperToolsDisabled (true->2) both are set", + "policies": { + "DeveloperToolsDisabled": true, + "DeveloperToolsAvailability": 1 + }, + "prefs": { + "devtools.availability": { + "value": 1 + } + } } ] },
diff --git a/chrome/test/data/updater/updater_qualification_app.crx b/chrome/test/data/updater/updater_qualification_app.crx new file mode 100644 index 0000000..e36c7c4 --- /dev/null +++ b/chrome/test/data/updater/updater_qualification_app.crx Binary files differ
diff --git a/chrome/test/data/webrtc/peerconnection_getstats.js b/chrome/test/data/webrtc/peerconnection_getstats.js index 7a6e66fb..7dbee00 100644 --- a/chrome/test/data/webrtc/peerconnection_getstats.js +++ b/chrome/test/data/webrtc/peerconnection_getstats.js
@@ -501,13 +501,14 @@ * @private */ let kRTCAudioPlayoutStats = new RTCStats(null, { + kind: 'string', synthesizedSamplesDuration: 'number', synthesizedSamplesEvents: 'number', totalSamplesDuration: 'number', totalPlayoutDelay: 'number', totalSamplesCount: 'number', }); -addRTCStatsToAllowlist(Presence.OPTIONAL, 'audio-playout', kRTCAudioPlayoutStats); +addRTCStatsToAllowlist(Presence.OPTIONAL, 'media-playout', kRTCAudioPlayoutStats); // Public interface to tests. These are expected to be called with // ExecuteJavascript invocations from the browser tests and will return answers
diff --git a/chrome/test/data/webui/app_home/app_list_test.ts b/chrome/test/data/webui/app_home/app_list_test.ts index 6fb2b80..79989a21 100644 --- a/chrome/test/data/webui/app_home/app_list_test.ts +++ b/chrome/test/data/webui/app_home/app_list_test.ts
@@ -40,7 +40,7 @@ mayShowRunOnOsLoginMode: true, mayToggleRunOnOsLoginMode: false, runOnOsLoginMode: RunOnOsLoginMode.kNotRun, - mayShowOpenInWindow: true, + isLocallyInstalled: true, openInWindow: false, }, { @@ -54,7 +54,7 @@ mayShowRunOnOsLoginMode: false, mayToggleRunOnOsLoginMode: false, runOnOsLoginMode: RunOnOsLoginMode.kNotRun, - mayShowOpenInWindow: false, + isLocallyInstalled: false, openInWindow: false, }, ], @@ -70,7 +70,7 @@ mayShowRunOnOsLoginMode: false, mayToggleRunOnOsLoginMode: false, runOnOsLoginMode: RunOnOsLoginMode.kNotRun, - mayShowOpenInWindow: false, + isLocallyInstalled: true, openInWindow: false, }; testBrowserProxy = new TestAppHomeBrowserProxy(apps); @@ -104,7 +104,7 @@ assertEquals( appItems[1]!.shadowRoot! .querySelector<HTMLImageElement>('.icon-container img')!.src, - apps.appList[1]!.iconUrl.url); + apps.appList[1]!.iconUrl.url + '?grayscale=true'); }); test('add/remove app', async () => { @@ -131,7 +131,7 @@ testAppInfo.name)); }); - test('context menu', () => { + test('context menu locally installed', () => { // Get the first app item. const appItem = appListElement.shadowRoot!.querySelector('app-item'); assertTrue(!!appItem); @@ -150,7 +150,7 @@ const openInWindow = contextMenu.querySelector<HTMLElement>('#open-in-window'); assertTrue(!!openInWindow); - assertEquals(openInWindow.hidden, !appInfo.mayShowOpenInWindow); + assertEquals(openInWindow.hidden, !appInfo.isLocallyInstalled); assertEquals( openInWindow.querySelector('cr-checkbox')!.checked, appInfo.openInWindow); @@ -170,6 +170,42 @@ assertTrue(!!contextMenu.querySelector('#create-shortcut')); assertTrue(!!contextMenu.querySelector('#uninstall')); assertTrue(!!contextMenu.querySelector('#app-settings')); + assertTrue(!!contextMenu.querySelector('#install-locally')); + + assertFalse( + contextMenu.querySelector<HTMLElement>('#create-shortcut')!.hidden); + assertFalse(contextMenu.querySelector<HTMLElement>('#uninstall')!.hidden); + assertFalse( + contextMenu.querySelector<HTMLElement>('#app-settings')!.hidden); + assertTrue( + contextMenu.querySelector<HTMLElement>('#install-locally')!.hidden); + }); + + test('context menu not locally installed', () => { + // Get the second app item that's not locally installed. + const appList = appListElement.shadowRoot!.querySelectorAll('app-item'); + assertEquals(appList.length, 2); + const appItem = appList[1]; + assertTrue(!!appItem); + + const contextMenu = + appListElement.shadowRoot!.querySelector('cr-action-menu'); + assertTrue(!!contextMenu); + assertTrue(contextMenu.hidden); + + appItem.dispatchEvent(new CustomEvent('contextmenu')); + assertFalse(contextMenu.hidden); + + assertTrue( + contextMenu.querySelector<HTMLElement>('#open-in-window')!.hidden); + assertTrue( + contextMenu.querySelector<HTMLElement>('#launch-on-startup')!.hidden); + assertTrue( + contextMenu.querySelector<HTMLElement>('#create-shortcut')!.hidden); + assertTrue(contextMenu.querySelector<HTMLElement>('#app-settings')!.hidden); + assertFalse(contextMenu.querySelector<HTMLElement>('#uninstall')!.hidden); + assertFalse( + contextMenu.querySelector<HTMLElement>('#install-locally')!.hidden); }); test('toggle open in window', () => { @@ -239,7 +275,7 @@ assertEquals(appInfo.runOnOsLoginMode, RunOnOsLoginMode.kWindowed); }); - test('click uninstall', () => { + test('click uninstall', async () => { const appItem = appListElement.shadowRoot!.querySelector('app-item'); assertTrue(!!appItem); @@ -250,11 +286,11 @@ assertTrue(!!uninstall); uninstall.click(); - testBrowserProxy.fakeHandler.whenCalled('uninstallApp') + await testBrowserProxy.fakeHandler.whenCalled('uninstallApp') .then((appId: string) => assertEquals(appId, apps.appList[0]!.id)); }); - test('click app settings', () => { + test('click app settings', async () => { const appItem = appListElement.shadowRoot!.querySelector('app-item'); assertTrue(!!appItem); @@ -265,11 +301,11 @@ assertTrue(!!appSettings); appSettings.click(); - testBrowserProxy.fakeHandler.whenCalled('showAppSettings') + await testBrowserProxy.fakeHandler.whenCalled('showAppSettings') .then((appId: string) => assertEquals(appId, apps.appList[0]!.id)); }); - test('click create shortcut', () => { + test('click create shortcut', async () => { const appItem = appListElement.shadowRoot!.querySelector('app-item'); assertTrue(!!appItem); @@ -281,8 +317,60 @@ assertTrue(!!createShortcut); createShortcut.click(); - testBrowserProxy.fakeHandler.whenCalled('createAppShortcut') + await testBrowserProxy.fakeHandler.whenCalled('createAppShortcut') .then((appId: string) => assertEquals(appId, apps.appList[0]!.id)); }); + test('click install locally', async () => { + const appItem = appListElement.shadowRoot!.querySelectorAll('app-item')[1]; + assertTrue(!!appItem); + + assertEquals( + appItem.shadowRoot! + .querySelector<HTMLImageElement>('.icon-container img')!.src, + apps.appList[1]!.iconUrl.url + '?grayscale=true'); + + appItem.dispatchEvent(new CustomEvent('contextmenu')); + + const contextMenu = + appListElement.shadowRoot!.querySelector('cr-action-menu'); + assertTrue(!!contextMenu); + + assertTrue( + contextMenu.querySelector<HTMLElement>('#open-in-window')!.hidden); + assertTrue( + contextMenu.querySelector<HTMLElement>('#create-shortcut')!.hidden); + assertTrue(contextMenu.querySelector<HTMLElement>('#app-settings')!.hidden); + assertFalse(contextMenu.querySelector<HTMLElement>('#uninstall')!.hidden); + + const installLocally = + appListElement.shadowRoot!.querySelector<HTMLElement>( + '#install-locally'); + assertTrue(!!installLocally); + assertFalse(installLocally.hidden); + + installLocally.click(); + await testBrowserProxy.fakeHandler.whenCalled('installAppLocally') + .then((appId: string) => assertEquals(appId, apps.appList[1]!.id)); + + await callbackRouterRemote.$.flushForTesting(); + flush(); + assertEquals( + appItem.shadowRoot! + .querySelector<HTMLImageElement>('.icon-container img')!.src, + apps.appList[1]!.iconUrl.url); + + appItem.dispatchEvent(new CustomEvent('contextmenu')); + + assertFalse( + contextMenu.querySelector<HTMLElement>('#open-in-window')!.hidden); + assertFalse( + contextMenu.querySelector<HTMLElement>('#create-shortcut')!.hidden); + assertFalse( + contextMenu.querySelector<HTMLElement>('#app-settings')!.hidden); + assertFalse(contextMenu.querySelector<HTMLElement>('#uninstall')!.hidden); + assertTrue( + contextMenu.querySelector<HTMLElement>('#install-locally')!.hidden); + }); + });
diff --git a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts index 6909820b..9b4226c 100644 --- a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts +++ b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts
@@ -16,7 +16,12 @@ private callbackRouterRemote_: PageRemote; constructor(apps: AppList, callbackRouterRemote: PageRemote) { - super(['uninstallApp', 'showAppSettings', 'createAppShortcut']); + super([ + 'uninstallApp', + 'showAppSettings', + 'createAppShortcut', + 'installAppLocally', + ]); this.apps_ = apps; this.callbackRouterRemote_ = callbackRouterRemote; } @@ -52,7 +57,16 @@ launchDeprecatedAppDialog() {} - installAppLocally(_appId: string) {} + installAppLocally(appId: string) { + this.methodCalled('installAppLocally', appId); + for (const app of this.apps_.appList) { + if (app.id === appId) { + app.isLocallyInstalled = true; + this.callbackRouterRemote_.addApp(app); + break; + } + } + } setUserDisplayMode(appId: string, userDisplayMode: UserDisplayMode) { for (const app of this.apps_.appList) {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts index b9cfb33..edd4d40 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts
@@ -57,6 +57,7 @@ url: createSvgDataUrl('svg-0'), }, timestamp: {internalValue: BigInt(`13318040939308000`)}, + isShared: false, }, { id: '0ec40478-9712-42e1-b5bf-3e75870ca042', @@ -66,6 +67,7 @@ url: createSvgDataUrl('svg-1'), }, timestamp: {internalValue: BigInt(`13318040939307000`)}, + isShared: false, }, { id: '0a268a37-877a-4936-81d4-38cc84b0f596', @@ -75,6 +77,7 @@ url: createSvgDataUrl('svg-2'), }, timestamp: {internalValue: BigInt(`13318040939306000`)}, + isShared: false, }, ]; @@ -178,6 +181,7 @@ photoCount: 1, preview: {url: createSvgDataUrl(`svg-${i}`)}, timestamp: {internalValue: BigInt(`${photosCount - i}`)}, + isShared: false, })); // Initialize |googlePhotosAlbumsElement|. @@ -260,6 +264,7 @@ photoCount: 1, preview: {url: `url-${nextAlbumId++}`}, timestamp: {internalValue: BigInt(`${nextAlbumId}`)}, + isShared: false, }; })); @@ -287,6 +292,7 @@ photoCount: 1, preview: {url: `url-${nextAlbumId++}`}, timestamp: {internalValue: BigInt(`${nextAlbumId}`)}, + isShared: false, }; }));
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_collection_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_collection_element_test.ts index f8fd708..9c667c4 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_collection_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_collection_element_test.ts
@@ -84,6 +84,7 @@ photoCount: 0, preview: {url: ''}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }]); // Initialize |googlePhotosCollectionElement|. @@ -147,6 +148,7 @@ photoCount: 1, preview: {url: 'foo.com'}, timestamp: {internalValue: BigInt(`13318040939308000`)}, + isShared: false, }]; wallpaperProvider.setGooglePhotosAlbums(albums); wallpaperProvider.setGooglePhotosPhotos([{
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts index 68c2c235..3ecad9b1 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts
@@ -57,6 +57,7 @@ photoCount: 1, preview: {url: 'foo.com'}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; // Set values returned by |wallpaperProvider|. @@ -124,6 +125,7 @@ // placeholder attribute. preview: {url: createSvgDataUrl('svg-1')}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; const otherAlbum: GooglePhotosAlbum = { @@ -132,6 +134,7 @@ photoCount: 1, preview: {url: createSvgDataUrl('svg-2')}, timestamp: {internalValue: BigInt('2')}, + isShared: false, }; const photosByAlbumId: Record<string, GooglePhotosPhoto[]> = { @@ -276,6 +279,7 @@ photoCount: 2, preview: {url: ''}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; const photo: GooglePhotosPhoto = { @@ -448,6 +452,7 @@ photoCount: photosCount, preview: {url: ''}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; const photos: GooglePhotosPhoto[] = Array.from( {length: photosCount}, (_, i) => ({ @@ -546,6 +551,7 @@ photoCount: photosCount, preview: {url: ''}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; // Set albums returned by |wallpaperProvider|. @@ -696,6 +702,7 @@ photoCount: 1, preview: {url: 'foo.com'}, timestamp: {internalValue: BigInt('1')}, + isShared: false, }; const photo: GooglePhotosPhoto = {
diff --git a/chrome/test/data/webui/cr_components/history_clusters_test.ts b/chrome/test/data/webui/cr_components/history_clusters_test.ts index 1aa020f..ebd18351 100644 --- a/chrome/test/data/webui/cr_components/history_clusters_test.ts +++ b/chrome/test/data/webui/cr_components/history_clusters_test.ts
@@ -36,6 +36,7 @@ }; const urlVisit1: URLVisit = { + visitId: BigInt(1), normalizedUrl: {url: 'https://www.google.com'}, urlForDisplay: 'https://www.google.com', pageTitle: '', @@ -55,6 +56,7 @@ visits: [urlVisit1], labelMatchPositions: [], relatedSearches: [], + fromPersistence: false, }; const cluster2: Cluster = { @@ -62,6 +64,7 @@ visits: [], labelMatchPositions: [], relatedSearches: [], + fromPersistence: false, }; const queryResult: QueryResult = {
diff --git a/chrome/test/data/webui/password_manager/checkup_details_section_test.ts b/chrome/test/data/webui/password_manager/checkup_details_section_test.ts index 545bbd2..a35e68c 100644 --- a/chrome/test/data/webui/password_manager/checkup_details_section_test.ts +++ b/chrome/test/data/webui/password_manager/checkup_details_section_test.ts
@@ -4,7 +4,7 @@ import 'chrome://password-manager/password_manager.js'; -import {CheckupSubpage, CrExpandButtonElement, Page, PasswordManagerImpl, Router} from 'chrome://password-manager/password_manager.js'; +import {CheckupSubpage, CrExpandButtonElement, Page, PasswordManagerImpl, PrefsBrowserProxyImpl, Router} from 'chrome://password-manager/password_manager.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; @@ -13,13 +13,15 @@ import {isVisible} from 'chrome://webui-test/test_util.js'; import {TestPasswordManagerProxy} from './test_password_manager_proxy.js'; -import {makeInsecureCredential} from './test_util.js'; +import {TestPrefsBrowserProxy} from './test_prefs_browser_proxy.js'; +import {createCredentialGroup, makeInsecureCredential, makePasswordManagerPrefs} from './test_util.js'; suite('CheckupDetailsSectionTest', function() { const CompromiseType = chrome.passwordsPrivate.CompromiseType; let passwordManager: TestPasswordManagerProxy; let pluralString: TestPluralStringProxy; + let prefsProxy: TestPrefsBrowserProxy; setup(function() { document.body.innerHTML = window.trustedTypes!.emptyHTML; @@ -27,6 +29,9 @@ PasswordManagerImpl.setInstance(passwordManager); pluralString = new TestPluralStringProxy(); PluralStringProxyImpl.setInstance(pluralString); + prefsProxy = new TestPrefsBrowserProxy(); + prefsProxy.prefs = makePasswordManagerPrefs(); + PrefsBrowserProxyImpl.setInstance(prefsProxy); Router.getInstance().navigateTo(Page.CHECKUP); return flushTasks(); }); @@ -99,10 +104,17 @@ elapsedMinSinceCompromise: 100, }), ]; + passwordManager.data.groups = [ + createCredentialGroup({ + name: 'Affiliation.com', + credentials: passwordManager.data.insecureCredentials, + }), + ]; const section = document.createElement('checkup-details-section'); document.body.appendChild(section); await passwordManager.whenCalled('getInsecureCredentials'); + await passwordManager.whenCalled('getCredentialGroups'); const params = await pluralString.whenCalled('getPluralString'); await flushTasks(); @@ -128,7 +140,7 @@ assertTrue(!!listItemElement); assertEquals( - expectedCredential.urls.shown, + passwordManager.data.groups[0]?.name, listItemElement.$.shownUrl.textContent!.trim()); assertEquals( expectedCredential.username, @@ -160,10 +172,17 @@ ], elapsedMinSinceCompromise: 1, })]; + passwordManager.data.groups = [ + createCredentialGroup({ + name: 'Best test site', + credentials: passwordManager.data.insecureCredentials, + }), + ]; const section = document.createElement('checkup-details-section'); document.body.appendChild(section); await passwordManager.whenCalled('getInsecureCredentials'); + await passwordManager.whenCalled('getCredentialGroups'); const params = await pluralString.whenCalled('getPluralString'); await flushTasks(); @@ -176,7 +195,9 @@ const weakItem = listItemElements[0]; assertTrue(!!weakItem); - assertEquals('test.com', weakItem.$.shownUrl.textContent!.trim()); + assertEquals( + passwordManager.data.groups[0]!.name, + weakItem.$.shownUrl.textContent!.trim()); assertEquals('viking', weakItem.$.username.textContent!.trim()); assertFalse(!!weakItem.shadowRoot!.querySelector('#compromiseType')); @@ -245,4 +266,187 @@ assertTrue(isVisible(listItemElements[0])); }); + + test('Show/Hide action button works', async function() { + Router.getInstance().navigateTo( + Page.CHECKUP_DETAILS, CheckupSubpage.COMPROMISED); + passwordManager.data.insecureCredentials = [ + makeInsecureCredential({ + id: 0, + url: 'test.com', + username: 'viking', + types: [ + CompromiseType.LEAKED, + ], + }), + ]; + + const section = document.createElement('checkup-details-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getInsecureCredentials'); + await flushTasks(); + + const listItem = section.shadowRoot!.querySelector('checkup-list-item'); + assertTrue(!!listItem); + assertTrue(isVisible(listItem)); + assertEquals('password', listItem.$.insecurePassword.type); + + assertFalse(isVisible(section.$.moreActionsMenu)); + + // Click more actions button + listItem.$.more.click(); + + assertTrue(isVisible(section.$.menuShowPassword)); + assertEquals( + loadTimeData.getString('showPassword'), + section.$.menuShowPassword.textContent?.trim()); + + const credentialWithPassword = passwordManager.data.insecureCredentials[0]!; + credentialWithPassword.password = 'pAssWoRd'; + passwordManager.setRequestCredentialsDetailsResponse( + [credentialWithPassword]); + + section.$.menuShowPassword.click(); + await passwordManager.whenCalled('requestCredentialsDetails'); + + assertEquals('text', listItem.$.insecurePassword.type); + assertEquals( + credentialWithPassword.password, listItem.$.insecurePassword.value); + + listItem.$.more.click(); + assertTrue(isVisible(section.$.menuShowPassword)); + assertEquals( + loadTimeData.getString('hidePassword'), + section.$.menuShowPassword.textContent?.trim()); + section.$.menuShowPassword.click(); + + assertEquals('password', listItem.$.insecurePassword.type); + }); + + test('Mute button works', async function() { + Router.getInstance().navigateTo( + Page.CHECKUP_DETAILS, CheckupSubpage.COMPROMISED); + passwordManager.data.insecureCredentials = [ + makeInsecureCredential({ + id: 0, + url: 'test.com', + username: 'viking', + types: [ + CompromiseType.LEAKED, + ], + }), + ]; + + const section = document.createElement('checkup-details-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getInsecureCredentials'); + await flushTasks(); + + const listItem = section.shadowRoot!.querySelector('checkup-list-item'); + assertTrue(!!listItem); + assertTrue(isVisible(listItem)); + + // Click more actions button + listItem.$.more.click(); + + const muteButton = + section.shadowRoot!.querySelector<HTMLElement>('#menuMuteUnmuteButton'); + assertTrue(!!muteButton); + assertTrue(isVisible(muteButton)); + assertEquals( + loadTimeData.getString('muteCompromisedPassword'), + muteButton.textContent?.trim()); + + muteButton.click(); + await passwordManager.whenCalled('muteInsecureCredential'); + }); + + test('Unmute button works', async function() { + Router.getInstance().navigateTo( + Page.CHECKUP_DETAILS, CheckupSubpage.COMPROMISED); + passwordManager.data.insecureCredentials = [ + makeInsecureCredential({ + id: 0, + url: 'test.com', + username: 'viking', + types: [ + CompromiseType.LEAKED, + ], + isMuted: true, + }), + ]; + + const section = document.createElement('checkup-details-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getInsecureCredentials'); + await flushTasks(); + + // Expand dismissed compromised credentials. + const expandButton = section.shadowRoot!.querySelector<HTMLElement>( + '#expandMutedCompromisedCredentialsButton'); + assertTrue(!!expandButton); + assertTrue(isVisible(expandButton)); + expandButton.click(); + await flushTasks(); + + const listItem = section.shadowRoot!.querySelector('checkup-list-item'); + assertTrue(!!listItem); + assertFalse(isVisible(section.$.moreActionsMenu)); + + // Click more actions button + listItem.$.more.click(); + + const unMuteButton = + section.shadowRoot!.querySelector<HTMLElement>('#menuMuteUnmuteButton'); + assertTrue(!!unMuteButton); + assertTrue(isVisible(unMuteButton)); + assertEquals( + loadTimeData.getString('unmuteCompromisedPassword'), + unMuteButton.textContent?.trim()); + + unMuteButton.click(); + await passwordManager.whenCalled('unmuteInsecureCredential'); + }); + + test('Mute button disabled by pref', async function() { + Router.getInstance().navigateTo( + Page.CHECKUP_DETAILS, CheckupSubpage.COMPROMISED); + passwordManager.data.insecureCredentials = [ + makeInsecureCredential({ + id: 0, + url: 'test.com', + username: 'viking', + types: [ + CompromiseType.LEAKED, + ], + }), + ]; + + prefsProxy.prefs = [ + { + key: 'profile.password_dismiss_compromised_alert', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + ]; + + const section = document.createElement('checkup-details-section'); + document.body.appendChild(section); + await passwordManager.whenCalled('getInsecureCredentials'); + await flushTasks(); + + const listItem = section.shadowRoot!.querySelector('checkup-list-item'); + assertTrue(!!listItem); + assertTrue(isVisible(listItem)); + + // Click more actions button + listItem.$.more.click(); + + const muteButton = section.shadowRoot!.querySelector<HTMLButtonElement>( + '#menuMuteUnmuteButton'); + + assertTrue(!!muteButton); + assertTrue(isVisible(muteButton)); + assertTrue(muteButton.disabled); + }); });
diff --git a/chrome/test/data/webui/password_manager/test_password_manager_proxy.ts b/chrome/test/data/webui/password_manager/test_password_manager_proxy.ts index df78c55e..8b6b7ea0 100644 --- a/chrome/test/data/webui/password_manager/test_password_manager_proxy.ts +++ b/chrome/test/data/webui/password_manager/test_password_manager_proxy.ts
@@ -43,6 +43,7 @@ 'getInsecureCredentials', 'getPasswordCheckStatus', 'getSavedPasswordList', + 'muteInsecureCredential', 'recordPasswordCheckInteraction', 'removeBlockedSite', 'requestCredentialsDetails', @@ -50,6 +51,7 @@ 'requestPlaintextPassword', 'showAddShortcutDialog', 'startBulkPasswordCheck', + 'unmuteInsecureCredential', ]); // Set these to have non-empty data. @@ -145,6 +147,16 @@ this.methodCalled('recordPasswordCheckInteraction', interaction); } + muteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry) { + this.methodCalled('muteInsecureCredential', insecureCredential); + } + + unmuteInsecureCredential(insecureCredential: + chrome.passwordsPrivate.PasswordUiEntry) { + this.methodCalled('unmuteInsecureCredential', insecureCredential); + } + showAddShortcutDialog() { this.methodCalled('showAddShortcutDialog'); }
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.ts b/chrome/test/data/webui/print_preview/native_layer_stub.ts index bd73a09..79df776 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.ts +++ b/chrome/test/data/webui/print_preview/native_layer_stub.ts
@@ -181,6 +181,8 @@ recordInHistogram() {} + recordBooleanHistogram() {} + saveAppState(appState: string) { this.methodCalled('saveAppState', appState); }
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index a8f1438..f996884 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -81,6 +81,7 @@ "google_assistant_page_test.js", "guest_os_shared_paths_test.js", "guest_os_shared_usb_devices_test.js", + "input_device_mojo_interface_provider_test.js", "input_method_options_page_test.js", "input_page_test.js", "internet_config_test.js",
diff --git a/chrome/test/data/webui/settings/chromeos/fake_input_device_settings_provider_test.js b/chrome/test/data/webui/settings/chromeos/fake_input_device_settings_provider_test.js index 79a3d1d..c670c9e1 100644 --- a/chrome/test/data/webui/settings/chromeos/fake_input_device_settings_provider_test.js +++ b/chrome/test/data/webui/settings/chromeos/fake_input_device_settings_provider_test.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {FakeInputDeviceSettingsProvider, MetaKey} from 'chrome://os-settings/chromeos/os_settings.js'; +import {FakeInputDeviceSettingsProvider, fakeKeyboards, fakeMice, fakePointingSticks, fakeTouchpads} from 'chrome://os-settings/chromeos/os_settings.js'; import {assertDeepEquals} from 'chrome://webui-test/chai_assert.js'; suite('FakeInputDeviceSettings', function() { @@ -20,54 +20,26 @@ }); test('setFakeKeyboards', () => { - const fakeKeyboards = [{ - id: 0, - name: 'fake-keyboard', - isExternal: false, - metaKey: MetaKey.COMMAND, - modifierKeys: [], - settings: {}, - }]; - provider.setFakeKeyboards(fakeKeyboards); - return provider.getFakeKeyboards().then( + return provider.getConnectedKeyboardSettings().then( result => assertDeepEquals(fakeKeyboards, result)); }); test('setFakeTouchpads', () => { - const fakeTouchpads = [{ - id: 1, - name: 'fake-touchpad', - isExternal: false, - isHaptic: false, - }]; - provider.setFakeTouchpads(fakeTouchpads); - return provider.getFakeTouchpads().then( + return provider.getConnectedTouchpadSettings().then( result => assertDeepEquals(fakeTouchpads, result)); }); test('setFakeMice', () => { - const fakeMice = [{ - id: 2, - name: 'fake-mouse', - isExternal: false, - }]; - provider.setFakeMice(fakeMice); - return provider.getFakeMice().then( + return provider.getConnectedMouseSettings().then( result => assertDeepEquals(fakeMice, result)); }); test('setFakePointingSticks', () => { - const fakePointingSticks = [{ - id: 3, - name: 'fake-pointing-stick', - isExternal: false, - }]; - provider.setFakePointingSticks(fakePointingSticks); - return provider.getFakePointingSticks().then( + return provider.getConnectedPointingStickSettings().then( result => assertDeepEquals(fakePointingSticks, result)); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/input_device_mojo_interface_provider_test.js b/chrome/test/data/webui/settings/chromeos/input_device_mojo_interface_provider_test.js new file mode 100644 index 0000000..6fd2372 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/input_device_mojo_interface_provider_test.js
@@ -0,0 +1,16 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {getInputDeviceSettingsProvider} from 'chrome://os-settings/chromeos/os_settings.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; + +suite('InputDeviceMojoInterfaceProvider', function() { + test('SettingGettingTestProvider', () => { + // Test that if there was no provider, getInputDeviceSettingsProvider + // method will create one. + const fakeProvider = getInputDeviceSettingsProvider(); + assertTrue(!!fakeProvider); + assertEquals(fakeProvider, getInputDeviceSettingsProvider()); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js index c98c06f..5864ef0 100644 --- a/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.js
@@ -2,17 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, Router, routes, setContactManagerForTesting, setNearbyShareSettingsForTesting} from 'chrome://os-settings/chromeos/os_settings.js'; +import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, Router, routes, setContactManagerForTesting, setNearbyShareSettingsForTesting} from 'chrome://os-settings/chromeos/os_settings.js'; import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js'; import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; -import {isChildVisible} from 'chrome://webui-test/test_util.js'; - import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {FakeContactManager} from 'chrome://webui-test/nearby_share/shared/fake_nearby_contact_manager.js'; import {FakeNearbyShareSettings} from 'chrome://webui-test/nearby_share/shared/fake_nearby_share_settings.js'; +import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {isChildVisible} from 'chrome://webui-test/test_util.js'; import {createFakePageContentData, HOST_DEVICE, TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js';
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js b/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js index f8374cd6..33b55cc 100644 --- a/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js +++ b/chrome/test/data/webui/settings/chromeos/multidevice_smartlock_item_test.js
@@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; +import {MultiDeviceBrowserProxyImpl, MultiDeviceFeature, MultiDeviceFeatureState, MultiDeviceSettingsMode, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {createFakePageContentData, TestMultideviceBrowserProxy} from './test_multidevice_browser_proxy.js'; @@ -92,9 +91,13 @@ // When the user requets a feature state change, an event with the relevant // details is handled. - smartLockItem.fire( - 'feature-toggle-clicked', - {feature: MultiDeviceFeature.SMART_LOCK, enabled: enabled}); + const featureToggleClickedEvent = + new CustomEvent('feature-toggle-clicked', { + bubbles: true, + composed: true, + detail: {feature: MultiDeviceFeature.SMART_LOCK, enabled}, + }); + smartLockItem.dispatchEvent(featureToggleClickedEvent); flush(); const params = await browserProxy.whenCalled('setFeatureEnabledState');
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index 036bbb8a..5f22837 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -407,6 +407,10 @@ 'hotspot_summary_item_tests.js', {enabled: ['ash::features::kHotspot']}, ], + [ + 'InputDeviceMojoInterfaceProvider', + 'input_device_mojo_interface_provider_test.js' + ], ['InputMethodOptionPage', 'input_method_options_page_test.js'], ['InputPage', 'input_page_test.js'], ['InternetConfig', 'internet_config_test.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js index cc664d54..1b53098 100644 --- a/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js +++ b/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.js
@@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {MultiDeviceFeature, MultiDevicePageContentData, MultiDeviceSettingsMode} from 'chrome://os-settings/chromeos/os_settings.js'; +import {MultiDeviceFeature, MultiDeviceSettingsMode} from 'chrome://os-settings/chromeos/os_settings.js'; import {webUIListenerCallback} from 'chrome://resources/ash/common/cr.m.js'; - import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; /**
diff --git a/chrome/test/data/webui/settings/privacy_sandbox_page_test.ts b/chrome/test/data/webui/settings/privacy_sandbox_page_test.ts index c2b311c6..fb01b894 100644 --- a/chrome/test/data/webui/settings/privacy_sandbox_page_test.ts +++ b/chrome/test/data/webui/settings/privacy_sandbox_page_test.ts
@@ -1115,6 +1115,7 @@ await flushTasks(); assertTrue(isVisible(page.$.adMeasurementToggle)); assertFalse(page.$.adMeasurementToggle.checked); + assertFalse(page.$.adMeasurementToggle.controlDisabled()); assertEquals( loadTimeData.getString('adMeasurementPageToggleSubLabel'), page.$.adMeasurementToggle.subLabel); @@ -1123,6 +1124,7 @@ await flushTasks(); assertTrue(isVisible(page.$.adMeasurementToggle)); assertTrue(page.$.adMeasurementToggle.checked); + assertFalse(page.$.adMeasurementToggle.controlDisabled()); assertEquals( loadTimeData.getString('adMeasurementPageToggleSubLabel'), page.$.adMeasurementToggle.subLabel); @@ -1138,6 +1140,7 @@ await flushTasks(); assertTrue(isVisible(page.$.adMeasurementToggle)); assertTrue(page.$.adMeasurementToggle.checked); + assertFalse(page.$.adMeasurementToggle.controlDisabled()); assertEquals( loadTimeData.getString('adMeasurementPageToggleSubLabel'), page.$.adMeasurementToggle.subLabel); @@ -1146,6 +1149,7 @@ await flushTasks(); assertTrue(isVisible(page.$.adMeasurementToggle)); assertFalse(page.$.adMeasurementToggle.checked); + assertFalse(page.$.adMeasurementToggle.controlDisabled()); assertEquals( loadTimeData.getString('adMeasurementPageToggleSubLabel'), page.$.adMeasurementToggle.subLabel); @@ -1155,4 +1159,16 @@ 'Settings.PrivacySandbox.AdMeasurement.Disabled', await metricsBrowserProxy.whenCalled('recordAction')); }); + + test('adMeasurementManaged', async function() { + page.set('prefs.privacy_sandbox.m1.ad_measurement_enabled', { + ...page.get('prefs.privacy_sandbox.m1.ad_measurement_enabled'), + value: false, + controlledBy: chrome.settingsPrivate.ControlledBy.USER_POLICY, + enforcement: chrome.settingsPrivate.Enforcement.ENFORCED, + }); + await flushTasks(); + assertFalse(page.$.adMeasurementToggle.checked); + assertTrue(page.$.adMeasurementToggle.controlDisabled()); + }); });
diff --git a/chrome/test/data/webui/settings/safety_check_permissions_test.ts b/chrome/test/data/webui/settings/safety_check_permissions_test.ts index 6f1246c..7fc8c5c 100644 --- a/chrome/test/data/webui/settings/safety_check_permissions_test.ts +++ b/chrome/test/data/webui/settings/safety_check_permissions_test.ts
@@ -6,7 +6,7 @@ import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Router, routes, SafetyCheckIconStatus, SettingsSafetyCheckNotificationPermissionsElement, SettingsSafetyCheckPageElement, SettingsSafetyCheckUnusedSitePermissionsElement} from 'chrome://settings/settings.js'; +import {MetricsBrowserProxyImpl, Route, Router, routes, SafetyCheckIconStatus, SafetyCheckInteractions, SettingsRoutes, SettingsSafetyCheckNotificationPermissionsElement, SettingsSafetyCheckPageElement, SettingsSafetyCheckUnusedSitePermissionsElement} from 'chrome://settings/settings.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {ContentSettingsTypes, NotificationPermission, UnusedSitePermissions, SiteSettingsPermissionsBrowserProxyImpl, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; @@ -14,13 +14,16 @@ import {isVisible} from 'chrome://webui-test/test_util.js'; import {assertSafetyCheckChild} from './safety_check_test_utils.js'; +import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js'; import {TestSiteSettingsPermissionsBrowserProxy} from './test_site_settings_permissions_browser_proxy.js'; import {TestSiteSettingsPrefsBrowserProxy} from './test_site_settings_prefs_browser_proxy.js'; // clang-format on suite('SafetyCheckUnusedSitePermissionsUiTests', function() { let page: SettingsSafetyCheckUnusedSitePermissionsElement; + let testRoutes: SettingsRoutes; let browserProxy: TestSiteSettingsPermissionsBrowserProxy; + let metricsBrowserProxy: TestMetricsBrowserProxy; const origin1 = 'www.example1.com'; const origin2 = 'www.example2.com'; @@ -28,6 +31,13 @@ setup(function() { browserProxy = new TestSiteSettingsPermissionsBrowserProxy(); SiteSettingsPermissionsBrowserProxyImpl.setInstance(browserProxy); + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.setInstance(metricsBrowserProxy); + testRoutes = { + PRIVACY: new Route('/privacy'), + BASIC: new Route('/'), + } as unknown as SettingsRoutes; + Router.resetInstanceForTesting(new Router(routes)); document.body.innerHTML = window.trustedTypes!.emptyHTML; }); @@ -37,6 +47,7 @@ page = document.createElement('settings-safety-check-unused-site-permissions'); + Router.getInstance().navigateTo(testRoutes.PRIVACY); document.body.appendChild(page); flush(); } @@ -85,6 +96,15 @@ // Ensure the correct Settings page is shown. assertEquals(routes.SITE_SETTINGS, Router.getInstance().getCurrentRoute()); + + const resultHistogram = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckInteractionHistogram'); + assertEquals( + SafetyCheckInteractions.UNUSED_SITE_PERMISSIONS_REVIEW, + resultHistogram); + const resultAction = await metricsBrowserProxy.whenCalled('recordAction'); + assertEquals( + 'Settings.SafetyCheck.ReviewUnusedSitePermissions', resultAction); }); }); @@ -196,6 +216,8 @@ suite('SafetyCheckPagePermissionModulesTest', function() { let page: SettingsSafetyCheckPageElement; + let testRoutes: SettingsRoutes; + let metricsBrowserProxy: TestMetricsBrowserProxy; let prefsBrowserProxy: TestSiteSettingsPrefsBrowserProxy; let permissionsBrowserProxy: TestSiteSettingsPermissionsBrowserProxy; const notificationElementName = @@ -216,16 +238,24 @@ ]; setup(function() { + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.setInstance(metricsBrowserProxy); prefsBrowserProxy = new TestSiteSettingsPrefsBrowserProxy(); SiteSettingsPrefsBrowserProxyImpl.setInstance(prefsBrowserProxy); permissionsBrowserProxy = new TestSiteSettingsPermissionsBrowserProxy(); SiteSettingsPermissionsBrowserProxyImpl.setInstance( permissionsBrowserProxy); + testRoutes = { + PRIVACY: new Route('/privacy'), + BASIC: new Route('/'), + } as unknown as SettingsRoutes; + Router.resetInstanceForTesting(new Router(routes)); document.body.innerHTML = window.trustedTypes!.emptyHTML; }); function createPage() { page = document.createElement('settings-safety-check-page'); + Router.getInstance().navigateTo(testRoutes.PRIVACY); document.body.appendChild(page); flush(); } @@ -257,6 +287,9 @@ assertTrue( isVisible(page.shadowRoot!.querySelector(notificationElementName))); + assertTrue(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckNotificationsModuleEntryPointShown')); + webUIListenerCallback( 'notification-permission-review-list-maybe-changed', []); await flushTasks(); @@ -272,6 +305,8 @@ assertFalse( isVisible(page.shadowRoot!.querySelector(notificationElementName))); + assertFalse(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckNotificationsModuleEntryPointShown')); // Re-enable the notification permission feature. loadTimeData.overrideValues( {safetyCheckNotificationPermissionsEnabled: true}); @@ -282,6 +317,8 @@ assertFalse( isVisible(page.shadowRoot!.querySelector(notificationElementName))); + assertFalse(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckNotificationsModuleEntryPointShown')); webUIListenerCallback( 'notification-permission-review-list-maybe-changed', @@ -292,11 +329,13 @@ isVisible(page.shadowRoot!.querySelector(notificationElementName))); }); - test('unusedSitePermissionsModuleVisible', async () => { + test('unusedSitePermissionsModuleEntryPointShown', async () => { await createPageForUnusedSitePermissions(unusedSiteMockData); assertTrue( isVisible(page.shadowRoot!.querySelector(unusedSiteElementName))); + assertTrue(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown')); }); test('unusedSitePermissionsModuleFeatureDisabled', async () => { @@ -306,6 +345,8 @@ assertFalse( isVisible(page.shadowRoot!.querySelector(unusedSiteElementName))); + assertFalse(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown')); // Re-enable the unused site permissions feature. loadTimeData.overrideValues( @@ -317,5 +358,7 @@ assertFalse( isVisible(page.shadowRoot!.querySelector(unusedSiteElementName))); + assertFalse(await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown')); }); });
diff --git a/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts b/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts index 1971812..5812c40 100644 --- a/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts +++ b/chrome/test/data/webui/settings/test_metrics_browser_proxy.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {MetricsBrowserProxy, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions, SafetyCheckNotificationsModuleInteractions} from 'chrome://settings/settings.js'; +import {MetricsBrowserProxy, PrivacyElementInteractions, PrivacyGuideInteractions, PrivacyGuideSettingsStates, SafeBrowsingInteractions, SafetyCheckInteractions, SafetyCheckNotificationsModuleInteractions, SafetyCheckUnusedSitePermissionsModuleInteractions} from 'chrome://settings/settings.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; export class TestMetricsBrowserProxy extends TestBrowserProxy implements @@ -13,6 +13,10 @@ 'recordSafetyCheckInteractionHistogram', 'recordSafetyCheckNotificationsListCountHistogram', 'recordSafetyCheckNotificationsModuleInteractionsHistogram', + 'recordSafetyCheckNotificationsModuleEntryPointShown', + 'recordSafetyCheckUnusedSitePermissionsListCountHistogram', + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram', + 'recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown', 'recordSettingsPageHistogram', 'recordSafeBrowsingInteractionHistogram', 'recordPrivacyGuideNextNavigationHistogram', @@ -41,6 +45,31 @@ interaction); } + recordSafetyCheckNotificationsModuleEntryPointShown(visible: boolean) { + this.methodCalled( + 'recordSafetyCheckNotificationsModuleEntryPointShown', visible); + } + + recordSafetyCheckUnusedSitePermissionsListCountHistogram(suggestions: + number) { + this.methodCalled( + 'recordSafetyCheckUnusedSitePermissionsListCountHistogram', + suggestions); + } + + recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram( + interaction: SafetyCheckUnusedSitePermissionsModuleInteractions) { + this.methodCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram', + interaction); + } + + recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown(visible: + boolean) { + this.methodCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleEntryPointShown', visible); + } + recordSettingsPageHistogram(interaction: PrivacyElementInteractions) { this.methodCalled('recordSettingsPageHistogram', interaction); }
diff --git a/chrome/test/data/webui/settings/unused_site_permissions_test.ts b/chrome/test/data/webui/settings/unused_site_permissions_test.ts index cdca163..32411057 100644 --- a/chrome/test/data/webui/settings/unused_site_permissions_test.ts +++ b/chrome/test/data/webui/settings/unused_site_permissions_test.ts
@@ -8,14 +8,17 @@ import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {ContentSettingsTypes, SettingsUnusedSitePermissionsElement, SiteSettingsPermissionsBrowserProxyImpl, UnusedSitePermissions} from 'chrome://settings/lazy_load.js'; +import {MetricsBrowserProxyImpl, SafetyCheckUnusedSitePermissionsModuleInteractions} from 'chrome://settings/settings.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; +import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js'; import {TestSiteSettingsPermissionsBrowserProxy} from './test_site_settings_permissions_browser_proxy.js'; // clang-format on suite('CrSettingsUnusedSitePermissionsTest', function() { let browserProxy: TestSiteSettingsPermissionsBrowserProxy; + let metricsBrowserProxy: TestMetricsBrowserProxy; let testElement: SettingsUnusedSitePermissionsElement; @@ -96,6 +99,8 @@ testElement = document.createElement('settings-unused-site-permissions'); testElement.setModelUpdateDelayMsForTesting(0); document.body.appendChild(testElement); + // Wait until the element has asked for the list of revoked permissions + // that will be shown for review. await browserProxy.whenCalled('getRevokedUnusedSitePermissionsList'); flush(); } @@ -104,10 +109,24 @@ browserProxy = new TestSiteSettingsPermissionsBrowserProxy(); browserProxy.setUnusedSitePermissions(mockData); SiteSettingsPermissionsBrowserProxyImpl.setInstance(browserProxy); + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.setInstance(metricsBrowserProxy); await createPage(); + // Clear the metrics that were recorded as part of the initial creation of + // the page. + metricsBrowserProxy.reset(); assertInitialUi(); }); + test('Capture metric on visit', async function() { + await createPage(); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.OPEN_REVIEW_UI, + result); + }); + test('Unused Site Permission strings', function() { const siteList = getSiteList(); assertEquals(4, siteList.length); @@ -146,7 +165,7 @@ siteList[3]!.querySelector('.secondary')!.textContent!.trim()); }); - test('Collapsible List', function() { + test('Collapsible List', async function() { const expandButton = testElement.shadowRoot!.querySelector('cr-expand-button'); assertTrue(!!expandButton); @@ -167,6 +186,11 @@ assertFalse(expandButton.expanded); assertFalse(unusedSitePermissionList.opened); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.MINIMIZE, result); + // User expands the list. expandButton.click(); flush(); @@ -266,4 +290,66 @@ 'safetyCheckUnusedSitePermissionsToastBulkLabel', 1); assertToast(true, expectedSingularToastText); }); + + test('Allow again record metrics', async function() { + const siteList = getSiteList(); + siteList[0]!.querySelector('cr-icon-button')!.click(); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.ALLOW_AGAIN, result); + }); + + test('Undo allow again record metrics', async function() { + const siteList = getSiteList(); + siteList[0]!.querySelector('cr-icon-button')!.click(); + // Reset the action captured by clicking the block button. + metricsBrowserProxy.resetResolver( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + clickUndo(); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.UNDO_ALLOW_AGAIN, + result); + }); + + test('Got it record metrics', async function() { + clickGotIt(); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.ACKNOWLEDGE_ALL, + result); + }); + + test('Undo got it record metrics', async function() { + clickGotIt(); + // Reset the action captured by clicking the got it button. + metricsBrowserProxy.resetResolver( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + clickUndo(); + const result = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsModuleInteractionsHistogram'); + assertEquals( + SafetyCheckUnusedSitePermissionsModuleInteractions.UNDO_ACKNOWLEDGE_ALL, + result); + }); + + test('Review list size record metrics', async function() { + browserProxy.setUnusedSitePermissions(mockData); + await createPage(); + const resultNumSites = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsListCountHistogram'); + assertEquals(mockData.length, resultNumSites); + + metricsBrowserProxy.resetResolver( + 'recordSafetyCheckUnusedSitePermissionsListCountHistogram'); + + browserProxy.setUnusedSitePermissions([]); + await createPage(); + const resultEmpty = await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckUnusedSitePermissionsListCountHistogram'); + assertEquals(0, resultEmpty); + }); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts index 5ed8c69a..d981852 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts
@@ -6,14 +6,31 @@ import 'chrome://customize-chrome-side-panel.top-chrome/app.js'; import {AppElement} from 'chrome://customize-chrome-side-panel.top-chrome/app.js'; -import {BackgroundCollection} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; -import {assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {BackgroundCollection, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromePageRemote, CustomizeChromeSection} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; +import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; +import {assertEquals, assertGE, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; + +import {installMock} from './test_support.js'; suite('AppTest', () => { let customizeChromeApp: AppElement; + let handler: TestBrowserProxy<CustomizeChromePageHandlerRemote>; + let callbackRouter: CustomizeChromePageRemote; setup(async () => { document.body.innerHTML = window.trustedTypes!.emptyHTML; + handler = installMock( + CustomizeChromePageHandlerRemote, + (mock: CustomizeChromePageHandlerRemote) => + CustomizeChromeApiProxy.setInstance( + mock, new CustomizeChromePageCallbackRouter())); + handler.setResultFor('getBackgroundImages', new Promise(() => {})); + handler.setResultFor('getChromeColors', new Promise(() => {})); + handler.setResultFor('getOverviewChromeColors', new Promise(() => {})); + handler.setResultFor('getBackgroundCollections', new Promise(() => {})); + callbackRouter = CustomizeChromeApiProxy.getInstance() + .callbackRouter.$.bindNewPipeAndPassRemote(); customizeChromeApp = document.createElement('customize-chrome-app'); document.body.appendChild(customizeChromeApp); }); @@ -81,4 +98,30 @@ assertTrue( customizeChromeApp.$.overviewPage.classList.contains('iron-selected')); }); + + test('app requests scroll to section update', () => { + window.dispatchEvent(new Event('load')); + assertGE(handler.getCallCount('updateScrollToSection'), 1); + }); + + test('app scrolls to section', async () => { + const sections = + customizeChromeApp.shadowRoot!.querySelectorAll('.section'); + const sectionsScrolledTo: Element[] = []; + sections.forEach((section) => { + section.scrollIntoView = () => sectionsScrolledTo.push(section); + }); + + customizeChromeApp.$.appearanceElement.dispatchEvent( + new Event('edit-theme-click')); + callbackRouter.scrollToSection(CustomizeChromeSection.kShortcuts); + await callbackRouter.$.flushForTesting(); + + assertEquals(1, sectionsScrolledTo.length); + assertEquals( + customizeChromeApp.shadowRoot!.querySelector('#shortcuts'), + sectionsScrolledTo[0]); + assertTrue( + customizeChromeApp.$.overviewPage.classList.contains('iron-selected')); + }); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/chrome_colors_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/chrome_colors_test.ts index 54272e1a..bd20f2ff 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/chrome_colors_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/chrome_colors_test.ts
@@ -7,17 +7,19 @@ import {ChromeColorsElement} from 'chrome://customize-chrome-side-panel.top-chrome/chrome_colors.js'; import {ColorElement} from 'chrome://customize-chrome-side-panel.top-chrome/color.js'; -import {ChromeColor, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; +import {ChromeColor, CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import {assertDeepEquals, assertEquals, assertGE, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; -import {installMock} from './test_support.js'; +import {createTheme, installMock} from './test_support.js'; suite('ChromeColorsTest', () => { let chromeColorsElement: ChromeColorsElement; let handler: TestBrowserProxy<CustomizeChromePageHandlerRemote>; + let callbackRouter: CustomizeChromePageRemote; setup(async () => { document.body.innerHTML = window.trustedTypes!.emptyHTML; @@ -26,6 +28,8 @@ (mock: CustomizeChromePageHandlerRemote) => CustomizeChromeApiProxy.setInstance( mock, new CustomizeChromePageCallbackRouter())); + callbackRouter = CustomizeChromeApiProxy.getInstance() + .callbackRouter.$.bindNewPipeAndPassRemote(); }); async function setInitialSettings(numColors: number): Promise<void> { @@ -101,4 +105,47 @@ assertGE(1, args.length); assertEquals(0xffff0000, args.at(-1).value); }); + + test('checks selected color', async () => { + await setInitialSettings(2); + const theme = createTheme(); + + // Set default color. + theme.foregroundColor = undefined; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + await waitAfterNextRender(chromeColorsElement); + + // Check default color selected. + const defaultColorElement = chromeColorsElement.$.defaultColor; + let checkedColors = + chromeColorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals(defaultColorElement, checkedColors[0]); + + // Set Chrome color. + theme.seedColor = {value: 1}; + theme.foregroundColor = {value: 3}; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + + // Check Chrome color selected. + checkedColors = + chromeColorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals('chrome-color tile', checkedColors[0]!.className); + assertEquals(3, (checkedColors[0]! as ColorElement).foregroundColor.value); + + // Set custom color. + theme.seedColor = {value: 10}; + theme.foregroundColor = {value: 5}; + callbackRouter.setTheme(theme); + await callbackRouter.$.flushForTesting(); + + // Check custom color selected. + checkedColors = + chromeColorsElement.shadowRoot!.querySelectorAll('[checked]'); + assertEquals(1, checkedColors.length); + assertEquals(chromeColorsElement.$.customColor, checkedColors[0]); + }); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts index bf21a9d..4b194e2 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/color_test.ts
@@ -35,8 +35,8 @@ 'customize-chrome-check-mark-wrapper')!; assertTrue(wrapper.checked); const svg = colorElement.shadowRoot!.querySelector('svg')!; - assertStyle(svg, 'width', '46px'); - assertStyle(svg, 'height', '46px'); + assertStyle(svg, 'width', '50px'); + assertStyle(svg, 'height', '50px'); assertStyle(svg, 'border', '0px none rgb(0, 0, 0)'); });
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts index ac15024..bd4bcb4b 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/themes_test.ts
@@ -9,10 +9,11 @@ import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import {ThemesElement} from 'chrome://customize-chrome-side-panel.top-chrome/themes.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; -import {createTheme, installMock} from './test_support.js'; +import {createBackgroundImage, createTheme, installMock} from './test_support.js'; function createTestCollection(name: string): BackgroundCollection { const testCollection: BackgroundCollection = { @@ -176,4 +177,46 @@ await callbackRouterRemote.$.flushForTesting(); assertTrue(themesElement.$.refreshDailyToggle.checked); }); + + test('checks selected theme', async () => { + await setCollection('test_collection', 2); + + // Set theme outside of collection. + const theme = createTheme(); + let backgroundImage = createBackgroundImage('https://test.jpg'); + theme.backgroundImage = backgroundImage; + callbackRouterRemote.setTheme(theme); + await callbackRouterRemote.$.flushForTesting(); + await waitAfterNextRender(themesElement); + + // Check that nothing is selected. + let checkedThemes = + themesElement.shadowRoot!.querySelectorAll('.theme [checked]'); + assertEquals(0, checkedThemes.length); + + // Set theme within collection. + backgroundImage = createBackgroundImage('https://image_1.jpg'); + theme.backgroundImage = backgroundImage; + callbackRouterRemote.setTheme(theme); + await callbackRouterRemote.$.flushForTesting(); + await waitAfterNextRender(themesElement); + + // Check that 1 theme is selected. + checkedThemes = + themesElement.shadowRoot!.querySelectorAll('.theme [checked]'); + assertEquals(1, checkedThemes.length); + const checkedTile = checkedThemes[0]!.parentElement as HTMLElement; + assertEquals(checkedTile!.title, 'attribution1_1'); + + // Set daily refresh. + theme.dailyRefreshCollectionId = 'test_collection_id'; + callbackRouterRemote.setTheme(theme); + await callbackRouterRemote.$.flushForTesting(); + await waitAfterNextRender(themesElement); + + // Check that nothing is selected. + checkedThemes = + themesElement.shadowRoot!.querySelectorAll('.theme [checked]'); + assertEquals(0, checkedThemes.length); + }); });
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts index c07ee84d..bcaebb8 100644 --- a/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_app_test.ts
@@ -54,17 +54,14 @@ chrome.readAnything.setThemeForTesting('Serif', 18.0, 0, 0, 1, 0); assertFontName('serif'); - chrome.readAnything.setThemeForTesting('Avenir', 18.0, 0, 0, 1, 0); - assertFontName('avenir'); - - chrome.readAnything.setThemeForTesting('Comic Neue', 18.0, 0, 0, 1, 0); - assertFontName('"Comic Neue"'); + chrome.readAnything.setThemeForTesting('Arial', 18.0, 0, 0, 1, 0); + assertFontName('Arial'); chrome.readAnything.setThemeForTesting('Comic Sans MS', 18.0, 0, 0, 1, 0); assertFontName('"Comic Sans MS"'); - chrome.readAnything.setThemeForTesting('Poppins', 18.0, 0, 0, 1, 0); - assertFontName('poppins'); + chrome.readAnything.setThemeForTesting('Times New Roman', 18.0, 0, 0, 1, 0); + assertFontName('"Times New Roman"'); }); test('updateTheme fontSize', () => {
diff --git a/chrome/test/data/webui/side_panel/user_notes/app_test.ts b/chrome/test/data/webui/side_panel/user_notes/app_test.ts index 72db37d..a7b37d78 100644 --- a/chrome/test/data/webui/side_panel/user_notes/app_test.ts +++ b/chrome/test/data/webui/side_panel/user_notes/app_test.ts
@@ -61,7 +61,8 @@ } const entryNote = notesElements[(notesElements.length - 1)]!; assertEquals( - 'true', entryNote.$.noteContent.getAttribute('contenteditable')); + 'plaintext-only', + entryNote.$.noteContent.getAttribute('contenteditable')); assertEquals(entryNote.$.noteContent.textContent, ''); }); @@ -71,7 +72,8 @@ const sampleNoteContent = 'sample note content'; entryNote.$.noteContent.textContent = sampleNoteContent; assertEquals( - 'true', entryNote.$.noteContent.getAttribute('contenteditable')); + 'plaintext-only', + entryNote.$.noteContent.getAttribute('contenteditable')); entryNote.$.noteContent.focus(); const notesAddButton = entryNote.shadowRoot!.querySelector('#addButton')! as HTMLButtonElement; @@ -96,7 +98,8 @@ const editButton = noteMenu.querySelectorAll('.dropdown-item')[0]! as HTMLButtonElement; editButton.click(); - assertEquals('true', note.$.noteContent.getAttribute('contenteditable')); + assertEquals( + 'plaintext-only', note.$.noteContent.getAttribute('contenteditable')); assertEquals(originalContent, note.$.noteContent.textContent); // Update content. const newContent = 'different content'; @@ -130,7 +133,8 @@ const editButton = noteMenu.querySelectorAll('.dropdown-item')[0]! as HTMLButtonElement; editButton.click(); - assertEquals('true', note.$.noteContent.getAttribute('contenteditable')); + assertEquals( + 'plaintext-only', note.$.noteContent.getAttribute('contenteditable')); assertEquals(originalContent, note.$.noteContent.textContent); // Update content. note.$.noteContent.textContent = 'different content';
diff --git a/chrome/test/delayload/delayloads_unittest.cc b/chrome/test/delayload/delayloads_unittest.cc index 7be8ee7..5c08637e 100644 --- a/chrome/test/delayload/delayloads_unittest.cc +++ b/chrome/test/delayload/delayloads_unittest.cc
@@ -22,7 +22,6 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "base/win/pe_image.h" -#include "base/win/windows_version.h" #include "build/build_config.h" #include "chrome/install_static/test/scoped_install_details.h" #include "testing/gtest/include/gtest/gtest.h" @@ -175,13 +174,8 @@ HMODULE chrome_module_handle = ::LoadLibrary(dll.value().c_str()); ASSERT_TRUE(chrome_module_handle != nullptr); - // Loading chrome.dll should not load user32.dll on Win10. - // On Win7, chains of system dlls and lack of apisets result in it loading. - if (base::win::GetVersion() >= base::win::Version::WIN10) { - EXPECT_EQ(nullptr, ::GetModuleHandle(L"user32.dll")); - } else { - EXPECT_NE(nullptr, ::GetModuleHandle(L"user32.dll")); - } + // Loading chrome.dll should not load user32.dll on Windows. + EXPECT_EQ(nullptr, ::GetModuleHandle(L"user32.dll")); } TEST_F(DelayloadsTest, ChromeElfDllDelayloadsCheck) {
diff --git a/chrome/test/enterprise/e2e/.vpython3 b/chrome/test/enterprise/e2e/.vpython3 index 576d79d..ec4f7f3 100644 --- a/chrome/test/enterprise/e2e/.vpython3 +++ b/chrome/test/enterprise/e2e/.vpython3
@@ -22,8 +22,8 @@ wheel: < name: "infra/celab/celab/windows-amd64" - # Source: https://ci.chromium.org/ui/p/celab/builders/ci/Windows/b8794218239718434945 - version: "X4GOaHKyH4sH23-7Yo1I8qtn9uTtdkE1ZdSRIUCJRhAC" + # Source: https://ci.chromium.org/ui/p/celab/builders/ci/Windows/b8791065637609854785 + version: "OTW3E7FRitKr7Dx2TPnKUccZueFcJXDd9VEKF9b8_5gC" > # googleapiclient
diff --git a/chrome/test/enterprise/e2e/connector/__init__.py b/chrome/test/enterprise/e2e/connector/__init__.py index 565c6f9f..585815b 100644 --- a/chrome/test/enterprise/e2e/connector/__init__.py +++ b/chrome/test/enterprise/e2e/connector/__init__.py
@@ -5,6 +5,7 @@ from .verifyContent import VerifyContent from .verifyable import Verifyable from .chrome_reporting_connector_test_case import ChromeReportingConnectorTestCase +from .device_trust_connector.device_trust_connector_windows_enrollment_test import * from .realtime_reporting_bce.realtime_reporting_bce_test import * from .reporting_connector_chronicle.reporting_connector_chronicle_test import * from .reporting_connector_crowdstrike.reporting_connector_crowdstrike_test import *
diff --git a/chrome/test/enterprise/e2e/connector/common/device_trust_ui_test.py b/chrome/test/enterprise/e2e/connector/common/device_trust_ui_test.py new file mode 100644 index 0000000..5586120 --- /dev/null +++ b/chrome/test/enterprise/e2e/connector/common/device_trust_ui_test.py
@@ -0,0 +1,507 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import os +import re +import socket +import sys +import time +import traceback +from typing import Dict, List, Optional, Set + +from absl import app +from absl import flags +from absl import logging +from attr import asdict +from attr import define +from attr import Factory +from selenium import webdriver +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import StaleElementReferenceException +from selenium.webdriver.support.ui import WebDriverWait +import test_util +from test_util import getElementFromShadowRoot +from test_util import getElementsFromShadowRoot +from test_util import shutdown_chrome +import win32clipboard + +FLAGS = flags.FLAGS + +flags.DEFINE_string( + 'idp_matcher', '', + 'The idp_matcher used to match a IdP site listed at chrome://policy.') + +PolicyURL = 'chrome://policy' +ConnectorInternalURL = 'chrome://connectors-internals' +PolicyContextAwareAccessSignalsAllowlist = 'ContextAwareAccessSignalsAllowlist' +SuccessValue = 9 + + +@define +class HistogramDataBucket: + """Maps to the json:"buckets" values inside HistogramData. + + This class allows for the parsing of the "buckets" json response when using + histogram collection in Chrome. For more information on histogram collection, + see http://shortn/_Oar7S8pRLF. + + Attributes: + count: The "count" value in the nested "buckets" json object of the json + response. Defaults to None. + high: The "high" value in the nested "buckets" json object of the json + response. Defaults to None. + low: The "low" value in the nested "buckets" json object of the json + response. Defaults to None. + """ + count: int = None + high: int = None + low: int = None + + def __bool__(self): + return bool(self.count or self.high or self.low) + + +@define +class HistogramDataParams: + """Maps to the json:"params" inside HistogramData. + + This class allows for the parsing of the "params" within the json response + provided when using histogram collection in Chrome. For more information on + histogram collection, see http://shortn/_Oar7S8pRLF. + + Attributes: + bucket_count: The "bucket_count" value in the nested "params" json of the + json response. Defaults to None. + max_value: The "max" value in the nested "params" json of the json response. + Defaults to None. + min_value: The "min" value in the nested "params" json of the json response. + Defaults to None. + data_type: The "type" value in the nested "params" json of the json + response. Defaults to None. + """ + bucket_count: float = None + max_value: float = None + min_value: float = None + data_type: str = None + + def __bool__(self): + return bool(self.bucket_count or self.max_value or self.min_value or + self.data_type) + + +@define +class HistogramData: + """Maps to the json string schema from histogram. + + This class allows for the parsing of the json response provided when using + histogram collection in Chrome. For more information on histogram collection, + see http://shortn/_Oar7S8pRLF. All values default to None in the case of a + partial json response. + + Attributes: + buckets: The "buckets" value of the json response. Defaults to None. + count: The "count" value of the json response. Defaults to None. + flags: The "flags" value of the json response. Defaults to None. + name: The "name" value of the json response. Defaults to None. + params: The "params" value of the json response. Defaults to None. + pid: The "pid" value of the json response. Defaults to None. + sum_value: The "sum" value of the json response. Defaults to None. + """ + buckets: List[HistogramDataBucket] = Factory(list) + count: float = 0.0 + flags: float = None + name: str = None + params: HistogramDataParams = None + pid: float = None + sum_value: float = None + values: Set[int] = Factory(set) + + def isValuePresent(self, value: int) -> bool: + return value in self.values + + +def parse(response: str) -> HistogramData: + """Parses a Chrome histogram response json string into a HistogramData object. + + Args: + response: A string representation for the json response from a call to + statsCollectionController.getBrowserHistogram. + + Returns: + A HistogramData object represented the json response. + + Raises: + BaseException: If the json response isn't able to be parsed into a + HistogramData object. + """ + d = json.loads(response) + buckets_list = d["buckets"] if "buckets" in d else [] + buckets = [ + HistogramDataBucket(b["count"], b["high"], b["low"]) for b in buckets_list + ] if buckets_list else None + count = d["count"] if "count" in d else None + flags = d["flags"] if "flags" in d else None + name = d["name"] if "name" in d else None + p = d["params"] if "params" in d else None + params = HistogramDataParams( + p["bucket_count"] if "bucket_count" in p else 0.0, + p["max"] if "max" in p else -1, p["min"] if "min" in p else -1, + p["type"] if "type" in p else None) if p else None + pid = d["pid"] if "pid" in d else None + s = d["sum"] if "sum" in d else None + return HistogramData(buckets, count, flags, name, params, pid, s) + + +def add(val1: Optional[float], val2: Optional[float]) -> Optional[float]: + if not val1 or not val2: + return val2 if not val1 else val1 + return val1 + val2 + + +def to_int(val: Optional[float]) -> int: + """Returns a rounded up integer from a byte string.""" + if not val: + return 0 + return int(float(str(val))) + + +def merge_histograms(hd1: Optional[HistogramData], + hd2: Optional[HistogramData]) -> Optional[HistogramData]: + """Merges two histograms by summing corresponding values. + + Args: + hd1: A HistogramData object to be merged. + hd2: A HistogramData object to be merged. + + Returns: + A HistogramData object in which all corresponding values are added. + """ + if not hd1 or not hd2: + return hd2 if not hd1 else hd1 + + logging.info(f'hd1={hd1}, hd2={hd2}') + hd1.count = add(hd1.count, hd2.count) + hd1.sum_value = add(hd1.sum_value, hd2.sum_value) + # Add both sum_value to values to allow query for present query + # sum_value is byte format, and it is like b'9.0' + try: + hd1.values.add(to_int(hd1.sum_value)) + hd1.values.add(to_int(hd2.sum_value)) + except e: + logging.warning( + f'fail to add {hd1.sum_value}, {hd2.sum_value}. err: {str(e)}') + + if not hd2.buckets: + return hd1 + + for b2 in hd2.buckets: + found = False + for i, b1 in enumerate(hd1.buckets): + if b2.low == b1.low and b2.high == b1.high: + hd1.buckets[i].count += b2.count + found = True + + if not found: + hd1.buckets.append(b2) + + return hd1 + + +def histogram(cd: webdriver.chrome.webdriver.WebDriver, + name: str, + timeout: int = 30) -> Optional[HistogramData]: + """Queries a particular histogram from Chrome and formats the response. + + The ChromeDriver instance provided is used to execute javascript in browser, + generating a histogram as a json response. The response is then parsed + and processed, ultimately returned as a HistogramData object. For more + information on histogram collection, see http://shortn/_Oar7S8pRLF. + + Args: + cd: A selenium.webdriver.chrome.webdriver.WebDriver instance. + name: The name of the histogram to search for. + timeout: The timeout for the script execution in seconds. Defaults to 30. + + Returns: + A HistogramData object parsed from the json response. + + Raises: + BaseException: When either histogram request returns an empty response. + """ + resp_str = execute_script( + cd, "return statsCollectionController.getBrowserHistogram('%s');" % name, + timeout) + if not resp_str: + raise BaseException("Could not get histogram with %s" % name) + + hd1 = parse(resp_str) + + # Fetch renderer histograms as well + resp_str = execute_script( + cd, "return statsCollectionController.getHistogram('%s');" % name) + if not resp_str: + raise ValueError("Could not get second histogram with %s" % name) + hd2 = parse(resp_str) + return merge_histograms(hd1, hd2) + + +def execute_script(cd: webdriver.chrome.webdriver.WebDriver, + script: str, + timeout: int = 30) -> str: + """Executes javascript in browser through ChromeDriver. + + Args: + cd: A selenium.webdriver.chrome.webdriver.WebDriver instance. + script: The script to run in the form of a string. + timeout: The timeout to update the socket to. Defaults to 30 seconds to + ensure adequate time for the javascript response. + + Returns: + A str of the response data from executing the script. + """ + default_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + logging.log(logging.DEBUG, "Set socket timeout to %s seconds", timeout) + + script_result = cd.execute_script(script) + logging.log(logging.DEBUG, "Executed Javascript in browser: %s", script) + + socket.setdefaulttimeout(default_timeout) + logging.log(logging.DEBUG, "Set socket timeout to default: %s", + default_timeout) + return script_result + + +def poll_histogram(cd: webdriver.chrome.webdriver.WebDriver, + names: List[str], + timeout: int = 30) -> Optional[Dict[str, HistogramData]]: + """Polls the histograms and returns the list of non-empty histogram. + + Args: + cd: A selenium.webdriver.chrome.webdriver.WebDriver instance. + names: The names of the histograms to fetch. + timeout: The timeout for each histogram fetch request in seconds. Defaults + to 30. + + Returns: + A dict of HistogramData object of the matched histogram. + """ + hgs = None + for name in names: + hg = histogram(cd, name, timeout) + if not hgs: + hgs = {} + hgs[name] = asdict(hg) + + return hgs + + +def save_screenshot(driver: webdriver.Chrome, path: str) -> None: + original_size = driver.get_window_size() + required_width = driver.execute_script( + 'return document.body.parentNode.scrollWidth') + required_height = driver.execute_script( + 'return document.body.parentNode.scrollHeight') + driver.set_window_size(required_width, required_height) + driver.find_element_by_tag_name('body').screenshot(path) + driver.set_window_size(original_size['width'], original_size['height']) + + +def main(argv): + logging.set_verbosity(logging.INFO) + + exclude_switches = ['disable-background-networking'] + chrome_options = webdriver.ChromeOptions() + chrome_options.add_experimental_option('excludeSwitches', exclude_switches) + chrome_options.add_argument('--enable-features=DeviceTrustConnectorEnabled') + chrome_options.add_argument('--enable-stats-collection-bindings') + results = {} + test_cases = ['key_creation', 'key_load'] + + for test_case in test_cases: + driver = test_util.create_chrome_webdriver(chrome_options=chrome_options) + result = {} + + try: + WebDriverWait(driver=driver, timeout=10) + + # Step 1: chrome://connectors-internals + count = 0 + dtc_policy_enabled = '' + key_manager_initialized = '' + spki_hash = '' + key_trust_level = '' + key_sync = '' + while count < 20: + count += 1 + driver.get(ConnectorInternalURL) + WebDriverWait(driver=driver, timeout=10) + connectors_internals_app = driver.find_element_by_css_selector( + 'connectors-internals-app') + WebDriverWait(driver=driver, timeout=10) + + connectors_tabs = getElementFromShadowRoot(driver, + connectors_internals_app, + 'connectors-tabs') + device_trust_connector = getElementFromShadowRoot( + driver, connectors_tabs, 'device-trust-connector') + dtc_policy_enabled = getElementFromShadowRoot(driver, + device_trust_connector, + '#enabled-string').text + key_manager_initialized = getElementFromShadowRoot( + driver, device_trust_connector, '#key-manager-state').text + spki_hash = getElementFromShadowRoot(driver, device_trust_connector, + '#spki-hash').text + key_trust_level = getElementFromShadowRoot(driver, + device_trust_connector, + '#key-trust-level').text + key_sync = getElementFromShadowRoot(driver, device_trust_connector, + '#key-sync').text + if dtc_policy_enabled.casefold() == 'true'.casefold( + ) and key_manager_initialized.casefold() == 'true'.casefold(): + break + time.sleep(6) + + result['KeyManagerInitialized'] = key_manager_initialized + result['DTCPolicyEnabled'] = dtc_policy_enabled + result['SpkiHash'] = spki_hash + result['KeySync'] = key_sync + result['KeyTrustLevel'] = key_trust_level + + # retrieve the other fields from signals + getElementFromShadowRoot(driver, device_trust_connector, + '#copy-signals').click() + + ci_signals = '' + try: + win32clipboard.OpenClipboard() + content = win32clipboard.GetClipboardData(win32clipboard.CF_HDROP) + ci_signals = json.loads(content) + win32clipboard.CloseClipboard() + except: + logging.info('Exception happen when read via win32clipboard. Skip') + + if not ci_signals: + # win32clipboard is not very reliable, apply alternate approach + signals = {} + content = getElementFromShadowRoot(driver, device_trust_connector, + 'div:nth-child(5)').text + logging.info(content) + # trim off 'Signals: {...} Copy Signals + content = content.replace('Signals:', '') + content = content.replace('Copy Signals', '') + ci_signals = json.loads(content) + + logging.info('signals: %s' % ci_signals) + result['ConnectorsInternalsSignals'] = ci_signals + + # Step 2: visit policy app + count = 0 + idp_urls = '' + idp_url = '' + device_id = '' + found_idp_urls = False + # Wait up to 30s till the idp_urls fields are filled. + while count < 5: + driver.get(PolicyURL) + WebDriverWait(driver=driver, timeout=10) + count += 1 + # Avoid to click `Reload-policies` button because it force a entire + # redownload of all policies. it is going to be very slow. + # driver.find_element_by_xpath('//*[@id="reload-policies"]').click() + # WebDriverWait(driver=driver, timeout=10) + policy_table = driver.find_element_by_css_selector('policy-table') + row_groups = getElementsFromShadowRoot(driver, policy_table, + '.policy-data') + try: + for group in row_groups: + name = getElementFromShadowRoot(driver, group, '#name').text + if not name: + break + if name == PolicyContextAwareAccessSignalsAllowlist: + idp_urls = getElementFromShadowRoot( + driver, group, 'div.policy.row > div.value').text + if idp_urls: + logging.info(f'idp_urls = {idp_urls}') + found_idp_urls = True + break + if found_idp_urls: + break + time.sleep(6) + except StaleElementReferenceException: + logging.info('StaleElementReferenceException happened, skip rest') + status_box = driver.find_element_by_css_selector('status-box') + el = getElementFromShadowRoot(driver, status_box, 'fieldset') + device_id = el.find_element_by_class_name( + 'machine-enrollment-device-id').text + # idp_urls could be of '["http://abc", "http://def"]' + # remove the excess {[, ], ", '} + idp_urls = idp_urls.translate({ord(i): None for i in '[]\"\''}) + for url in idp_urls.split(','): + if re.search(FLAGS.idp_matcher, url): + idp_url = url + break + + # Step 3: visit IdP homepage + logging.info(f'fake_idp:{idp_url}') + result['FakeIdP'] = idp_url + result['DeviceId'] = device_id + driver.get(idp_url) + WebDriverWait(driver=driver, timeout=10) + # artificially wait for another 3 seconds + time.sleep(3) + driver.find_element_by_xpath('//*[@id="content"]/div[2]/a').click() + + # Step 4: Check for signals + WebDriverWait(driver=driver, timeout=10) + try: + server_signals = json.loads( + driver.find_element_by_xpath('//*[@id="serverSignals"]').text) + + client_signals = json.loads( + driver.find_element_by_xpath('//*[@id="clientSignals"]').text) + result['ClientSignals'] = client_signals + result['ServerSignals'] = server_signals + except NoSuchElementException: + logging.info('No such element found! trying to find error message') + err_msg = json.loads( + driver.find_element_by_xpath('//*[@id="errorMessage"]/pre').text) + logging.info('error: %s' % err_msg) + result['SignalError'] = err_msg + + # Step 5: check histogram + hg = poll_histogram(driver, [ + 'Enterprise.DeviceTrust.Persistence.StoreKeyPair.Error', + 'Enterprise.DeviceTrust.Persistence.LoadKeyPair.Error', + 'Enterprise.DeviceTrust.Persistence.CreateKeyPair.Error', + 'Enterprise.DeviceTrust.RotateSigningKey.NoNonce.Status', + 'Enterprise.DeviceTrust.RotateSigningKey.NoNonce.UploadCode', + 'Enterprise.DeviceTrust.ManagementService.Error', + 'Enterprise.DeviceTrust.Attestation.Result', + 'Enterprise.DeviceTrust.KeyRotationCommand.Error', + 'Enterprise.DeviceTrust.KeyRotationCommand.Error.Hresult', + 'Enterprise.DeviceTrust.KeyRotationCommand.ExitCode', + ]) + if hg: + result['Histograms'] = hg + + results[test_case] = result + shutdown_chrome() + + except Exception as error: + logging.info('test_case: %s, result dict: %s' % (test_case, result)) + logging.error(error) + traceback.print_exc() + save_screenshot(driver, r'c:\temp\screen.png') + finally: + driver.quit() + # Replace single quotes inside string to double quotes in order + # facilitates json.loads() method call. Single quotes are not + # JSON specification - RFC7159 compatible. + logging.info(f'Results:{json.dumps(results)}') + + +if __name__ == '__main__': + app.run(main)
diff --git a/chrome/test/enterprise/e2e/connector/common/realtime_reporting_ui_test.py b/chrome/test/enterprise/e2e/connector/common/realtime_reporting_ui_test.py index 747f4fe..f63888f 100644 --- a/chrome/test/enterprise/e2e/connector/common/realtime_reporting_ui_test.py +++ b/chrome/test/enterprise/e2e/connector/common/realtime_reporting_ui_test.py
@@ -5,6 +5,7 @@ import logging import json import time + from absl import app from pywinauto.application import Application from selenium import webdriver
diff --git a/chrome/test/enterprise/e2e/connector/device_trust_connector/__init__.py b/chrome/test/enterprise/e2e/connector/device_trust_connector/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/chrome/test/enterprise/e2e/connector/device_trust_connector/__init__.py
diff --git a/chrome/test/enterprise/e2e/connector/device_trust_connector/device_trust_connector_windows_enrollment_test.py b/chrome/test/enterprise/e2e/connector/device_trust_connector/device_trust_connector_windows_enrollment_test.py new file mode 100644 index 0000000..4be4095 --- /dev/null +++ b/chrome/test/enterprise/e2e/connector/device_trust_connector/device_trust_connector_windows_enrollment_test.py
@@ -0,0 +1,94 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from datetime import datetime +import json +import logging +import os +import re +import time +from typing import Any + +from chrome_ent_test.infra.core import before_all +from chrome_ent_test.infra.core import category +from chrome_ent_test.infra.core import environment +from chrome_ent_test.infra.core import test + +from infra import ChromeEnterpriseTestCase + + +def parse_to_json(source: str, pattern: str) -> Any: + """Matches string with a regex and loads to a Json object.""" + matcher = re.search(pattern, source) + if matcher: + json_string = matcher.group(0) + return json.loads(json_string) + return None + + +@category('chrome_only') +@environment(file='../connector_test.asset.textpb') +class DeviceTrustConnectorWindowsEnrollmentTest(ChromeEnterpriseTestCase): + + @before_all + def setup(self): + self.InstallChrome(self.win_config['client'], system_level=True) + self.InstallGoogleUpdater(self.win_config['client']) + self.WakeGoogleUpdater(self.win_config['client']) + self.AddFirewallExclusion(self.win_config['client']) + self.EnableUITest(self.win_config['client']) + + @test + def test_device_trust_enrollment(self): + # To match for the right IdP site when there are multiple present + idp_matcher = '^[htps]+[:/]+staging-.*' + eventFound = False + path = 'gs://%s/secrets/CELabOrg-devicetrust-enrollToken' % self.gsbucket + cmd = r'gsutil cat ' + path + token = self.RunCommand(self.win_config['dc'], cmd).rstrip().decode() + # Enable two Policies + self.SetPolicy(self.win_config['dc'], r'CloudManagementEnrollmentToken', + token, 'String') + + self.SetPolicy(self.win_config['dc'], r'SafeBrowsingEnabled', 1, 'DWORD') + self.RunCommand(self.win_config['client'], 'gpupdate /force') + + # Schedule to run device_trust_ui_test on GCP VM machines + commonDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + output = self.RunUITest( + self.win_config['client'], + os.path.join(commonDir, 'common', 'device_trust_ui_test.py'), + timeout=600, + args=[ + '--idp_matcher', + idp_matcher, + '--alsologtostderr', + ]) + + # Assert on the information retrieved from output + results = parse_to_json(output, '(?<=Results:).*') + self.assertIsNotNone(results) + keys = ['key_creation', 'key_load'] + for key in keys: + logging.info('Test case: %s' % key) + result = results[key] + self.assertEqual(result['DTCPolicyEnabled'], 'true') + self.assertEqual(result['KeyManagerInitialized'], 'true') + self.assertTrue('200' in result['KeySync']) + logging.info('key_sync: %s' % result['KeySync']) + self.assertFalse('UNKNOWN' in result['KeyTrustLevel']) + logging.info('key_trust_level: %s' % result['KeyTrustLevel']) + self.assertIsNotNone(result['SpkiHash']) + logging.info('device_hash: %s' % result['SpkiHash']) + # self.assertTrue(result['HistogramSuccess']) + self.assertIsNotNone(result['FakeIdP']) + self.assertIsNotNone(result['Histograms']) + client = result['ClientSignals'] + server = result['ServerSignals'] + self.assertEqual(client['deviceEnrollmentDomain'], 'beyondcorp.bigr.name') + self.assertEqual(client['safeBrowsingProtectionLevel'], 1) + self.assertEqual(server['keyTrustLevel'], 'CHROME_BROWSER_HW_KEY') + self.assertIsNotNone(server['devicePermanentId']) + + self.RemoveDeviceTrustKey(self.win_config['client'])
diff --git a/chrome/test/enterprise/e2e/connector/reporting_connector_pan/pan_api_service.py b/chrome/test/enterprise/e2e/connector/reporting_connector_pan/pan_api_service.py index 4b15ae52..02f63eff 100644 --- a/chrome/test/enterprise/e2e/connector/reporting_connector_pan/pan_api_service.py +++ b/chrome/test/enterprise/e2e/connector/reporting_connector_pan/pan_api_service.py
@@ -15,6 +15,7 @@ from .pan_event import PanEvent + # Constants SUCCESS = 0 PENDING = 1
diff --git a/chrome/test/enterprise/e2e/infra/chrome_ent_test_case.py b/chrome/test/enterprise/e2e/infra/chrome_ent_test_case.py index d5cb91e61..232651d0 100644 --- a/chrome/test/enterprise/e2e/infra/chrome_ent_test_case.py +++ b/chrome/test/enterprise/e2e/infra/chrome_ent_test_case.py
@@ -49,30 +49,63 @@ # Current Win Server version for testing win_config = win_2016_config + def AddFirewallExclusion(self, instance_name): + """Add-MpPreference to exclude some folders from defenser scan.""" + program_file = '"$Env:ProgramFiles"' + program_file_x86 = '"$Env:ProgramFiles(x86)"' + local_appdata = '"$Env:LOCALAPPDATA"' + celab_path = r'"c:\cel\supporting_files"' + updater_path = r'"c:\temp"' + cmd = (r'Add-MpPreference -ExclusionPath ' + ', '.join([ + program_file, program_file_x86, local_appdata, celab_path, updater_path + ])) + self.clients[instance_name].RunPowershell(cmd) + def InstallGoogleUpdater(self, instance_name): """Install Omaha4 client on VM.""" - if not FLAGS.omaha_updater or not FLAGS.omaha_installer: + if not FLAGS.omaha_installer: # No omaha installer/updater. Do nothing. - logging.debug('Either --omaha_updater or --omaha_installer flag is empty.' + logging.debug('--omaha_installer flag is empty.' 'Skip installing google updater.') return cmd = r'New-Item -ItemType Directory -Force -Path c:\temp' self.clients[instance_name].RunPowershell(cmd) installer = self.UploadFile(instance_name, FLAGS.omaha_installer, r'c:\temp') - updater = self.UploadFile(instance_name, FLAGS.omaha_updater, r'c:\temp') cmd = installer + r' --install --system' self.RunCommand(instance_name, cmd) - cmd = updater + r' --wake' + def WakeGoogleUpdater(self, instance_name): + """Runs updater.exe to wake up Omaha 4 service.""" + if not FLAGS.omaha_updater: + logging.debug('--omaha_updater flag is empty.' 'Skip run google updater.') + return + + updater = self.UploadFile(instance_name, FLAGS.omaha_updater, r'c:\temp') + cmd = ( + updater + r' --wake' + r' --enable-logging' + + r' --vmodule=*/components/winhttp/*=2,*/components/update_client/*=2,' + r'*/chrome/updater/*=2') self.RunCommand(instance_name, cmd) - def InstallChrome(self, instance_name): + def InstallChrome(self, instance_name, system_level=False): """Installs chrome. Currently supports two types of installer: - mini_installer.exe, and - *.msi + + system_level is False by default for all reporting connector + e2e tests as it does not need Omaha client to be installed. + For DTC e2e test, however, + system_level should be set True so that it will be installed together + with Omaha 4 client and then call powershell script to add + chrome path to $Env:Path. + + Args: + instance_name: the gcp instance. + system_level: whether the chrome install with --system-level + or not. By default, the value is False. """ cmd = r'New-Item -ItemType Directory -Force -Path c:\temp' self.clients[instance_name].RunPowershell(cmd) @@ -83,7 +116,12 @@ dir = os.path.dirname(os.path.abspath(__file__)) self.UploadFile(instance_name, os.path.join(dir, 'installer_data'), r'c:\temp') - cmd = file_name + r' --installerdata=c:\temp\installer_data' + if system_level: + cmd = ( + file_name + r' --installerdata=c:\temp\installer_data' + + r' --system-level') + else: + cmd = file_name + r' --installerdata=c:\temp\installer_data' else: cmd = 'msiexec /i %s' % file_name @@ -93,6 +131,9 @@ r'powershell -File c:\cel\supporting_files\ensure_chromium_api_keys.ps1' r' -Path gs://%s/api/key') % self.gsbucket self.RunCommand(instance_name, cmd) + if system_level: + cmd = r'powershell -File c:\cel\supporting_files\add_chrome_path.ps1' + self.RunCommand(instance_name, cmd) def SetPolicy(self, instance_name, policy_name, policy_value, policy_type): r"""Sets a Google Chrome policy in registry. @@ -120,9 +161,21 @@ key, policy_name, policy_value, policy_type) self.clients[instance_name].RunPowershell(cmd) + def RemoveDeviceTrustKey(self, instance_name): + """Removes a device trust key in registry. + + Args: + instance_name: the name of the GCP VM machine. + """ + cmd = (r'Remove-Item -Path HKLM:\SOFTWARE\Google\Chrome\DeviceTrust ' + '-Force -Verbose') + self.clients[instance_name].RunPowershell(cmd) + def RemovePolicy(self, instance_name, policy_name): """Removes a Google Chrome policy in registry. + Args: + instance_name: the name of the GCP VM machine. policy_name: the policy name. """ segments = policy_name.split('\\') @@ -144,7 +197,7 @@ self.RunCommand(instance_name, r'md -Force c:\temp') self.EnsurePythonInstalled(instance_name) self.InstallPipPackagesLatest(instance_name, - ['selenium', 'absl-py', 'pywin32']) + ['selenium', 'absl-py', 'pywin32', 'attrs']) temp_dir = 'C:\\temp\\' if FLAGS.chromedriver is None: @@ -197,6 +250,9 @@ # upload the test file_name = self.UploadFile(instance_name, test_file, r'c:\temp') + # check for cel_ui_agent.exe running + self._checkUIAgentRunningOnInstance(instance_name) + # run the test. # note that '-u' flag is passed to enable unbuffered stdout and stderr. # Without this flag, if the test is killed because of timeout, we will not @@ -219,6 +275,9 @@ random.shuffle(s) return ''.join(s) + def _checkUIAgentRunningOnInstance(self, instance_name): + self.RunCommand(instance_name, 'tasklist | findstr cel_ui_agent.exe') + def _rebootInstance(self, instance_name): self.RunCommand(instance_name, 'shutdown /r /t 0') @@ -234,14 +293,14 @@ self.InstallPipPackagesLatest(instance_name, ['pywinauto', 'pyperclip', 'requests']) - password = self._generatePassword() - user_name = 'ui_user' + ui_test_user = 'ui_user' + ui_test_password = self._generatePassword() cmd = (r'powershell -File c:\cel\supporting_files\enable_auto_logon.ps1 ' - r'-userName %s -password %s') % (user_name, password) + r'-userName %s -password %s') % (ui_test_user, ui_test_password) self.RunCommand(instance_name, cmd) self._rebootInstance(instance_name) cmd = (r'powershell -File c:\cel\supporting_files\set_ui_agent.ps1 ' - '-username %s') % user_name + '-username %s') % ui_test_user self.RunCommand(instance_name, cmd) self._rebootInstance(instance_name)
diff --git a/chrome/test/enterprise/e2e/infra/test_util.py b/chrome/test/enterprise/e2e/infra/test_util.py index 0cef7b4..73c0d3fd 100644 --- a/chrome/test/enterprise/e2e/infra/test_util.py +++ b/chrome/test/enterprise/e2e/infra/test_util.py
@@ -44,6 +44,7 @@ def getElementFromShadowRoot(driver, element, selector): + """Gets a first matched WebElement from ShadowRoot.""" if element is None: return None else: @@ -52,6 +53,16 @@ selector) +def getElementsFromShadowRoot(driver, element, selector): + """Gets a list of matched WebElements from ShadowRoot. """ + if element is None: + return None + else: + return driver.execute_script( + "return arguments[0].shadowRoot.querySelectorAll(arguments[1])", + element, selector) + + def create_chrome_webdriver(chrome_options=None, incognito=False, prefs=None): """Configures and returns a Chrome WebDriver object."
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h index 19451a1..b5233011 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.h +++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -40,11 +40,19 @@ } } +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Global media controls aren't supported in lacros. +#define INSTANTIATE_MEDIA_ROUTER_INTEGRATION_BROWER_TEST_SUITE(name) \ + INSTANTIATE_TEST_SUITE_P(/* no prefix */, name, \ + testing::Values(UiForBrowserTest::kCast), \ + testing::PrintToStringParamName()) +#else #define INSTANTIATE_MEDIA_ROUTER_INTEGRATION_BROWER_TEST_SUITE(name) \ INSTANTIATE_TEST_SUITE_P( \ /* no prefix */, name, \ testing::Values(UiForBrowserTest::kCast, UiForBrowserTest::kGmc), \ testing::PrintToStringParamName()) +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) // Macro used to skip tests that are only supported with the Cast dialog. //
diff --git a/chrome/updater/app/server/posix/app_server_posix.cc b/chrome/updater/app/server/posix/app_server_posix.cc index 48fd379..0f036e6 100644 --- a/chrome/updater/app/server/posix/app_server_posix.cc +++ b/chrome/updater/app/server/posix/app_server_posix.cc
@@ -78,7 +78,9 @@ } bool AppServerPosix::SwapInNewVersion() { - return PromoteCandidate(updater_scope()) == kErrorOk; + int result = PromoteCandidate(updater_scope()); + VLOG_IF(1, result != kErrorOk) << __func__ << " failed: " << result; + return result == kErrorOk; } } // namespace updater
diff --git a/chrome/updater/branding.gni b/chrome/updater/branding.gni index 0ae9753..09d355a 100644 --- a/chrome/updater/branding.gni +++ b/chrome/updater/branding.gni
@@ -10,7 +10,7 @@ crash_product_name = "Update4" crash_upload_url = "https://clients2.google.com/cr/report" help_center_url = "http://support.google.com/installer/" - app_logo_url = "https://dl.google.com/update2/testing/icons/" + app_logo_url = "https://dl.google.com/update2/installers/icons/" keystone_app_name = "GoogleSoftwareUpdate" mac_browser_bundle_identifier = "com.google.Chrome" mac_updater_bundle_identifier = "com.google.GoogleUpdater" @@ -28,7 +28,7 @@ crash_product_name = "ChromiumUpdater" crash_upload_url = "https://clients2.google.com/cr/staging_report" help_center_url = "http://support.google.com/installer/" - app_logo_url = "https://dl.google.com/update2/testing/icons/" + app_logo_url = "https://dl.google.com/update2/installers/icons/" keystone_app_name = "ChromiumSoftwareUpdate" mac_browser_bundle_identifier = "org.chromium.Chromium" mac_updater_bundle_identifier = "org.chromium.ChromiumUpdater"
diff --git a/chrome/updater/ipc/update_service_internal_proxy_win.cc b/chrome/updater/ipc/update_service_internal_proxy_win.cc index c30471b..08a232c 100644 --- a/chrome/updater/ipc/update_service_internal_proxy_win.cc +++ b/chrome/updater/ipc/update_service_internal_proxy_win.cc
@@ -23,7 +23,6 @@ #include "chrome/updater/util/util.h" #include "chrome/updater/util/win_util.h" #include "chrome/updater/win/win_constants.h" -#include "third_party/abseil-cpp/absl/types/variant.h" namespace updater { namespace {
diff --git a/chrome/updater/ipc/update_service_proxy_win.cc b/chrome/updater/ipc/update_service_proxy_win.cc index 178015f..01a9aa3 100644 --- a/chrome/updater/ipc/update_service_proxy_win.cc +++ b/chrome/updater/ipc/update_service_proxy_win.cc
@@ -34,7 +34,6 @@ #include "chrome/updater/util/win_util.h" #include "chrome/updater/win/win_constants.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/abseil-cpp/absl/types/variant.h" namespace updater { namespace {
diff --git a/chrome/updater/linux/setup/setup.cc b/chrome/updater/linux/setup/setup.cc index 55c6f2e..9c41278 100644 --- a/chrome/updater/linux/setup/setup.cc +++ b/chrome/updater/linux/setup/setup.cc
@@ -32,7 +32,7 @@ if (!dest_path) { return kErrorFailedToGetVersionedInstallDirectory; } - dest_path = dest_path->AppendASCII(kExecutableName); + dest_path = dest_path->Append(GetExecutableRelativePath()); base::FilePath exe_path; if (!base::PathService::Get(base::FILE_EXE, &exe_path)) {
diff --git a/chrome/updater/mac/setup/setup.mm b/chrome/updater/mac/setup/setup.mm index 36fbc4e..87d0b47 100644 --- a/chrome/updater/mac/setup/setup.mm +++ b/chrome/updater/mac/setup/setup.mm
@@ -35,6 +35,7 @@ #include "chrome/updater/setup.h" #include "chrome/updater/updater_branding.h" #include "chrome/updater/updater_scope.h" +#include "chrome/updater/updater_version.h" #include "chrome/updater/util/launchd_util.h" #import "chrome/updater/util/mac_util.h" #import "chrome/updater/util/posix_util.h" @@ -247,19 +248,18 @@ GetUpdaterExecutablePath(scope); const absl::optional<base::FilePath> install_dir = GetBaseInstallDirectory(scope); - const absl::optional<base::FilePath> versioned_path = - GetVersionedInstallDirectory(scope); const absl::optional<base::FilePath> bundle_path = GetUpdaterAppBundlePath(scope); - if (!updater_executable_path || !install_dir || !versioned_path || - !bundle_path) { + if (!updater_executable_path || !install_dir || !bundle_path) { return kErrorFailedToGetVersionedInstallDirectory; } // Update the launcher sym link. base::FilePath tmp_launcher_name = install_dir->Append("NewCurrent"); - if (symlink(versioned_path->value().c_str(), - tmp_launcher_name.value().c_str())) { + if (!base::DeleteFile(tmp_launcher_name)) { + VLOG(1) << "Failed to delete existing " << tmp_launcher_name.value(); + } + if (symlink(kUpdaterVersion, tmp_launcher_name.value().c_str())) { return kErrorFailedToLinkLauncher; } if (rename(tmp_launcher_name.value().c_str(), @@ -270,7 +270,8 @@ base::FilePath path = bundle_path->Append("Contents").Append("Helpers").Append("launcher"); struct stat info; - if (stat(path.value().c_str(), &info) || info.st_uid || + if (lstat(path.value().c_str(), &info) || info.st_uid || + !(S_IFREG & info.st_mode) || lchmod(path.value().c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH | S_ISUID)) { VPLOG(1) << "Launcher lchmod failed. Cross-user on-demand will not work";
diff --git a/chrome/updater/run_all_unittests.cc b/chrome/updater/run_all_unittests.cc index 534fdb9..a43532d 100644 --- a/chrome/updater/run_all_unittests.cc +++ b/chrome/updater/run_all_unittests.cc
@@ -26,11 +26,9 @@ #include <memory> #include <string> -#include "base/base_paths.h" #include "base/path_service.h" #include "base/win/registry.h" #include "base/win/scoped_com_initializer.h" -#include "base/win/windows_version.h" #include "chrome/installer/util/scoped_token_privilege.h" #include "chrome/updater/util/win_util.h" @@ -166,12 +164,6 @@ MaybeIncreaseTestTimeouts(argc, argv); #if BUILDFLAG(IS_WIN) - // TODO(crbug.com/1406309) - this can be deleted once BuildBot removes the - // Windows 7 testers. - if (base::win::GetVersion() < base::win::Version::WIN10) { - LOG(ERROR) << "Tests didn't run because of an unsupported Windows version."; - return 0; - } updater::test::MaybeExcludePathsFromWindowsDefender(); VLOG(0) << "Process priority: " << base::Process::Current().GetPriority();
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc index 14388c8a..82f4f81a 100644 --- a/chrome/updater/test/integration_tests_impl.cc +++ b/chrome/updater/test/integration_tests_impl.cc
@@ -326,8 +326,9 @@ void CopyLog(const base::FilePath& src_dir) { // TODO(crbug.com/1159189): copy other test artifacts. base::FilePath dest_dir = GetLogDestinationDir(); + const base::FilePath log_path = src_dir.AppendASCII("updater.log"); if (!dest_dir.empty() && base::PathExists(dest_dir) && - base::PathExists(src_dir)) { + base::PathExists(log_path)) { dest_dir = dest_dir.AppendASCII(GetTestName()); EXPECT_TRUE(base::CreateDirectory(dest_dir)); const base::FilePath dest_file_path = [dest_dir]() { @@ -337,7 +338,6 @@ } return path; }(); - const base::FilePath log_path = src_dir.AppendASCII("updater.log"); VLOG(0) << "Copying updater.log file. From: " << log_path << ". To: " << dest_file_path; EXPECT_TRUE(base::CopyFile(log_path, dest_file_path));
diff --git a/chrome/updater/test/integration_tests_linux.cc b/chrome/updater/test/integration_tests_linux.cc index bd28d7b..9cecde3 100644 --- a/chrome/updater/test/integration_tests_linux.cc +++ b/chrome/updater/test/integration_tests_linux.cc
@@ -69,7 +69,8 @@ return WaitFor( base::BindRepeating( [](UpdaterScope scope) { - return !base::NamedProcessIterator(kExecutableName, nullptr) + return !base::NamedProcessIterator( + GetExecutableRelativePath().MaybeAsASCII(), nullptr) .NextProcessEntry() && !base::NamedProcessIterator(kLauncherName, nullptr) .NextProcessEntry();
diff --git a/chrome/updater/util/linux_util.cc b/chrome/updater/util/linux_util.cc index 1d9c8cab..f1ab24d9 100644 --- a/chrome/updater/util/linux_util.cc +++ b/chrome/updater/util/linux_util.cc
@@ -7,6 +7,7 @@ #include "base/base_paths.h" #include "base/files/file_path.h" #include "base/path_service.h" +#include "base/strings/strcat.h" #include "chrome/updater/constants.h" #include "chrome/updater/updater_branding.h" #include "chrome/updater/updater_scope.h" @@ -39,7 +40,7 @@ } base::FilePath GetExecutableRelativePath() { - return base::FilePath(kExecutableName); + return base::FilePath(base::StrCat({kExecutableName, kExecutableSuffix})); } absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) {
diff --git a/chrome/updater/win/installer/installer.ico b/chrome/updater/win/installer/installer.ico index 5ecfcbd..8420f53 100644 --- a/chrome/updater/win/installer/installer.ico +++ b/chrome/updater/win/installer/installer.ico Binary files differ
diff --git a/chromecast/android/lint-baseline.xml b/chromecast/android/lint-baseline.xml index 4aeae9d..200481c 100644 --- a/chromecast/android/lint-baseline.xml +++ b/chromecast/android/lint-baseline.xml
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.0.0-alpha10" type="baseline" client="" dependencies="true" name="" variant="all" version="8.0.0-alpha10"> +<issues format="6" by="lint 8.1.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.1.0-alpha01"> <issue id="MissingVersion" @@ -24,6 +24,17 @@ </issue> <issue + id="UnspecifiedRegisterReceiverFlag" + message="`mReceiver` \
is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected \
broadcasts registered for an IntentFilter that cannot be inspected by lint" + errorLine1=" mContext.registerReceiver(mReceiver, filter);" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="../../chromecast/browser/android/apk/src/org/chromium/chromecast/shell/BroadcastReceiverScope.java" + line="37" + column="9"/> + </issue> + + <issue id="Overdraw" message="Possible overdraw: Root element paints background `#FFFFFF` with a theme that also paints a background (inferred theme is `@style/CastShellTheme`)" errorLine1=" android:background="#FFFFFF""
diff --git a/chromecast/browser/test/DEPS b/chromecast/browser/test/DEPS index b969a40..c1430ea 100644 --- a/chromecast/browser/test/DEPS +++ b/chromecast/browser/test/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+content/public/test", + "+media/cdm/clear_key_cdm_common.h", ]
diff --git a/chromecast/browser/test/cast_navigation_browsertest.cc b/chromecast/browser/test/cast_navigation_browsertest.cc index e570c41..57a7eb4 100644 --- a/chromecast/browser/test/cast_navigation_browsertest.cc +++ b/chromecast/browser/test/cast_navigation_browsertest.cc
@@ -9,6 +9,7 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "media/base/test_data_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "url/gurl.h" #include "url/url_constants.h" @@ -19,7 +20,6 @@ const char16_t kError[] = u"ERROR"; const char16_t kFailed[] = u"FAILED"; -const char kClearKeyKeySystem[] = "org.w3.clearkey"; const char kWebMAudioOnly[] = "audio/webm; codecs=\"vorbis\""; } @@ -108,7 +108,8 @@ #endif IN_PROC_BROWSER_TEST_F(CastNavigationBrowserTest, ClearKeySupport) { - PlayEncryptedMedia(kClearKeyKeySystem, kWebMAudioOnly, "bear-a_enc-a.webm"); + PlayEncryptedMedia(media::kClearKeyKeySystem, kWebMAudioOnly, + "bear-a_enc-a.webm"); } } // namespace shell
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 1a00fac..c99b674 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -15326.0.0 \ No newline at end of file +15328.0.0 \ No newline at end of file
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc index 25c0234..1b13700 100644 --- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc +++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.cc
@@ -378,7 +378,8 @@ } void FakeSessionManagerClient::StartRemoteDeviceWipe( - const enterprise_management::SignedData& signed_command) { + const enterprise_management::SignedData& signed_command, + enterprise_management::PolicyFetchRequest::SignatureType signature_type) { start_device_wipe_call_count_++; if (!on_start_device_wipe_callback_.is_null()) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
diff --git a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h index 57a2fa5..dcf23ef 100644 --- a/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h +++ b/chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h
@@ -16,6 +16,7 @@ #include "base/time/time.h" #include "chromeos/ash/components/dbus/arc/arc.pb.h" #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h" +#include "components/policy/proto/device_management_backend.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { @@ -99,7 +100,9 @@ const cryptohome::AccountIdentifier& cryptohome_id) override; void StartDeviceWipe() override; void StartRemoteDeviceWipe( - const enterprise_management::SignedData& signed_command) override; + const enterprise_management::SignedData& signed_command, + enterprise_management::PolicyFetchRequest::SignatureType signature_type) + override; void ClearForcedReEnrollmentVpd( chromeos::VoidDBusMethodCallback callback) override; void UnblockDevModeForEnrollment(
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc index 55c4dfa..759630f 100644 --- a/chromeos/ash/components/dbus/session_manager/session_manager_client.cc +++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.cc
@@ -368,12 +368,15 @@ } void StartRemoteDeviceWipe( - const enterprise_management::SignedData& signed_command) override { + const enterprise_management::SignedData& signed_command, + enterprise_management::PolicyFetchRequest::SignatureType signature_type) + override { dbus::MethodCall method_call( login_manager::kSessionManagerInterface, login_manager::kSessionManagerStartRemoteDeviceWipe); dbus::MessageWriter writer(&method_call); writer.AppendProtoAsArrayOfBytes(signed_command); + writer.AppendByte(signature_type); session_manager_proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::DoNothing());
diff --git a/chromeos/ash/components/dbus/session_manager/session_manager_client.h b/chromeos/ash/components/dbus/session_manager/session_manager_client.h index 76f2a05..116a4b0 100644 --- a/chromeos/ash/components/dbus/session_manager/session_manager_client.h +++ b/chromeos/ash/components/dbus/session_manager/session_manager_client.h
@@ -14,6 +14,7 @@ #include "base/observer_list.h" #include "base/time/time.h" #include "chromeos/dbus/common/dbus_method_call_status.h" +#include "components/policy/proto/device_management_backend.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/cros_system_api/dbus/login_manager/dbus-constants.h" @@ -242,8 +243,19 @@ // Starts a remotely initiated factory reset, similar to |StartDeviceWipe| // above, but also performs additional checks on Chrome OS side. + // session_manager validates |signed_command| against |signature_type| + // algorithm. + // + // If the device is not managed by AD, session_manager does not expect + // unsigned remote commands or em::PolicyFetchRequest::NONE as + // |signature_type|. + // If managed by AD, unsigned powerwash requests and + // em::PolicyFetchRequest::NONE signature type are allowed, and any extra + // validation checks are skipped. virtual void StartRemoteDeviceWipe( - const enterprise_management::SignedData& signed_command) = 0; + const enterprise_management::SignedData& signed_command, + enterprise_management::PolicyFetchRequest::SignatureType + signature_type) = 0; // Set the block_demode and check_enrollment flags to 0 in the VPD. virtual void ClearForcedReEnrollmentVpd(
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc index 0e3df51..5d68f2f 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
@@ -673,60 +673,6 @@ } } -void FakeUserDataAuthClient::GetKeyData( - const ::user_data_auth::GetKeyDataRequest& request, - GetKeyDataCallback callback) { - ::user_data_auth::GetKeyDataReply reply; - ReplyOnReturn auto_reply(&reply, std::move(callback)); - - // Check if user exists. - const auto user_it = users_.find(request.account_id()); - if (user_it == std::end(users_)) { - LOG(ERROR) << "User does not exist: " << request.account_id().account_id(); - reply.set_error(CryptohomeErrorCode::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND); - return; - } - const UserCryptohomeState& user_state = user_it->second; - - const std::string& requested_label = - request.authorization_request().key().data().label(); - - // Create range [factors_begin, factors_end) of factors matching - // `requested_label`: If the `requested_label` is empty, then every factor - // matches. Otherwise the factor with that precise label matches. If no such - // factor exists, the range is empty. - auto factors_begin = std::begin(user_state.auth_factors); - auto factors_end = std::end(user_state.auth_factors); - if (!requested_label.empty()) { - factors_begin = user_state.auth_factors.find(requested_label); - if (factors_begin != factors_end) { - factors_end = std::next(factors_begin); - } - } - - // Fill `reply.key_data()` with the factors we found. - for (auto factors_it = factors_begin; factors_it != factors_end; - ++factors_it) { - const std::string& label = factors_it->first; - const FakeAuthFactor& factor = factors_it->second; - - absl::optional<cryptohome::KeyData> key_data = - FakeAuthFactorToKeyData(label, factor); - if (key_data.has_value()) { - reply.mutable_key_data()->Add(std::move(*key_data)); - } else { - LOG(WARNING) << "Ignoring auth factor incompatible with legacy API: " - << label; - } - } - - if (reply.key_data().empty()) { - // This happens if no or only unsupported factors matched the request. - LOG(ERROR) << "No legacy key exists for label " << requested_label; - reply.set_error(CryptohomeErrorCode::CRYPTOHOME_ERROR_KEY_NOT_FOUND); - } -} - void FakeUserDataAuthClient::CheckKey( const ::user_data_auth::CheckKeyRequest& request, CheckKeyCallback callback) { @@ -755,57 +701,6 @@ } } -void FakeUserDataAuthClient::AddKey( - const ::user_data_auth::AddKeyRequest& request, - AddKeyCallback callback) { - ::user_data_auth::AddKeyReply reply; - ReplyOnReturn auto_reply(&reply, std::move(callback)); - - const cryptohome::AccountIdentifier& account_id = request.account_id(); - const bool clobber_if_exists = request.clobber_if_exists(); - const cryptohome::Key& new_key = request.key(); - - auto user_it = users_.find(account_id); - if (user_it == std::end(users_)) { - // TODO(crbug.com/1334538): Cryptohome would not create a new user here, - // but many tests rely on it. New tests shouldn't rely on this behavior. - LOG(ERROR) << "Need to create new user: " << account_id.account_id(); - user_it = users_.insert(user_it, {account_id, UserCryptohomeState()}); - } - DCHECK(user_it != std::end(users_)); - UserCryptohomeState& user_state = user_it->second; - - auto [new_label, new_factor] = - KeyToFakeAuthFactor(new_key, enable_auth_check_); - CHECK(clobber_if_exists || !user_state.auth_factors.contains(new_label)) - << "Key exists, will not clobber: " << new_label; - user_state.auth_factors[std::move(new_label)] = std::move(new_factor); -} -void FakeUserDataAuthClient::RemoveKey( - const ::user_data_auth::RemoveKeyRequest& request, - RemoveKeyCallback callback) { - ::user_data_auth::RemoveKeyReply reply; - ReplyOnReturn auto_reply(&reply, std::move(callback)); - - const auto user_it = users_.find(request.account_id()); - if (user_it == std::end(users_)) { - // TODO(crbug.com/1334538): Cryptohome would report an error here, but many - // tests do not set up users before calling RemoveKey. That's why we don't - // report an error here. New tests shouldn't rely on this behavior. - LOG(ERROR) << "User does not exist: " << request.account_id().account_id(); - return; - } - UserCryptohomeState& user_state = user_it->second; - - const std::string& label = request.key().data().label(); - if (label.empty()) { - // An empty request label matches all keys, so remove all. - LOG(WARNING) << "RemoveKey for empty label removes all keys"; - user_state.auth_factors.clear(); - } else { - user_state.auth_factors.erase(label); - } -} void FakeUserDataAuthClient::StartFingerprintAuthSession( const ::user_data_auth::StartFingerprintAuthSessionRequest& request, StartFingerprintAuthSessionCallback callback) {
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h index 5c90a23..22ce2724 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
@@ -192,14 +192,8 @@ UnmountCallback callback) override; void Remove(const ::user_data_auth::RemoveRequest& request, RemoveCallback callback) override; - void GetKeyData(const ::user_data_auth::GetKeyDataRequest& request, - GetKeyDataCallback callback) override; void CheckKey(const ::user_data_auth::CheckKeyRequest& request, CheckKeyCallback callback) override; - void AddKey(const ::user_data_auth::AddKeyRequest& request, - AddKeyCallback callback) override; - void RemoveKey(const ::user_data_auth::RemoveKeyRequest& request, - RemoveKeyCallback callback) override; void StartFingerprintAuthSession( const ::user_data_auth::StartFingerprintAuthSessionRequest& request, StartFingerprintAuthSessionCallback callback) override;
diff --git a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h index 993ff1e..0c13fc0 100644 --- a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
@@ -42,25 +42,10 @@ RemoveCallback callback), (override)); MOCK_METHOD(void, - GetKeyData, - (const ::user_data_auth::GetKeyDataRequest& request, - GetKeyDataCallback callback), - (override)); - MOCK_METHOD(void, CheckKey, (const ::user_data_auth::CheckKeyRequest& request, CheckKeyCallback callback), (override)); - MOCK_METHOD(void, - AddKey, - (const ::user_data_auth::AddKeyRequest& request, - AddKeyCallback callback), - (override)); - MOCK_METHOD(void, - RemoveKey, - (const ::user_data_auth::RemoveKeyRequest& request, - RemoveKeyCallback callback), - (override)); MOCK_METHOD( void, StartFingerprintAuthSession,
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc index 4c9d752..535bd81 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc
@@ -124,13 +124,6 @@ std::move(callback)); } - void GetKeyData(const ::user_data_auth::GetKeyDataRequest& request, - GetKeyDataCallback callback) override { - CallProtoMethod(::user_data_auth::kGetKeyData, - ::user_data_auth::kUserDataAuthInterface, request, - std::move(callback)); - } - void CheckKey(const ::user_data_auth::CheckKeyRequest& request, CheckKeyCallback callback) override { CallProtoMethod(::user_data_auth::kCheckKey, @@ -138,20 +131,6 @@ std::move(callback)); } - void AddKey(const ::user_data_auth::AddKeyRequest& request, - AddKeyCallback callback) override { - CallProtoMethod(::user_data_auth::kAddKey, - ::user_data_auth::kUserDataAuthInterface, request, - std::move(callback)); - } - - void RemoveKey(const ::user_data_auth::RemoveKeyRequest& request, - RemoveKeyCallback callback) override { - CallProtoMethod(::user_data_auth::kRemoveKey, - ::user_data_auth::kUserDataAuthInterface, request, - std::move(callback)); - } - void StartFingerprintAuthSession( const ::user_data_auth::StartFingerprintAuthSessionRequest& request, StartFingerprintAuthSessionCallback callback) override {
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h index 58becf9..44a923d6 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
@@ -54,15 +54,6 @@ using RemoveCallback = chromeos::DBusMethodCallback<::user_data_auth::RemoveReply>; - // Key-based API, still used by PIN codepath. - // TODO(b/260718534): Remove next group as part of UserAuthFactors cleanup. - using GetKeyDataCallback = - chromeos::DBusMethodCallback<::user_data_auth::GetKeyDataReply>; - using AddKeyCallback = - chromeos::DBusMethodCallback<::user_data_auth::AddKeyReply>; - using RemoveKeyCallback = - chromeos::DBusMethodCallback<::user_data_auth::RemoveKeyReply>; - // This API is still used by old WebAuthN path. // TODO(b/260715686): Remove as part of UseAuthsessionForWebAuthN cleanup. using CheckKeyCallback = @@ -188,18 +179,6 @@ virtual void CheckKey(const ::user_data_auth::CheckKeyRequest& request, CheckKeyCallback callback) = 0; - // Key-based API, still used by PIN codepath. - // TODO(b/260718534): Remove next group as part of UserAuthFactors cleanup. - // Get key metadata for user's vault. - virtual void GetKeyData(const ::user_data_auth::GetKeyDataRequest& request, - GetKeyDataCallback callback) = 0; - // Add a key to user's vault. - virtual void AddKey(const ::user_data_auth::AddKeyRequest& request, - AddKeyCallback callback) = 0; - // Remove a key from user's vault. - virtual void RemoveKey(const ::user_data_auth::RemoveKeyRequest& request, - RemoveKeyCallback callback) = 0; - // Starts a fingerprint auth session. virtual void StartFingerprintAuthSession( const ::user_data_auth::StartFingerprintAuthSessionRequest& request,
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc index 6593a6e..9eaf91f5 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client_unittest.cc
@@ -185,10 +185,7 @@ ::user_data_auth::UnmountReply expected_unmount_reply_; ::user_data_auth::MountReply expected_mount_reply_; ::user_data_auth::RemoveReply expected_remove_reply_; - ::user_data_auth::GetKeyDataReply expected_get_key_data_reply_; ::user_data_auth::CheckKeyReply expected_check_key_reply_; - ::user_data_auth::AddKeyReply expected_add_key_reply_; - ::user_data_auth::RemoveKeyReply expected_remove_key_reply_; ::user_data_auth::StartFingerprintAuthSessionReply expected_start_fingerprint_auth_session_reply_; ::user_data_auth::EndFingerprintAuthSessionReply @@ -231,14 +228,8 @@ writer.AppendProtoAsArrayOfBytes(expected_mount_reply_); } else if (method_call->GetMember() == ::user_data_auth::kRemove) { writer.AppendProtoAsArrayOfBytes(expected_remove_reply_); - } else if (method_call->GetMember() == ::user_data_auth::kGetKeyData) { - writer.AppendProtoAsArrayOfBytes(expected_get_key_data_reply_); } else if (method_call->GetMember() == ::user_data_auth::kCheckKey) { writer.AppendProtoAsArrayOfBytes(expected_check_key_reply_); - } else if (method_call->GetMember() == ::user_data_auth::kAddKey) { - writer.AppendProtoAsArrayOfBytes(expected_add_key_reply_); - } else if (method_call->GetMember() == ::user_data_auth::kRemoveKey) { - writer.AppendProtoAsArrayOfBytes(expected_remove_key_reply_); } else if (method_call->GetMember() == ::user_data_auth::kStartFingerprintAuthSession) { writer.AppendProtoAsArrayOfBytes( @@ -347,19 +338,6 @@ EXPECT_TRUE(ProtobufEquals(result_reply.value(), expected_remove_reply_)); } -TEST_F(UserDataAuthClientTest, GetKeyData) { - expected_get_key_data_reply_.set_error( - user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_TPM_DEFEND_LOCK); - absl::optional<::user_data_auth::GetKeyDataReply> result_reply; - - client_->GetKeyData(::user_data_auth::GetKeyDataRequest(), - CreateCopyCallback(&result_reply)); - base::RunLoop().RunUntilIdle(); - ASSERT_NE(result_reply, absl::nullopt); - EXPECT_TRUE( - ProtobufEquals(result_reply.value(), expected_get_key_data_reply_)); -} - TEST_F(UserDataAuthClientTest, CheckKey) { expected_check_key_reply_.set_error( user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_TPM_DEFEND_LOCK); @@ -372,30 +350,6 @@ EXPECT_TRUE(ProtobufEquals(result_reply.value(), expected_check_key_reply_)); } -TEST_F(UserDataAuthClientTest, AddKey) { - expected_add_key_reply_.set_error( - user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_TPM_DEFEND_LOCK); - absl::optional<::user_data_auth::AddKeyReply> result_reply; - - client_->AddKey(::user_data_auth::AddKeyRequest(), - CreateCopyCallback(&result_reply)); - base::RunLoop().RunUntilIdle(); - ASSERT_NE(result_reply, absl::nullopt); - EXPECT_TRUE(ProtobufEquals(result_reply.value(), expected_add_key_reply_)); -} - -TEST_F(UserDataAuthClientTest, RemoveKey) { - expected_remove_key_reply_.set_error( - user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_TPM_DEFEND_LOCK); - absl::optional<::user_data_auth::RemoveKeyReply> result_reply; - - client_->RemoveKey(::user_data_auth::RemoveKeyRequest(), - CreateCopyCallback(&result_reply)); - base::RunLoop().RunUntilIdle(); - ASSERT_NE(result_reply, absl::nullopt); - EXPECT_TRUE(ProtobufEquals(result_reply.value(), expected_remove_key_reply_)); -} - TEST_F(UserDataAuthClientTest, StartFingerprintAuthSession) { expected_start_fingerprint_auth_session_reply_.set_error( user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_TPM_DEFEND_LOCK);
diff --git a/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.cc b/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.cc index 7648c61..f0d639e6 100644 --- a/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.cc +++ b/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.cc
@@ -39,7 +39,8 @@ return base::StringPrintf("%04d%02d", exploded.year, exploded.month); } -FresnelImportDataRequest ChurnCohortUseCaseImpl::GenerateImportRequestBody() { +absl::optional<FresnelImportDataRequest> +ChurnCohortUseCaseImpl::GenerateImportRequestBody() { std::string psm_id_str = GetPsmIdentifier().value().sensitive_id(); std::string window_id_str = GetWindowIdentifier().value();
diff --git a/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.h b/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.h index 5a15c20..0eb8cca 100644 --- a/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.h +++ b/chromeos/ash/components/device_activity/churn_cohort_use_case_impl.h
@@ -40,7 +40,7 @@ // then the Churn Cohort window identifier is `202212` std::string GenerateWindowIdentifier(base::Time ts) const override; - FresnelImportDataRequest GenerateImportRequestBody() override; + absl::optional<FresnelImportDataRequest> GenerateImportRequestBody() override; // Whether current device active use case check-in is enabled or not. bool IsEnabledCheckIn() override;
diff --git a/chromeos/ash/components/device_activity/daily_use_case_impl.cc b/chromeos/ash/components/device_activity/daily_use_case_impl.cc index 7ccceec..a03eb42 100644 --- a/chromeos/ash/components/device_activity/daily_use_case_impl.cc +++ b/chromeos/ash/components/device_activity/daily_use_case_impl.cc
@@ -31,7 +31,8 @@ DailyUseCaseImpl::~DailyUseCaseImpl() = default; -FresnelImportDataRequest DailyUseCaseImpl::GenerateImportRequestBody() { +absl::optional<FresnelImportDataRequest> +DailyUseCaseImpl::GenerateImportRequestBody() { // Generate Fresnel PSM import request body. FresnelImportDataRequest import_request;
diff --git a/chromeos/ash/components/device_activity/daily_use_case_impl.h b/chromeos/ash/components/device_activity/daily_use_case_impl.h index 01ec99d..915389c 100644 --- a/chromeos/ash/components/device_activity/daily_use_case_impl.h +++ b/chromeos/ash/components/device_activity/daily_use_case_impl.h
@@ -34,9 +34,9 @@ ~DailyUseCaseImpl() override; // DeviceActiveUseCase: - FresnelImportDataRequest GenerateImportRequestBody() override; + absl::optional<FresnelImportDataRequest> GenerateImportRequestBody() override; - // Whether current device active use case check-in is enabled or not. + // Whether current device active use case check-in is enabled or not. bool IsEnabledCheckIn() override; // Whether current device active use case check membership is enabled or not.
diff --git a/chromeos/ash/components/device_activity/daily_use_case_impl_unittest.cc b/chromeos/ash/components/device_activity/daily_use_case_impl_unittest.cc index 00a38f9..1cca434 100644 --- a/chromeos/ash/components/device_activity/daily_use_case_impl_unittest.cc +++ b/chromeos/ash/components/device_activity/daily_use_case_impl_unittest.cc
@@ -113,7 +113,7 @@ daily_use_case_impl_->SetWindowIdentifier(new_daily_ts); FresnelImportDataRequest req = - daily_use_case_impl_->GenerateImportRequestBody(); + daily_use_case_impl_->GenerateImportRequestBody().value(); EXPECT_EQ(req.device_metadata().hardware_id(), kHardwareClassKeyNotFound); EXPECT_EQ(req.device_metadata().chromeos_channel(), Channel::CHANNEL_STABLE); EXPECT_EQ(req.device_metadata().market_segment(),
diff --git a/chromeos/ash/components/device_activity/device_active_use_case.cc b/chromeos/ash/components/device_activity/device_active_use_case.cc index 7f41c692..8f131c2 100644 --- a/chromeos/ash/components/device_activity/device_active_use_case.cc +++ b/chromeos/ash/components/device_activity/device_active_use_case.cc
@@ -214,6 +214,17 @@ psm_rlwe_client_ = std::move(status_or_client.value()); } +void DeviceActiveUseCase::SetChurnActiveStatus( + ChurnActiveStatus* churn_active_status) { + churn_active_status_ = churn_active_status; +} + +ChurnActiveStatus* DeviceActiveUseCase::GetChurnActiveStatus() { + DCHECK(churn_active_status_); + + return churn_active_status_; +} + std::string DeviceActiveUseCase::FormatPTDateString(base::Time ts) { base::Time::Exploded exploded; ts.UTCExplode(&exploded);
diff --git a/chromeos/ash/components/device_activity/device_active_use_case.h b/chromeos/ash/components/device_activity/device_active_use_case.h index c0bf8aca..75c3d4bc0 100644 --- a/chromeos/ash/components/device_activity/device_active_use_case.h +++ b/chromeos/ash/components/device_activity/device_active_use_case.h
@@ -11,7 +11,9 @@ #include "base/component_export.h" #include "base/time/time.h" #include "chromeos/ash/components/dbus/private_computing/private_computing_service.pb.h" +#include "chromeos/ash/components/device_activity/churn_active_status.h" #include "chromeos/ash/components/device_activity/fresnel_service.pb.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/private_membership/src/private_membership_rlwe_client.h" class PrefService; @@ -71,7 +73,8 @@ // // Important: Each new dimension added to metadata will need to be approved by // privacy. - virtual FresnelImportDataRequest GenerateImportRequestBody() = 0; + virtual absl::optional<FresnelImportDataRequest> + GenerateImportRequestBody() = 0; // Whether current device active use case check-in is enabled or not. virtual bool IsEnabledCheckIn() = 0; @@ -192,6 +195,14 @@ // Retrieve the ChromeOS device market segment. MarketSegment GetMarketSegment() const; + // Once the client has initiated churn_active_status object, then pass + // the reference to the churn use cases to get the churn active status. + void SetChurnActiveStatus(ChurnActiveStatus* churn_active_status); + + // Uses the churn_active_status to get the device churn active status + // metadata. + ChurnActiveStatus* GetChurnActiveStatus(); + // Retrieve |psm_device_active_secret_|. const std::string& GetPsmDeviceActiveSecret() const; @@ -250,6 +261,10 @@ // Client Generates protos used in request body of Oprf and Query requests. std::unique_ptr<private_membership::rlwe::PrivateMembershipRlweClient> psm_rlwe_client_; + + // The churn_active_status is used for Churn Cohort and Observation use + // cases to calculate the churn active status metadata. + ChurnActiveStatus* churn_active_status_ = nullptr; }; } // namespace device_activity
diff --git a/chromeos/ash/components/device_activity/device_activity_client.cc b/chromeos/ash/components/device_activity/device_activity_client.cc index f607e7e..a300898 100644 --- a/chromeos/ash/components/device_activity/device_activity_client.cc +++ b/chromeos/ash/components/device_activity/device_activity_client.cc
@@ -1051,11 +1051,16 @@ RecordStateCountMetric(state_); // Generate Fresnel PSM import request body. - FresnelImportDataRequest import_request = + absl::optional<FresnelImportDataRequest> import_request = current_use_case->GenerateImportRequestBody(); + if (!import_request.has_value()) { + TransitionToIdle(current_use_case); + return; + } + std::string request_body; - import_request.SerializeToString(&request_body); + import_request.value().SerializeToString(&request_body); auto resource_request = GenerateResourceRequest( net::HttpRequestHeaders::kPostMethod, GetFresnelURL(), api_key_);
diff --git a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.cc b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.cc index df529af5..ed220e8b 100644 --- a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.cc +++ b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.cc
@@ -39,7 +39,7 @@ TwentyEightDayActiveUseCaseImpl::~TwentyEightDayActiveUseCaseImpl() = default; -FresnelImportDataRequest +absl::optional<FresnelImportDataRequest> TwentyEightDayActiveUseCaseImpl::GenerateImportRequestBody() { // Generate Fresnel PSM import request body. FresnelImportDataRequest import_request;
diff --git a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.h b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.h index ac88ba79..78fa699 100644 --- a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.h +++ b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl.h
@@ -37,7 +37,7 @@ ~TwentyEightDayActiveUseCaseImpl() override; // DeviceActiveUseCase: - FresnelImportDataRequest GenerateImportRequestBody() override; + absl::optional<FresnelImportDataRequest> GenerateImportRequestBody() override; private_computing::ActiveStatus GenerateActiveStatus() override; // Whether current device active use case check-in is enabled or not.
diff --git a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl_unittest.cc b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl_unittest.cc index c6fdadff..eaf4414 100644 --- a/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl_unittest.cc +++ b/chromeos/ash/components/device_activity/twenty_eight_day_active_use_case_impl_unittest.cc
@@ -138,7 +138,8 @@ twenty_eight_day_active_use_case_impl_->SetWindowIdentifier(new_daily_ts); FresnelImportDataRequest req = - twenty_eight_day_active_use_case_impl_->GenerateImportRequestBody(); + twenty_eight_day_active_use_case_impl_->GenerateImportRequestBody() + .value(); EXPECT_EQ(req.device_metadata().chromeos_channel(), Channel::CHANNEL_STABLE); EXPECT_FALSE(req.device_metadata().chromeos_version().empty());
diff --git a/chromeos/ash/components/network/BUILD.gn b/chromeos/ash/components/network/BUILD.gn index 8babe499..a5baf10 100644 --- a/chromeos/ash/components/network/BUILD.gn +++ b/chromeos/ash/components/network/BUILD.gn
@@ -99,6 +99,8 @@ "hidden_network_handler.h", "hotspot_allowed_flag_handler.cc", "hotspot_allowed_flag_handler.h", + "hotspot_capabilities_provider.cc", + "hotspot_capabilities_provider.h", "hotspot_controller.cc", "hotspot_controller.h", "hotspot_state_handler.cc", @@ -303,6 +305,7 @@ "geolocation_handler_unittest.cc", "hidden_network_handler_unittest.cc", "hotspot_allowed_flag_handler_unittest.cc", + "hotspot_capabilities_provider_unittest.cc", "hotspot_controller_unittest.cc", "hotspot_state_handler_unittest.cc", "managed_cellular_pref_handler_unittest.cc",
diff --git a/chromeos/ash/components/network/hotspot_capabilities_provider.cc b/chromeos/ash/components/network/hotspot_capabilities_provider.cc new file mode 100644 index 0000000..f007f0d --- /dev/null +++ b/chromeos/ash/components/network/hotspot_capabilities_provider.cc
@@ -0,0 +1,283 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" + +#include "base/containers/contains.h" +#include "chromeos/ash/components/dbus/shill/shill_manager_client.h" +#include "chromeos/ash/components/network/hotspot_util.h" +#include "chromeos/ash/components/network/network_event_log.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" + +namespace ash { + +namespace { + +// Convert the base::Value::List type of |allowed_security_modes_in_shill| to +// the corresponding mojom enum and update the value to the +// |allowed_security_modes|. +void UpdateAllowedSecurityList( + std::vector<hotspot_config::mojom::WiFiSecurityMode>& + allowed_security_modes, + const base::Value::List& allowed_security_modes_in_shill) { + allowed_security_modes.clear(); + for (const base::Value& allowed_security : allowed_security_modes_in_shill) { + allowed_security_modes.push_back( + ShillSecurityToMojom(allowed_security.GetString())); + } +} + +bool IsDisallowedByPlatformCapabilities( + hotspot_config::mojom::HotspotAllowStatus allow_status) { + using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; + return allow_status == HotspotAllowStatus::kDisallowedNoCellularUpstream || + allow_status == HotspotAllowStatus::kDisallowedNoWiFiDownstream || + allow_status == HotspotAllowStatus::kDisallowedNoWiFiSecurityModes; +} + +} // namespace + +HotspotCapabilitiesProvider::HotspotCapabilities::HotspotCapabilities( + const hotspot_config::mojom::HotspotAllowStatus allow_status) + : allow_status(allow_status) {} + +HotspotCapabilitiesProvider::HotspotCapabilities::~HotspotCapabilities() = + default; + +HotspotCapabilitiesProvider::HotspotCapabilitiesProvider() = default; + +HotspotCapabilitiesProvider::~HotspotCapabilitiesProvider() { + ResetNetworkStateHandler(); + + if (ShillManagerClient::Get()) { + ShillManagerClient::Get()->RemovePropertyChangedObserver(this); + } +} + +void HotspotCapabilitiesProvider::Init( + NetworkStateHandler* network_state_handler) { + network_state_handler_ = network_state_handler; + network_state_handler_observer_.Observe(network_state_handler_); + + // Add as an observer here so that new hotspot state updated after this call + // are recognized. + ShillManagerClient::Get()->AddPropertyChangedObserver(this); + ShillManagerClient::Get()->GetProperties( + base::BindOnce(&HotspotCapabilitiesProvider::OnManagerProperties, + weak_ptr_factory_.GetWeakPtr())); +} + +void HotspotCapabilitiesProvider::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void HotspotCapabilitiesProvider::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +bool HotspotCapabilitiesProvider::HasObserver(Observer* observer) const { + return observer_list_.HasObserver(observer); +} + +const HotspotCapabilitiesProvider::HotspotCapabilities& +HotspotCapabilitiesProvider::GetHotspotCapabilities() const { + return hotspot_capabilities_; +} + +void HotspotCapabilitiesProvider::OnPropertyChanged(const std::string& key, + const base::Value& value) { + if (key == shill::kTetheringCapabilitiesProperty) { + UpdateHotspotCapabilities(value.GetDict()); + } +} + +// The hotspot capabilities is re-calculated when a cellular network connection +// state is changed. +void HotspotCapabilitiesProvider::NetworkConnectionStateChanged( + const NetworkState* network) { + using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; + // Only check the Cellular connectivity as the upstream technology + if (!network->Matches(NetworkTypePattern::Cellular())) { + return; + } + + // Exit early if the platform capabilities doesn't support hotspot. + if (IsDisallowedByPlatformCapabilities(hotspot_capabilities_.allow_status)) { + return; + } + + if (!network->IsConnectingOrConnected()) { + // The cellular network got disconnected. + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoMobileData); + return; + } + + if (network->IsConnectedState()) { + ShillManagerClient::Get()->CheckTetheringReadiness( + base::BindOnce(&HotspotCapabilitiesProvider::OnCheckReadinessSuccess, + weak_ptr_factory_.GetWeakPtr(), base::DoNothing()), + base::BindOnce(&HotspotCapabilitiesProvider::OnCheckReadinessFailure, + weak_ptr_factory_.GetWeakPtr(), base::DoNothing())); + } +} + +void HotspotCapabilitiesProvider::OnShuttingDown() { + ResetNetworkStateHandler(); +} + +void HotspotCapabilitiesProvider::ResetNetworkStateHandler() { + if (!network_state_handler_) { + return; + } + network_state_handler_observer_.Reset(); + network_state_handler_ = nullptr; +} + +void HotspotCapabilitiesProvider::OnManagerProperties( + absl::optional<base::Value> properties) { + if (!properties) { + NET_LOG(ERROR) + << "HotspotCapabilitiesProvider: Failed to get manager properties."; + return; + } + + const base::Value::Dict* capabilities = + properties->GetDict().FindDict(shill::kTetheringCapabilitiesProperty); + if (!capabilities) { + NET_LOG(EVENT) << "HotspotCapabilitiesProvider: No dict value for: " + << shill::kTetheringCapabilitiesProperty; + } else { + UpdateHotspotCapabilities(*capabilities); + } +} + +void HotspotCapabilitiesProvider::UpdateHotspotCapabilities( + const base::Value::Dict& capabilities) { + using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; + + const base::Value::List* upstream_technologies = + capabilities.FindList(shill::kTetheringCapUpstreamProperty); + if (!upstream_technologies) { + NET_LOG(ERROR) << "No list value for: " + << shill::kTetheringCapUpstreamProperty << " in " + << shill::kTetheringCapabilitiesProperty; + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoCellularUpstream); + return; + } + + if (!base::Contains(*upstream_technologies, shill::kTypeCellular)) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoCellularUpstream); + return; + } + + const base::Value::List* downstream_technologies = + capabilities.FindList(shill::kTetheringCapDownstreamProperty); + if (!downstream_technologies) { + NET_LOG(ERROR) << "No list value for: " + << shill::kTetheringCapDownstreamProperty << " in " + << shill::kTetheringCapabilitiesProperty; + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoWiFiDownstream); + return; + } + + if (!base::Contains(*downstream_technologies, shill::kTypeWifi)) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoWiFiDownstream); + return; + } + + // Update allowed security modes for WiFi downstream + const base::Value::List* allowed_security_modes_in_shill = + capabilities.FindList(shill::kTetheringCapSecurityProperty); + if (!allowed_security_modes_in_shill) { + NET_LOG(ERROR) << "No list value for: " + << shill::kTetheringCapSecurityProperty << " in " + << shill::kTetheringCapabilitiesProperty; + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoWiFiSecurityModes); + return; + } + + UpdateAllowedSecurityList(hotspot_capabilities_.allowed_security_modes, + *allowed_security_modes_in_shill); + if (hotspot_capabilities_.allowed_security_modes.empty()) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoWiFiSecurityModes); + return; + } + + // Check if there's a connected cellular network + const NetworkState* connected_cellular_network = + network_state_handler_->ConnectedNetworkByType( + NetworkTypePattern::Cellular()); + if (!connected_cellular_network) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedNoMobileData); + return; + } + + CheckTetheringReadiness(base::DoNothing()); +} + +void HotspotCapabilitiesProvider::CheckTetheringReadiness( + CheckTetheringReadinessCallback callback) { + auto callback_split = base::SplitOnceCallback(std::move(callback)); + ShillManagerClient::Get()->CheckTetheringReadiness( + base::BindOnce(&HotspotCapabilitiesProvider::OnCheckReadinessSuccess, + weak_ptr_factory_.GetWeakPtr(), + std::move(callback_split.first)), + base::BindOnce(&HotspotCapabilitiesProvider::OnCheckReadinessFailure, + weak_ptr_factory_.GetWeakPtr(), + std::move(callback_split.second))); +} + +void HotspotCapabilitiesProvider::OnCheckReadinessSuccess( + CheckTetheringReadinessCallback callback, + const std::string& result) { + using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; + + if (result == shill::kTetheringReadinessReady) { + SetHotspotAllowStatus(HotspotAllowStatus::kAllowed); + std::move(callback).Run(CheckTetheringReadinessResult::kReady); + return; + } + if (result == shill::kTetheringReadinessUpstreamNetworkNotAvailable) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedReadinessCheckFail); + std::move(callback).Run( + CheckTetheringReadinessResult::kUpstreamNetworkNotAvailable); + return; + } + if (result == shill::kTetheringReadinessNotAllowed) { + SetHotspotAllowStatus(HotspotAllowStatus::kDisallowedReadinessCheckFail); + std::move(callback).Run(CheckTetheringReadinessResult::kNotAllowed); + return; + } + NET_LOG(ERROR) << "Unexpected check tethering readiness result: " << result; + std::move(callback).Run(CheckTetheringReadinessResult::kNotAllowed); +} + +void HotspotCapabilitiesProvider::OnCheckReadinessFailure( + CheckTetheringReadinessCallback callback, + const std::string& error_name, + const std::string& error_message) { + NET_LOG(ERROR) << "Check tethering readiness failed, error name: " + << error_name << ", message: " << error_message; + SetHotspotAllowStatus( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedReadinessCheckFail); + std::move(callback).Run(CheckTetheringReadinessResult::kShillOperationFailed); +} + +void HotspotCapabilitiesProvider::SetHotspotAllowStatus( + hotspot_config::mojom::HotspotAllowStatus new_allow_status) { + if (hotspot_capabilities_.allow_status == new_allow_status) { + return; + } + + hotspot_capabilities_.allow_status = new_allow_status; + NotifyHotspotCapabilitiesChanged(); +} + +void HotspotCapabilitiesProvider::NotifyHotspotCapabilitiesChanged() { + for (auto& observer : observer_list_) { + observer.OnHotspotCapabilitiesChanged(); + } +} + +} // namespace ash \ No newline at end of file
diff --git a/chromeos/ash/components/network/hotspot_capabilities_provider.h b/chromeos/ash/components/network/hotspot_capabilities_provider.h new file mode 100644 index 0000000..e6d46faa2 --- /dev/null +++ b/chromeos/ash/components/network/hotspot_capabilities_provider.h
@@ -0,0 +1,134 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_HOTSPOT_CAPABILITIES_PROVIDER_H_ +#define CHROMEOS_ASH_COMPONENTS_NETWORK_HOTSPOT_CAPABILITIES_PROVIDER_H_ + +#include <memory> +#include <vector> + +#include "base/component_export.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/scoped_observation.h" +#include "base/values.h" +#include "chromeos/ash/components/dbus/shill/shill_property_changed_observer.h" +#include "chromeos/ash/components/network/network_state_handler.h" +#include "chromeos/ash/components/network/network_state_handler_observer.h" +#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace ash { + +class NetworkStateHandler; + +// This class caches hotspot related status and implements methods to get +// current state, active client count, capabilities and configure the hotspot +// configurations. +class COMPONENT_EXPORT(CHROMEOS_NETWORK) HotspotCapabilitiesProvider + : public ShillPropertyChangedObserver, + public NetworkStateHandlerObserver { + public: + class Observer : public base::CheckedObserver { + public: + ~Observer() override = default; + + // Invoked when hotspot capabilities is changed. + virtual void OnHotspotCapabilitiesChanged() = 0; + }; + + // Represents the hotspot capabilities. Includes: + // 1. The allow status that is calculated from the combination Shill Tethering + // Capabilities and Shill Tethering Readiness check result and policy allow + // status. + // 2. List of allowed WiFi security modes for WiFi downstream. + struct HotspotCapabilities { + explicit HotspotCapabilities( + const hotspot_config::mojom::HotspotAllowStatus allow_status); + ~HotspotCapabilities(); + + hotspot_config::mojom::HotspotAllowStatus allow_status; + std::vector<hotspot_config::mojom::WiFiSecurityMode> allowed_security_modes; + }; + + // Represents the check tethering readiness result. + enum class CheckTetheringReadinessResult { + kReady = 0, + kNotAllowed = 1, + kUpstreamNetworkNotAvailable = 2, + kShillOperationFailed = 3, + }; + + HotspotCapabilitiesProvider(); + HotspotCapabilitiesProvider(const HotspotCapabilitiesProvider&) = delete; + HotspotCapabilitiesProvider& operator=(const HotspotCapabilitiesProvider&) = + delete; + ~HotspotCapabilitiesProvider() override; + + void Init(NetworkStateHandler* network_state_handler); + + // Return the latest hotspot capabilities + const HotspotCapabilities& GetHotspotCapabilities() const; + + // Update the hotspot allow status with the given |new_allow_status| + // and then notify observers if it changes. + void SetHotspotAllowStatus( + hotspot_config::mojom::HotspotAllowStatus new_allow_status); + + // Return callback for the CheckTetheringReadiness method. + using CheckTetheringReadinessCallback = + base::OnceCallback<void(CheckTetheringReadinessResult result)>; + + // Check tethering readiness and update the hotspot_capabilities_ if + // necessary. |callback| is called with check readiness result. + void CheckTetheringReadiness(CheckTetheringReadinessCallback callback); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + bool HasObserver(Observer* observer) const; + + private: + // ShillPropertyChangedObserver overrides + void OnPropertyChanged(const std::string& key, + const base::Value& value) override; + + // NetworkStateHandlerObserver + void NetworkConnectionStateChanged(const NetworkState* network) override; + void OnShuttingDown() override; + + // Callback to handle the manager properties with hotspot related properties. + void OnManagerProperties(absl::optional<base::Value> properties); + + // Notify observer that hotspot capabilities was changed. + void NotifyHotspotCapabilitiesChanged(); + + // Update the cached hotspot_capabilities_ from the tethering capabilities + // values from Shill. This function is called whenever the tethering + // capabilities value is changed in Shill. + void UpdateHotspotCapabilities(const base::Value::Dict& capabilities); + + // Callback when the CheckTetheringReadiness operation succeeded. + void OnCheckReadinessSuccess(CheckTetheringReadinessCallback callback, + const std::string& result); + + // Callback when the CheckTetheringReadiness operation failed. + void OnCheckReadinessFailure(CheckTetheringReadinessCallback callback, + const std::string& error_name, + const std::string& error_message); + + void ResetNetworkStateHandler(); + + HotspotCapabilities hotspot_capabilities_{ + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream}; + + NetworkStateHandler* network_state_handler_ = nullptr; + base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver> + network_state_handler_observer_{this}; + base::ObserverList<Observer> observer_list_; + base::WeakPtrFactory<HotspotCapabilitiesProvider> weak_ptr_factory_{this}; +}; + +} // namespace ash + +#endif // CHROMEOS_ASH_COMPONENTS_NETWORK_HOTSPOT_CAPABILITIES_PROVIDER_H_
diff --git a/chromeos/ash/components/network/hotspot_capabilities_provider_unittest.cc b/chromeos/ash/components/network/hotspot_capabilities_provider_unittest.cc new file mode 100644 index 0000000..5203f9b --- /dev/null +++ b/chromeos/ash/components/network/hotspot_capabilities_provider_unittest.cc
@@ -0,0 +1,233 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" + +#include "ash/constants/ash_features.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "base/values.h" +#include "chromeos/ash/components/dbus/shill/shill_clients.h" +#include "chromeos/ash/components/dbus/shill/shill_manager_client.h" +#include "chromeos/ash/components/network/network_state_handler.h" +#include "chromeos/ash/components/network/network_state_test_helper.h" +#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" + +namespace ash { + +namespace { + +const char kCellularServicePath[] = "/service/cellular0"; +const char kCellularServiceGuid[] = "cellular_guid0"; +const char kCellularServiceName[] = "cellular_name0"; + +} // namespace + +class TestObserver : public HotspotCapabilitiesProvider::Observer { + public: + TestObserver() = default; + ~TestObserver() override = default; + + void OnHotspotCapabilitiesChanged() override { + hotspot_capabilities_changed_count_++; + } + + size_t hotspot_capabilities_changed_count() { + return hotspot_capabilities_changed_count_; + } + + private: + size_t hotspot_capabilities_changed_count_ = 0u; +}; + +class HotspotCapabilitiesProviderTest : public ::testing::Test { + public: + void SetUp() override { + feature_list_.InitAndEnableFeature(features::kHotspot); + + if (hotspot_capabilities_provider_ && + hotspot_capabilities_provider_->HasObserver(&observer_)) { + hotspot_capabilities_provider_->RemoveObserver(&observer_); + } + hotspot_capabilities_provider_ = + std::make_unique<HotspotCapabilitiesProvider>(); + hotspot_capabilities_provider_->AddObserver(&observer_); + hotspot_capabilities_provider_->Init( + network_state_test_helper_.network_state_handler()); + base::RunLoop().RunUntilIdle(); + } + + void TearDown() override { + network_state_test_helper_.ClearDevices(); + network_state_test_helper_.ClearServices(); + hotspot_capabilities_provider_->RemoveObserver(&observer_); + hotspot_capabilities_provider_.reset(); + } + + HotspotCapabilitiesProvider::CheckTetheringReadinessResult + CheckTetheringReadiness() { + base::RunLoop run_loop; + HotspotCapabilitiesProvider::CheckTetheringReadinessResult return_result; + hotspot_capabilities_provider_->CheckTetheringReadiness( + base::BindLambdaForTesting( + [&](HotspotCapabilitiesProvider::CheckTetheringReadinessResult + result) { + return_result = result; + run_loop.QuitClosure(); + })); + run_loop.RunUntilIdle(); + return return_result; + } + + protected: + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<HotspotCapabilitiesProvider> hotspot_capabilities_provider_; + TestObserver observer_; + NetworkStateTestHelper network_state_test_helper_{ + /*use_default_devices_and_services=*/false}; +}; + +TEST_F(HotspotCapabilitiesProviderTest, GetHotspotCapabilities) { + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(0u, observer_.hotspot_capabilities_changed_count()); + + base::Value::Dict capabilities_dict; + capabilities_dict.Set(shill::kTetheringCapUpstreamProperty, + base::Value::List()); + capabilities_dict.Set(shill::kTetheringCapDownstreamProperty, + base::Value::List()); + capabilities_dict.Set(shill::kTetheringCapSecurityProperty, + base::Value::List()); + network_state_test_helper_.manager_test()->SetManagerProperty( + shill::kTetheringCapabilitiesProperty, + base::Value(capabilities_dict.Clone())); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(0u, observer_.hotspot_capabilities_changed_count()); + + base::Value::List upstream_list; + upstream_list.Append(shill::kTypeCellular); + capabilities_dict.Set(shill::kTetheringCapUpstreamProperty, + std::move(upstream_list)); + network_state_test_helper_.manager_test()->SetManagerProperty( + shill::kTetheringCapabilitiesProperty, + base::Value(capabilities_dict.Clone())); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoWiFiDownstream, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(1u, observer_.hotspot_capabilities_changed_count()); + + // Add WiFi to the downstream technology list in Shill + base::Value::List downstream_list; + downstream_list.Append(shill::kTypeWifi); + capabilities_dict.Set(shill::kTetheringCapDownstreamProperty, + std::move(downstream_list)); + // Add allowed WiFi security mode in Shill + base::Value::List security_list; + security_list.Append(shill::kSecurityWpa2); + security_list.Append(shill::kSecurityWpa3); + capabilities_dict.Set(shill::kTetheringCapSecurityProperty, + std::move(security_list)); + network_state_test_helper_.manager_test()->SetManagerProperty( + shill::kTetheringCapabilitiesProperty, + base::Value(capabilities_dict.Clone())); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoMobileData, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(2u, hotspot_capabilities_provider_->GetHotspotCapabilities() + .allowed_security_modes.size()); + EXPECT_EQ(2u, observer_.hotspot_capabilities_changed_count()); + + // Add an active cellular network and simulate check tethering readiness + // operation fail. + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kFailure, + /*readiness_status=*/std::string()); + ShillServiceClient::TestInterface* service_test = + network_state_test_helper_.service_test(); + service_test->AddService(kCellularServicePath, kCellularServiceGuid, + kCellularServiceName, shill::kTypeCellular, + shill::kStateOnline, /*visible=*/true); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedReadinessCheckFail, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(3u, observer_.hotspot_capabilities_changed_count()); + + // Disconnect the active cellular network + service_test->SetServiceProperty(kCellularServicePath, shill::kStateProperty, + base::Value(shill::kStateIdle)); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoMobileData, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(4u, observer_.hotspot_capabilities_changed_count()); + + // Simulate check tethering readiness operation success and re-connect the + // cellular network + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kSuccess, shill::kTetheringReadinessReady); + service_test->SetServiceProperty(kCellularServicePath, shill::kStateProperty, + base::Value(shill::kStateOnline)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ( + hotspot_config::mojom::HotspotAllowStatus::kAllowed, + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); + EXPECT_EQ(5u, observer_.hotspot_capabilities_changed_count()); +} + +TEST_F(HotspotCapabilitiesProviderTest, CheckTetheringReadiness) { + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kSuccess, shill::kTetheringReadinessReady); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(CheckTetheringReadiness(), + HotspotCapabilitiesProvider::CheckTetheringReadinessResult::kReady); + + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kSuccess, + shill::kTetheringReadinessNotAllowed); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + CheckTetheringReadiness(), + HotspotCapabilitiesProvider::CheckTetheringReadinessResult::kNotAllowed); + + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kSuccess, + /*readiness_status=*/std::string()); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + CheckTetheringReadiness(), + HotspotCapabilitiesProvider::CheckTetheringReadinessResult::kNotAllowed); + + network_state_test_helper_.manager_test() + ->SetSimulateCheckTetheringReadinessResult( + FakeShillSimulatedResult::kFailure, + /*readiness_status=*/std::string()); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(CheckTetheringReadiness(), + HotspotCapabilitiesProvider::CheckTetheringReadinessResult:: + kShillOperationFailed); +} + +} // namespace ash
diff --git a/chromeos/ash/components/network/hotspot_controller.cc b/chromeos/ash/components/network/hotspot_controller.cc index c98b822..14fe040 100644 --- a/chromeos/ash/components/network/hotspot_controller.cc +++ b/chromeos/ash/components/network/hotspot_controller.cc
@@ -23,8 +23,9 @@ HotspotController::~HotspotController() = default; -void HotspotController::Init(HotspotStateHandler* hotspot_state_handler) { - hotspot_state_handler_ = hotspot_state_handler; +void HotspotController::Init( + HotspotCapabilitiesProvider* hotspot_capabilities_provider) { + hotspot_capabilities_provider_ = hotspot_capabilities_provider; } void HotspotController::EnableHotspot(HotspotControlCallback callback) { @@ -62,21 +63,28 @@ } void HotspotController::CheckTetheringReadiness() { - if (hotspot_state_handler_->GetHotspotCapabilities().allow_status != + if (hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status != hotspot_config::mojom::HotspotAllowStatus::kAllowed) { CompleteCurrentRequest( hotspot_config::mojom::HotspotControlResult::kNotAllowed); return; } - hotspot_state_handler_->CheckTetheringReadiness( + hotspot_capabilities_provider_->CheckTetheringReadiness( base::BindOnce(&HotspotController::OnCheckTetheringReadiness, weak_ptr_factory_.GetWeakPtr())); } void HotspotController::OnCheckTetheringReadiness( - HotspotStateHandler::CheckTetheringReadinessResult result) { - if (result != HotspotStateHandler::CheckTetheringReadinessResult::kReady) { + HotspotCapabilitiesProvider::CheckTetheringReadinessResult result) { + if (result == HotspotCapabilitiesProvider::CheckTetheringReadinessResult:: + kUpstreamNetworkNotAvailable) { + CompleteCurrentRequest( + hotspot_config::mojom::HotspotControlResult::kUpstreamNotAvailable); + return; + } + if (result != + HotspotCapabilitiesProvider::CheckTetheringReadinessResult::kReady) { CompleteCurrentRequest( hotspot_config::mojom::HotspotControlResult::kReadinessCheckFailed); return;
diff --git a/chromeos/ash/components/network/hotspot_controller.h b/chromeos/ash/components/network/hotspot_controller.h index adf7577..ae08aaf5 100644 --- a/chromeos/ash/components/network/hotspot_controller.h +++ b/chromeos/ash/components/network/hotspot_controller.h
@@ -10,7 +10,7 @@ #include "base/component_export.h" #include "base/containers/queue.h" #include "base/memory/weak_ptr.h" -#include "chromeos/ash/components/network/hotspot_state_handler.h" +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-forward.h" namespace ash { @@ -31,10 +31,12 @@ HotspotController& operator=(const HotspotController&) = delete; ~HotspotController(); - void Init(HotspotStateHandler* hotspot_state_handler); + void Init(HotspotCapabilitiesProvider* hotspot_capabilities_provider); + // Return callback for the EnableHotspot or DisableHotspot method. using HotspotControlCallback = base::OnceCallback<void( hotspot_config::mojom::HotspotControlResult control_result)>; + // Push the enable or disable hotspot request to the request queue and try to // execute. If another request is already being processed, the current request // will wait until the previous one is completed. @@ -57,7 +59,7 @@ void ProcessRequestQueue(); void CheckTetheringReadiness(); void OnCheckTetheringReadiness( - HotspotStateHandler::CheckTetheringReadinessResult result); + HotspotCapabilitiesProvider::CheckTetheringReadinessResult result); void PerformSetTetheringEnabled(bool enabled); void OnSetTetheringEnabledSuccess(const std::string& result); void OnSetTetheringEnabledFailure(const std::string& error_name, @@ -67,7 +69,7 @@ std::unique_ptr<HotspotControlRequest> current_request_; base::queue<std::unique_ptr<HotspotControlRequest>> queued_requests_; - HotspotStateHandler* hotspot_state_handler_ = nullptr; + HotspotCapabilitiesProvider* hotspot_capabilities_provider_ = nullptr; base::WeakPtrFactory<HotspotController> weak_ptr_factory_{this}; };
diff --git a/chromeos/ash/components/network/hotspot_controller_unittest.cc b/chromeos/ash/components/network/hotspot_controller_unittest.cc index ad8d453..202d253 100644 --- a/chromeos/ash/components/network/hotspot_controller_unittest.cc +++ b/chromeos/ash/components/network/hotspot_controller_unittest.cc
@@ -10,7 +10,7 @@ #include "base/values.h" #include "chromeos/ash/components/dbus/shill/shill_clients.h" #include "chromeos/ash/components/dbus/shill/shill_manager_client.h" -#include "chromeos/ash/components/network/hotspot_state_handler.h" +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" #include "chromeos/ash/components/network/network_state_handler.h" #include "chromeos/ash/components/network/network_state_test_helper.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" @@ -31,11 +31,12 @@ class HotspotControllerTest : public ::testing::Test { public: void SetUp() override { - hotspot_state_handler_ = std::make_unique<HotspotStateHandler>(); - hotspot_state_handler_->Init( + hotspot_capabilities_provider_ = + std::make_unique<HotspotCapabilitiesProvider>(); + hotspot_capabilities_provider_->Init( network_state_test_helper_.network_state_handler()); hotspot_controller_ = std::make_unique<HotspotController>(); - hotspot_controller_->Init(hotspot_state_handler_.get()); + hotspot_controller_->Init(hotspot_capabilities_provider_.get()); SetReadinessCheckResultReady(); } @@ -43,7 +44,7 @@ network_state_test_helper_.ClearDevices(); network_state_test_helper_.ClearServices(); hotspot_controller_.reset(); - hotspot_state_handler_.reset(); + hotspot_capabilities_provider_.reset(); } void SetValidTetheringCapabilities() { @@ -130,7 +131,7 @@ base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; std::unique_ptr<HotspotController> hotspot_controller_; - std::unique_ptr<HotspotStateHandler> hotspot_state_handler_; + std::unique_ptr<HotspotCapabilitiesProvider> hotspot_capabilities_provider_; NetworkStateTestHelper network_state_test_helper_{ /*use_default_devices_and_services=*/false}; }; @@ -169,7 +170,7 @@ EnableHotspot()); EXPECT_EQ( hotspot_config::mojom::HotspotAllowStatus::kDisallowedReadinessCheckFail, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status); } TEST_F(HotspotControllerTest, EnableTetheringNetworkSetupFailure) {
diff --git a/chromeos/ash/components/network/hotspot_state_handler.cc b/chromeos/ash/components/network/hotspot_state_handler.cc index b5db76a..4c9c1dc 100644 --- a/chromeos/ash/components/network/hotspot_state_handler.cc +++ b/chromeos/ash/components/network/hotspot_state_handler.cc
@@ -14,52 +14,22 @@ namespace { -size_t GetActiveClientCount(const base::Value& status) { - const base::Value* active_clients = - status.FindListKey(shill::kTetheringStatusClientsProperty); +size_t GetActiveClientCount(const base::Value::Dict& status) { + const base::Value::List* active_clients = + status.FindList(shill::kTetheringStatusClientsProperty); if (!active_clients) { NET_LOG(ERROR) << shill::kTetheringStatusClientsProperty << " not found in " << shill::kTetheringStatusProperty; return 0; } - return active_clients->GetList().size(); -} - -// Convert the base::Value::List type of |allowed_security_modes_in_shill| to -// the corresponding mojom enum and update the value to the -// |allowed_security_modes|. -void UpdateAllowedSecurityList( - std::vector<hotspot_config::mojom::WiFiSecurityMode>& - allowed_security_modes, - const base::Value::List& allowed_security_modes_in_shill) { - allowed_security_modes.clear(); - for (const base::Value& allowed_security : allowed_security_modes_in_shill) { - allowed_security_modes.push_back( - ShillSecurityToMojom(allowed_security.GetString())); - } -} - -bool IsDisallowedByPlatformCapabilities( - hotspot_config::mojom::HotspotAllowStatus allow_status) { - using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; - return allow_status == HotspotAllowStatus::kDisallowedNoCellularUpstream || - allow_status == HotspotAllowStatus::kDisallowedNoWiFiDownstream || - allow_status == HotspotAllowStatus::kDisallowedNoWiFiSecurityModes; + return active_clients->size(); } } // namespace -HotspotStateHandler::HotspotCapabilities::HotspotCapabilities( - const hotspot_config::mojom::HotspotAllowStatus allow_status) - : allow_status(allow_status) {} - -HotspotStateHandler::HotspotCapabilities::~HotspotCapabilities() = default; - HotspotStateHandler::HotspotStateHandler() = default; HotspotStateHandler::~HotspotStateHandler() { - ResetNetworkStateHandler(); - if (ShillManagerClient::Get()) { ShillManagerClient::Get()->RemovePropertyChangedObserver(this); } @@ -68,10 +38,7 @@ } } -void HotspotStateHandler::Init(NetworkStateHandler* network_state_handler) { - network_state_handler_ = network_state_handler; - network_state_handler_observer_.Observe(network_state_handler_); - +void HotspotStateHandler::Init() { if (LoginState::IsInitialized()) { LoginState::Get()->AddObserver(this); } @@ -106,11 +73,6 @@ return active_client_count_; } -const HotspotStateHandler::HotspotCapabilities& -HotspotStateHandler::GetHotspotCapabilities() const { - return hotspot_capabilities_; -} - hotspot_config::mojom::HotspotConfigPtr HotspotStateHandler::GetHotspotConfig() const { if (!hotspot_config_) @@ -189,8 +151,8 @@ hotspot_config::mojom::SetHotspotConfigResult::kSuccess); return; } - const base::Value* shill_tethering_config = - properties->FindDictKey(shill::kTetheringConfigProperty); + const base::Value::Dict* shill_tethering_config = + properties->GetDict().FindDict(shill::kTetheringConfigProperty); if (!shill_tethering_config) { NET_LOG(ERROR) << "Error getting " << shill::kTetheringConfigProperty << " in Shill manager properties"; @@ -208,51 +170,7 @@ void HotspotStateHandler::OnPropertyChanged(const std::string& key, const base::Value& value) { if (key == shill::kTetheringStatusProperty) - UpdateHotspotStatus(value); - else if (key == shill::kTetheringCapabilitiesProperty) - UpdateHotspotCapabilities(value); -} - -// The hotspot capabilities is re-calculated when a cellular network connection -// state is changed. -void HotspotStateHandler::NetworkConnectionStateChanged( - const NetworkState* network) { - using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; - // Only check the Cellular connectivity as the upstream technology - if (!network->Matches(NetworkTypePattern::Cellular())) { - return; - } - - // Exit early if the platform capabilities doesn't support hotspot. - if (IsDisallowedByPlatformCapabilities(hotspot_capabilities_.allow_status)) { - return; - } - - if (!network->IsConnectingOrConnected()) { - // The cellular network got disconnected. - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoMobileData); - return; - } - - if (network->IsConnectedState()) { - ShillManagerClient::Get()->CheckTetheringReadiness( - base::BindOnce(&HotspotStateHandler::OnCheckReadinessSuccess, - weak_ptr_factory_.GetWeakPtr(), base::DoNothing()), - base::BindOnce(&HotspotStateHandler::OnCheckReadinessFailure, - weak_ptr_factory_.GetWeakPtr(), base::DoNothing())); - } -} - -void HotspotStateHandler::OnShuttingDown() { - ResetNetworkStateHandler(); -} - -void HotspotStateHandler::ResetNetworkStateHandler() { - if (!network_state_handler_) { - return; - } - network_state_handler_observer_.Reset(); - network_state_handler_ = nullptr; + UpdateHotspotStatus(value.GetDict()); } void HotspotStateHandler::OnManagerProperties( @@ -262,28 +180,19 @@ return; } - const base::Value* status = - properties->FindDictKey(shill::kTetheringStatusProperty); + const base::Value::Dict* status = + properties->GetDict().FindDict(shill::kTetheringStatusProperty); if (!status) { NET_LOG(EVENT) << "HotspotStateHandler: No dict value for: " << shill::kTetheringStatusProperty; } else { UpdateHotspotStatus(*status); } - - const base::Value* capabilities = - properties->FindDictKey(shill::kTetheringCapabilitiesProperty); - if (!capabilities) { - NET_LOG(EVENT) << "HotspotStateHandler: No dict value for: " - << shill::kTetheringCapabilitiesProperty; - } else { - UpdateHotspotCapabilities(*capabilities); - } } -void HotspotStateHandler::UpdateHotspotStatus(const base::Value& status) { +void HotspotStateHandler::UpdateHotspotStatus(const base::Value::Dict& status) { const std::string* state = - status.FindStringKey(shill::kTetheringStatusStateProperty); + status.FindString(shill::kTetheringStatusStateProperty); if (!state) { NET_LOG(EVENT) << "HotspotStateHandler: No string value for: " << shill::kTetheringStatusStateProperty << " in " @@ -310,123 +219,6 @@ NotifyHotspotStatusChanged(); } -void HotspotStateHandler::UpdateHotspotCapabilities( - const base::Value& capabilities) { - using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; - - const base::Value* upstream_technologies = - capabilities.FindListKey(shill::kTetheringCapUpstreamProperty); - if (!upstream_technologies) { - NET_LOG(ERROR) << "No list value for: " - << shill::kTetheringCapUpstreamProperty << " in " - << shill::kTetheringCapabilitiesProperty; - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoCellularUpstream); - return; - } - - if (!base::Contains(upstream_technologies->GetList(), - base::Value(shill::kTypeCellular))) { - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoCellularUpstream); - return; - } - - const base::Value* downstream_technologies = - capabilities.FindListKey(shill::kTetheringCapDownstreamProperty); - if (!downstream_technologies) { - NET_LOG(ERROR) << "No list value for: " - << shill::kTetheringCapDownstreamProperty << " in " - << shill::kTetheringCapabilitiesProperty; - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoWiFiDownstream); - return; - } - - if (!base::Contains(downstream_technologies->GetList(), - base::Value(shill::kTypeWifi))) { - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoWiFiDownstream); - return; - } - - // Update allowed security modes for WiFi downstream - const base::Value* allowed_security_modes_in_shill = - capabilities.FindListKey(shill::kTetheringCapSecurityProperty); - if (!allowed_security_modes_in_shill) { - NET_LOG(ERROR) << "No list value for: " - << shill::kTetheringCapSecurityProperty << " in " - << shill::kTetheringCapabilitiesProperty; - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoWiFiSecurityModes); - return; - } - - UpdateAllowedSecurityList(hotspot_capabilities_.allowed_security_modes, - allowed_security_modes_in_shill->GetList()); - if (hotspot_capabilities_.allowed_security_modes.empty()) { - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoWiFiSecurityModes); - return; - } - - // Check if there's a connected cellular network - const NetworkState* connected_cellular_network = - network_state_handler_->ConnectedNetworkByType( - NetworkTypePattern::Cellular()); - if (!connected_cellular_network) { - SetHotspotCapablities(HotspotAllowStatus::kDisallowedNoMobileData); - return; - } - - CheckTetheringReadiness(base::DoNothing()); -} - -void HotspotStateHandler::CheckTetheringReadiness( - CheckTetheringReadinessCallback callback) { - auto callback_split = base::SplitOnceCallback(std::move(callback)); - ShillManagerClient::Get()->CheckTetheringReadiness( - base::BindOnce(&HotspotStateHandler::OnCheckReadinessSuccess, - weak_ptr_factory_.GetWeakPtr(), - std::move(callback_split.first)), - base::BindOnce(&HotspotStateHandler::OnCheckReadinessFailure, - weak_ptr_factory_.GetWeakPtr(), - std::move(callback_split.second))); -} - -void HotspotStateHandler::OnCheckReadinessSuccess( - CheckTetheringReadinessCallback callback, - const std::string& result) { - using HotspotAllowStatus = hotspot_config::mojom::HotspotAllowStatus; - - if (result == shill::kTetheringReadinessReady) { - SetHotspotCapablities(HotspotAllowStatus::kAllowed); - std::move(callback).Run(CheckTetheringReadinessResult::kReady); - return; - } - if (result == shill::kTetheringReadinessNotAllowed) { - SetHotspotCapablities(HotspotAllowStatus::kDisallowedReadinessCheckFail); - std::move(callback).Run(CheckTetheringReadinessResult::kNotAllowed); - return; - } - NET_LOG(ERROR) << "Unexpected check tethering readiness result: " << result; - std::move(callback).Run(CheckTetheringReadinessResult::kNotAllowed); -} - -void HotspotStateHandler::OnCheckReadinessFailure( - CheckTetheringReadinessCallback callback, - const std::string& error_name, - const std::string& error_message) { - NET_LOG(ERROR) << "Check tethering readiness failed, error name: " - << error_name << ", message: " << error_message; - SetHotspotCapablities( - hotspot_config::mojom::HotspotAllowStatus::kDisallowedReadinessCheckFail); - std::move(callback).Run(CheckTetheringReadinessResult::kShillOperationFailed); -} - -void HotspotStateHandler::SetHotspotCapablities( - hotspot_config::mojom::HotspotAllowStatus new_allow_status) { - if (hotspot_capabilities_.allow_status == new_allow_status) - return; - - hotspot_capabilities_.allow_status = new_allow_status; - NotifyHotspotCapabilitiesChanged(); -} - void HotspotStateHandler::SetPolicyAllowHotspot(bool allow) { // TODO (jiajunz) } @@ -436,9 +228,4 @@ observer.OnHotspotStatusChanged(); } -void HotspotStateHandler::NotifyHotspotCapabilitiesChanged() { - for (auto& observer : observer_list_) - observer.OnHotspotCapabilitiesChanged(); -} - } // namespace ash \ No newline at end of file
diff --git a/chromeos/ash/components/network/hotspot_state_handler.h b/chromeos/ash/components/network/hotspot_state_handler.h index 95addc5..150ff10 100644 --- a/chromeos/ash/components/network/hotspot_state_handler.h +++ b/chromeos/ash/components/network/hotspot_state_handler.h
@@ -15,22 +15,17 @@ #include "base/values.h" #include "chromeos/ash/components/dbus/shill/shill_property_changed_observer.h" #include "chromeos/ash/components/login/login_state/login_state.h" -#include "chromeos/ash/components/network/network_state_handler.h" -#include "chromeos/ash/components/network/network_state_handler_observer.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { -class NetworkStateHandler; - // This class caches hotspot related status and implements methods to get // current state, active client count, capabilities and configure the hotspot // configurations. class COMPONENT_EXPORT(CHROMEOS_NETWORK) HotspotStateHandler : public ShillPropertyChangedObserver, - public LoginState::Observer, - public NetworkStateHandlerObserver { + public LoginState::Observer { public: class Observer : public base::CheckedObserver { public: @@ -39,29 +34,6 @@ // Invoked when hotspot state, active client count or hotspot config is // changed. virtual void OnHotspotStatusChanged() = 0; - // Invoked when hotspot capabilities is changed. - virtual void OnHotspotCapabilitiesChanged() = 0; - }; - - // Represents the hotspot capabilities. Includes: - // 1. The allow status that is calculated from the combination Shill Tethering - // Capabilities and Shill Tethering Readiness check result and policy allow - // status. - // 2. List of allowed WiFi security modes for WiFi downstream. - struct HotspotCapabilities { - HotspotCapabilities( - const hotspot_config::mojom::HotspotAllowStatus allow_status); - ~HotspotCapabilities(); - - hotspot_config::mojom::HotspotAllowStatus allow_status; - std::vector<hotspot_config::mojom::WiFiSecurityMode> allowed_security_modes; - }; - - // Represents the check tethering readiness result. - enum class CheckTetheringReadinessResult { - kReady = 0, - kNotAllowed = 1, - kShillOperationFailed = 2, }; HotspotStateHandler(); @@ -69,17 +41,19 @@ HotspotStateHandler& operator=(const HotspotStateHandler&) = delete; ~HotspotStateHandler() override; - void Init(NetworkStateHandler* network_state_handler); + void Init(); + // Return the latest hotspot state const hotspot_config::mojom::HotspotState& GetHotspotState() const; + // Return the latest hotspot active client count size_t GetHotspotActiveClientCount() const; + // Return the current hotspot configuration hotspot_config::mojom::HotspotConfigPtr GetHotspotConfig() const; - // Return the latest hotspot capabilities - const HotspotCapabilities& GetHotspotCapabilities() const; // Return callback for the SetHotspotConfig method. |success| indicates // whether the operation is success or not. + using SetHotspotConfigCallback = base::OnceCallback<void( hotspot_config::mojom::SetHotspotConfigResult result)>; @@ -87,12 +61,6 @@ // the success result of SetHotspotConfig operation. void SetHotspotConfig(hotspot_config::mojom::HotspotConfigPtr config, SetHotspotConfigCallback callback); - - using CheckTetheringReadinessCallback = - base::OnceCallback<void(CheckTetheringReadinessResult result)>; - // Check tethering readiness and update the hotspot_capabilities_ if - // necessary. |callback| is called with check readiness result. - void CheckTetheringReadiness(CheckTetheringReadinessCallback callback); // Set whether Hotspot should be allowed/disallowed by policy. void SetPolicyAllowHotspot(bool allow); @@ -108,23 +76,16 @@ // LoginState::Observer void LoggedInStateChanged() override; - // NetworkStateHandlerObserver - void NetworkConnectionStateChanged(const NetworkState* network) override; - void OnShuttingDown() override; - // Callback to handle the manager properties with hotspot related properties. void OnManagerProperties(absl::optional<base::Value> properties); // Update the cached hotspot_state_ and active_client_count_ from hotspot // status in Shill. - void UpdateHotspotStatus(const base::Value& status); + void UpdateHotspotStatus(const base::Value::Dict& status); // Notify observers that hotspot state or active client count was changed. void NotifyHotspotStatusChanged(); - // Notify observer that hotspot capabilities was changed. - void NotifyHotspotCapabilitiesChanged(); - // Update the cached hotspot_config_ with the tethering configuration // from |manager_properties|, and then run the |callback|. void UpdateHotspotConfigAndRunCallback( @@ -139,37 +100,11 @@ const std::string& error_name, const std::string& error_message); - // Update the cached hotspot_capabilities_ from the tethering capabilities - // values from Shill. This function is called whenever the tethering - // capabilities value is changed in Shill. - void UpdateHotspotCapabilities(const base::Value& capabilities); - - // Callback when the CheckTetheringReadiness operation succeeded. - void OnCheckReadinessSuccess(CheckTetheringReadinessCallback callback, - const std::string& result); - - // Callback when the CheckTetheringReadiness operation failed. - void OnCheckReadinessFailure(CheckTetheringReadinessCallback callback, - const std::string& error_name, - const std::string& error_message); - - // Update the hotspot_capabilities_ with the given |new_allow_status| - // and then notify observers if it changes. - void SetHotspotCapablities( - hotspot_config::mojom::HotspotAllowStatus new_allow_status); - - void ResetNetworkStateHandler(); - hotspot_config::mojom::HotspotState hotspot_state_ = hotspot_config::mojom::HotspotState::kDisabled; - HotspotCapabilities hotspot_capabilities_{ - hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream}; - absl::optional<base::Value> hotspot_config_ = absl::nullopt; + absl::optional<base::Value::Dict> hotspot_config_ = absl::nullopt; size_t active_client_count_ = 0; - NetworkStateHandler* network_state_handler_ = nullptr; - base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver> - network_state_handler_observer_{this}; base::ObserverList<Observer> observer_list_; base::WeakPtrFactory<HotspotStateHandler> weak_ptr_factory_{this}; };
diff --git a/chromeos/ash/components/network/hotspot_state_handler_unittest.cc b/chromeos/ash/components/network/hotspot_state_handler_unittest.cc index 304ee4e..363a228f 100644 --- a/chromeos/ash/components/network/hotspot_state_handler_unittest.cc +++ b/chromeos/ash/components/network/hotspot_state_handler_unittest.cc
@@ -23,9 +23,6 @@ const char kHotspotConfigSSID[] = "hotspot_SSID"; const char kHotspotConfigPassphrase[] = "hotspot_passphrase"; -const char kCellularServicePath[] = "/service/cellular0"; -const char kCellularServiceGuid[] = "cellular_guid0"; -const char kCellularServiceName[] = "cellular_name0"; hotspot_config::mojom::HotspotConfigPtr GenerateTestConfig() { auto mojom_config = hotspot_config::mojom::HotspotConfig::New(); @@ -48,21 +45,12 @@ // HotspotStateHandler::Observer: void OnHotspotStatusChanged() override { hotspot_status_changed_count_++; } - void OnHotspotCapabilitiesChanged() override { - hotspot_capabilities_changed_count_++; - } - size_t hotspot_status_changed_count() { return hotspot_status_changed_count_; } - size_t hotspot_capabilities_changed_count() { - return hotspot_capabilities_changed_count_; - } - private: size_t hotspot_status_changed_count_ = 0u; - size_t hotspot_capabilities_changed_count_ = 0u; }; class HotspotStateHandlerTest : public ::testing::Test { @@ -78,8 +66,7 @@ } hotspot_state_handler_ = std::make_unique<HotspotStateHandler>(); hotspot_state_handler_->AddObserver(&observer_); - hotspot_state_handler_->Init( - network_state_test_helper_.network_state_handler()); + hotspot_state_handler_->Init(); base::RunLoop().RunUntilIdle(); } @@ -106,18 +93,6 @@ return result; } - HotspotStateHandler::CheckTetheringReadinessResult CheckTetheringReadiness() { - base::RunLoop run_loop; - HotspotStateHandler::CheckTetheringReadinessResult return_result; - hotspot_state_handler_->CheckTetheringReadiness(base::BindLambdaForTesting( - [&](HotspotStateHandler::CheckTetheringReadinessResult result) { - return_result = result; - run_loop.QuitClosure(); - })); - run_loop.RunUntilIdle(); - return return_result; - } - void LoginToRegularUser() { LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_ACTIVE, LoginState::LOGGED_IN_USER_REGULAR); @@ -145,11 +120,11 @@ hotspot_config::mojom::HotspotState::kDisabled); // Update tethering status to active in Shill. - base::Value status_dict(base::Value::Type::DICTIONARY); - status_dict.GetDict().Set(shill::kTetheringStatusStateProperty, - base::Value(shill::kTetheringStateActive)); + base::Value::Dict status_dict; + status_dict.Set(shill::kTetheringStatusStateProperty, + shill::kTetheringStateActive); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(hotspot_state_handler_->GetHotspotState(), @@ -157,10 +132,10 @@ EXPECT_EQ(1u, observer_.hotspot_status_changed_count()); // Update tethering status to idle in Shill. - status_dict.GetDict().Set(shill::kTetheringStatusStateProperty, - base::Value(shill::kTetheringStateIdle)); + status_dict.Set(shill::kTetheringStatusStateProperty, + shill::kTetheringStateIdle); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(hotspot_state_handler_->GetHotspotState(), @@ -168,10 +143,10 @@ EXPECT_EQ(2u, observer_.hotspot_status_changed_count()); // Simulate user starting tethering. - status_dict.GetDict().Set(shill::kTetheringStatusStateProperty, - base::Value(shill::kTetheringStateStarting)); + status_dict.Set(shill::kTetheringStatusStateProperty, + shill::kTetheringStateStarting); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(hotspot_state_handler_->GetHotspotState(), @@ -182,11 +157,11 @@ TEST_F(HotspotStateHandlerTest, GetHotspotActiveClientCount) { EXPECT_EQ(0u, hotspot_state_handler_->GetHotspotActiveClientCount()); - base::Value status_dict(base::Value::Type::DICTIONARY); - status_dict.GetDict().Set(shill::kTetheringStatusStateProperty, - base::Value(shill::kTetheringStateActive)); + base::Value::Dict status_dict; + status_dict.Set(shill::kTetheringStatusStateProperty, + shill::kTetheringStateActive); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0u, hotspot_state_handler_->GetHotspotActiveClientCount()); @@ -199,128 +174,26 @@ client.Set(shill::kTetheringStatusClientHostnameProperty, "hostname1"); client.Set(shill::kTetheringStatusClientMACProperty, "persist"); active_clients_list.Append(std::move(client)); - status_dict.GetDict().Set(shill::kTetheringStatusClientsProperty, - std::move(active_clients_list)); + status_dict.Set(shill::kTetheringStatusClientsProperty, + std::move(active_clients_list)); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1u, hotspot_state_handler_->GetHotspotActiveClientCount()); EXPECT_EQ(2u, observer_.hotspot_status_changed_count()); - status_dict.GetDict().Set(shill::kTetheringStatusStateProperty, - base::Value(shill::kTetheringStateIdle)); - status_dict.GetDict().Remove(shill::kTetheringStatusClientsProperty); + status_dict.Set(shill::kTetheringStatusStateProperty, + shill::kTetheringStateIdle); + status_dict.Remove(shill::kTetheringStatusClientsProperty); network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringStatusProperty, status_dict); + shill::kTetheringStatusProperty, base::Value(status_dict.Clone())); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0u, hotspot_state_handler_->GetHotspotActiveClientCount()); EXPECT_EQ(3u, observer_.hotspot_status_changed_count()); } -TEST_F(HotspotStateHandlerTest, GetHotspotCapabilities) { - EXPECT_EQ( - hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(0u, observer_.hotspot_capabilities_changed_count()); - - base::Value capabilities_dict(base::Value::Type::DICTIONARY); - capabilities_dict.GetDict().Set(shill::kTetheringCapUpstreamProperty, - base::Value(base::Value::Type::LIST)); - capabilities_dict.GetDict().Set(shill::kTetheringCapDownstreamProperty, - base::Value(base::Value::Type::LIST)); - capabilities_dict.GetDict().Set(shill::kTetheringCapSecurityProperty, - base::Value(base::Value::Type::LIST)); - network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringCapabilitiesProperty, capabilities_dict); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ( - hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoCellularUpstream, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(0u, observer_.hotspot_capabilities_changed_count()); - - base::Value::List upstream_list; - upstream_list.Append(shill::kTypeCellular); - capabilities_dict.GetDict().Set(shill::kTetheringCapUpstreamProperty, - std::move(upstream_list)); - network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringCapabilitiesProperty, capabilities_dict); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ( - hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoWiFiDownstream, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(1u, observer_.hotspot_capabilities_changed_count()); - - // Add WiFi to the downstream technology list in Shill - base::Value::List downstream_list; - downstream_list.Append(shill::kTypeWifi); - capabilities_dict.GetDict().Set(shill::kTetheringCapDownstreamProperty, - std::move(downstream_list)); - // Add allowed WiFi security mode in Shill - base::Value::List security_list; - security_list.Append(shill::kSecurityWpa2); - security_list.Append(shill::kSecurityWpa3); - capabilities_dict.GetDict().Set(shill::kTetheringCapSecurityProperty, - std::move(security_list)); - network_state_test_helper_.manager_test()->SetManagerProperty( - shill::kTetheringCapabilitiesProperty, capabilities_dict); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoMobileData, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(2u, hotspot_state_handler_->GetHotspotCapabilities() - .allowed_security_modes.size()); - EXPECT_EQ(2u, observer_.hotspot_capabilities_changed_count()); - - // Add an active cellular network and simulate check tethering readiness - // operation fail. - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kFailure, - /*readiness_status=*/std::string()); - ShillServiceClient::TestInterface* service_test = - network_state_test_helper_.service_test(); - service_test->AddService(kCellularServicePath, kCellularServiceGuid, - kCellularServiceName, shill::kTypeCellular, - shill::kStateOnline, /*visible=*/true); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ( - hotspot_config::mojom::HotspotAllowStatus::kDisallowedReadinessCheckFail, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(3u, observer_.hotspot_capabilities_changed_count()); - - // Disconnect the active cellular network - service_test->SetServiceProperty(kCellularServicePath, shill::kStateProperty, - base::Value(shill::kStateIdle)); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(hotspot_config::mojom::HotspotAllowStatus::kDisallowedNoMobileData, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(4u, observer_.hotspot_capabilities_changed_count()); - - // Simulate check tethering readiness operation success and re-connect the - // cellular network - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kSuccess, shill::kTetheringReadinessReady); - service_test->SetServiceProperty(kCellularServicePath, shill::kStateProperty, - base::Value(shill::kStateOnline)); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(hotspot_config::mojom::HotspotAllowStatus::kAllowed, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); - EXPECT_EQ(5u, observer_.hotspot_capabilities_changed_count()); - - hotspot_state_handler_->SetPolicyAllowHotspot(/*allow*/ false); - base::RunLoop().RunUntilIdle(); - // TODO (jiajunz): Should expect equal after SetPolicyAllowHotspot() is - // implemented. - EXPECT_NE(hotspot_config::mojom::HotspotAllowStatus::kDisallowedByPolicy, - hotspot_state_handler_->GetHotspotCapabilities().allow_status); -} - TEST_F(HotspotStateHandlerTest, SetAndGetHotspotConfig) { EXPECT_EQ(hotspot_config::mojom::SetHotspotConfigResult::kFailedNotLogin, SetHotspotConfig(GenerateTestConfig())); @@ -346,38 +219,4 @@ EXPECT_EQ(2u, observer_.hotspot_status_changed_count()); } -TEST_F(HotspotStateHandlerTest, CheckTetheringReadiness) { - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kSuccess, shill::kTetheringReadinessReady); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CheckTetheringReadiness(), - HotspotStateHandler::CheckTetheringReadinessResult::kReady); - - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kSuccess, - shill::kTetheringReadinessNotAllowed); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CheckTetheringReadiness(), - HotspotStateHandler::CheckTetheringReadinessResult::kNotAllowed); - - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kSuccess, - /*readiness_result=*/std::string()); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CheckTetheringReadiness(), - HotspotStateHandler::CheckTetheringReadinessResult::kNotAllowed); - - network_state_test_helper_.manager_test() - ->SetSimulateCheckTetheringReadinessResult( - FakeShillSimulatedResult::kFailure, - /*readiness_result=*/std::string()); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CheckTetheringReadiness(), - HotspotStateHandler::CheckTetheringReadinessResult:: - kShillOperationFailed); -} - } // namespace ash
diff --git a/chromeos/ash/components/network/hotspot_util.cc b/chromeos/ash/components/network/hotspot_util.cc index 78c03bde4..0ffafa1 100644 --- a/chromeos/ash/components/network/hotspot_util.cc +++ b/chromeos/ash/components/network/hotspot_util.cc
@@ -5,7 +5,6 @@ #include "chromeos/ash/components/network/hotspot_util.h" #include "base/strings/string_number_conversions.h" -#include "base/values.h" #include "chromeos/ash/components/network/network_event_log.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -113,18 +112,18 @@ } hotspot_config::mojom::HotspotConfigPtr ShillTetheringConfigToMojomConfig( - const base::Value& shill_tethering_config) { + const base::Value::Dict& shill_tethering_config) { using hotspot_config::mojom::HotspotConfig; auto result = HotspotConfig::New(); - absl::optional<bool> auto_disable = shill_tethering_config.GetDict().FindBool( - shill::kTetheringConfAutoDisableProperty); + absl::optional<bool> auto_disable = + shill_tethering_config.FindBool(shill::kTetheringConfAutoDisableProperty); if (!auto_disable) { NET_LOG(ERROR) << "Auto_disable not found in tethering config."; } result->auto_disable = auto_disable.value_or(true); - const std::string* wifi_band = shill_tethering_config.GetDict().FindString( - shill::kTetheringConfBandProperty); + const std::string* wifi_band = + shill_tethering_config.FindString(shill::kTetheringConfBandProperty); if (!wifi_band) { NET_LOG(ERROR) << "WiFi band not found in tethering config."; result->band = hotspot_config::mojom::WiFiBand::kAutoChoose; @@ -132,8 +131,8 @@ result->band = ShillBandToMojom(*wifi_band); } - const std::string* security = shill_tethering_config.GetDict().FindString( - shill::kTetheringConfSecurityProperty); + const std::string* security = + shill_tethering_config.FindString(shill::kTetheringConfSecurityProperty); if (!security) { NET_LOG(ERROR) << "WiFi security mode not found in tethering config."; result->security = hotspot_config::mojom::WiFiSecurityMode::kWpa2; @@ -141,21 +140,20 @@ result->security = ShillSecurityToMojom(*security); } - const std::string* ssid = shill_tethering_config.GetDict().FindString( - shill::kTetheringConfSSIDProperty); + const std::string* ssid = + shill_tethering_config.FindString(shill::kTetheringConfSSIDProperty); if (!ssid) { NET_LOG(ERROR) << "SSID not found in tethering config."; } result->ssid = ssid ? HexDecode(*ssid) : std::string(); - const std::string* passphrase = shill_tethering_config.GetDict().FindString( + const std::string* passphrase = shill_tethering_config.FindString( shill::kTetheringConfPassphraseProperty); if (!passphrase) { NET_LOG(ERROR) << "Passphrase not found in tethering config."; } result->passphrase = passphrase ? *passphrase : std::string(); absl::optional<bool> bssid_randomization = - shill_tethering_config.GetDict().FindBool( - shill::kTetheringConfMARProperty); + shill_tethering_config.FindBool(shill::kTetheringConfMARProperty); if (!bssid_randomization) { NET_LOG(ERROR) << shill::kTetheringConfMARProperty << " not found in tethering config.";
diff --git a/chromeos/ash/components/network/hotspot_util.h b/chromeos/ash/components/network/hotspot_util.h index 0b0e50bf..96b4f54 100644 --- a/chromeos/ash/components/network/hotspot_util.h +++ b/chromeos/ash/components/network/hotspot_util.h
@@ -5,15 +5,10 @@ #ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_HOTSPOT_UTIL_H_ #define CHROMEOS_ASH_COMPONENTS_NETWORK_HOTSPOT_UTIL_H_ -#include <string> - #include "base/component_export.h" +#include "base/values.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-forward.h" -namespace base { -class Value; -} // namespace base - namespace ash { // Convert shill tethering state string value to mojom::HotspotState enum @@ -29,7 +24,7 @@ // Convert shill tethering config dictionary value to mojom::HotspotConfigPtr COMPONENT_EXPORT(CHROMEOS_NETWORK) hotspot_config::mojom::HotspotConfigPtr ShillTetheringConfigToMojomConfig( - const base::Value& shill_tethering_config); + const base::Value::Dict& shill_tethering_config); // Convert mojom::HotspotConfigPtr to the corresponding shill tethering config // value
diff --git a/chromeos/ash/components/network/network_handler.cc b/chromeos/ash/components/network/network_handler.cc index 1d1284a..e7a00db 100644 --- a/chromeos/ash/components/network/network_handler.cc +++ b/chromeos/ash/components/network/network_handler.cc
@@ -18,6 +18,7 @@ #include "chromeos/ash/components/network/geolocation_handler.h" #include "chromeos/ash/components/network/hidden_network_handler.h" #include "chromeos/ash/components/network/hotspot_allowed_flag_handler.h" +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" #include "chromeos/ash/components/network/hotspot_controller.h" #include "chromeos/ash/components/network/hotspot_state_handler.h" #include "chromeos/ash/components/network/managed_cellular_pref_handler.h" @@ -75,8 +76,9 @@ hidden_network_handler_.reset(new HiddenNetworkHandler()); } if (ash::features::IsHotspotEnabled()) { - hotspot_state_handler_.reset(new HotspotStateHandler()); + hotspot_capabilities_provider_.reset(new HotspotCapabilitiesProvider()); hotspot_controller_.reset(new HotspotController()); + hotspot_state_handler_.reset(new HotspotStateHandler()); } if (NetworkCertLoader::IsInitialized()) { network_cert_migrator_.reset(new NetworkCertMigrator()); @@ -139,8 +141,9 @@ } hotspot_allowed_flag_handler_->Init(); if (ash::features::IsHotspotEnabled()) { - hotspot_state_handler_->Init(network_state_handler_.get()); - hotspot_controller_->Init(hotspot_state_handler_.get()); + hotspot_capabilities_provider_->Init(network_state_handler_.get()); + hotspot_controller_->Init(hotspot_capabilities_provider_.get()); + hotspot_state_handler_->Init(); } managed_cellular_pref_handler_->Init(network_state_handler_.get()); esim_policy_login_metrics_logger_->Init( @@ -278,6 +281,10 @@ return hidden_network_handler_.get(); } +HotspotCapabilitiesProvider* NetworkHandler::hotspot_capabilities_provider() { + return hotspot_capabilities_provider_.get(); +} + HotspotController* NetworkHandler::hotspot_controller() { return hotspot_controller_.get(); }
diff --git a/chromeos/ash/components/network/network_handler.h b/chromeos/ash/components/network/network_handler.h index 2a2a49c..f5a0e28b 100644 --- a/chromeos/ash/components/network/network_handler.h +++ b/chromeos/ash/components/network/network_handler.h
@@ -30,6 +30,7 @@ class GeolocationHandler; class HiddenNetworkHandler; class HotspotAllowedFlagHandler; +class HotspotCapabilitiesProvider; class HotspotController; class HotspotStateHandler; class ManagedCellularPrefHandler; @@ -110,6 +111,7 @@ CellularInhibitor* cellular_inhibitor(); CellularPolicyHandler* cellular_policy_handler(); HiddenNetworkHandler* hidden_network_handler(); + HotspotCapabilitiesProvider* hotspot_capabilities_provider(); HotspotController* hotspot_controller(); HotspotStateHandler* hotspot_state_handler(); NetworkStateHandler* network_state_handler(); @@ -157,8 +159,9 @@ std::unique_ptr<ConnectionInfoMetricsLogger> connection_info_metrics_logger_; std::unique_ptr<HiddenNetworkHandler> hidden_network_handler_; std::unique_ptr<HotspotAllowedFlagHandler> hotspot_allowed_flag_handler_; - std::unique_ptr<HotspotStateHandler> hotspot_state_handler_; + std::unique_ptr<HotspotCapabilitiesProvider> hotspot_capabilities_provider_; std::unique_ptr<HotspotController> hotspot_controller_; + std::unique_ptr<HotspotStateHandler> hotspot_state_handler_; std::unique_ptr<ESimPolicyLoginMetricsLogger> esim_policy_login_metrics_logger_; std::unique_ptr<HiddenNetworkMetricsHelper> hidden_network_metrics_helper_;
diff --git a/chromeos/ash/resources/BUILD.gn b/chromeos/ash/resources/BUILD.gn index 9a13b0a..0906086 100644 --- a/chromeos/ash/resources/BUILD.gn +++ b/chromeos/ash/resources/BUILD.gn
@@ -36,6 +36,6 @@ "//chromeos/ash/services/device_sync/public/mojom:mojom_js", "//chromeos/ash/services/hotspot_config/public/mojom:mojom_js", "//chromeos/ash/services/multidevice_setup/public/mojom:mojom_js", - "//chromeos/ash/services/nearby/public/mojom:mojom_js", + "//chromeos/ash/services/nearby/public/mojom:nearby_share_settings_js", ] }
diff --git a/chromeos/ash/services/auth_factor_config/BUILD.gn b/chromeos/ash/services/auth_factor_config/BUILD.gn index 1fc52c59..4a51951 100644 --- a/chromeos/ash/services/auth_factor_config/BUILD.gn +++ b/chromeos/ash/services/auth_factor_config/BUILD.gn
@@ -10,9 +10,11 @@ sources = [ "auth_factor_config.cc", "auth_factor_config.h", + "chrome_browser_delegates.h", "in_process_instances.cc", "in_process_instances.h", - "quick_unlock_storage_delegate.h", + "pin_factor_editor.cc", + "pin_factor_editor.h", "recovery_factor_editor.cc", "recovery_factor_editor.h", ]
diff --git a/chromeos/ash/services/auth_factor_config/auth_factor_config.cc b/chromeos/ash/services/auth_factor_config/auth_factor_config.cc index 7fd28764..83e82554 100644 --- a/chromeos/ash/services/auth_factor_config/auth_factor_config.cc +++ b/chromeos/ash/services/auth_factor_config/auth_factor_config.cc
@@ -88,7 +88,21 @@ : mojom::ManagementType::kNone; std::move(callback).Run(result); - break; + return; + } + case mojom::AuthFactor::kPin: { + const auto* user = ::user_manager::UserManager::Get()->GetPrimaryUser(); + CHECK(user); + const PrefService* prefs = quick_unlock_storage_->GetPrefService(*user); + CHECK(prefs); + + if (prefs->IsManagedPreference(prefs::kQuickUnlockModeAllowlist) || + prefs->IsManagedPreference(prefs::kWebAuthnFactors)) { + std::move(callback).Run(mojom::ManagementType::kUser); + } else { + std::move(callback).Run(mojom::ManagementType::kNone); + } + return; } } } @@ -106,7 +120,37 @@ std::move(callback).Run( prefs->IsUserModifiablePreference(prefs::kRecoveryFactorBehavior)); - break; + return; + } + case mojom::AuthFactor::kPin: { + const auto* user = ::user_manager::UserManager::Get()->GetPrimaryUser(); + CHECK(user); + const PrefService* prefs = quick_unlock_storage_->GetPrefService(*user); + CHECK(prefs); + + // Lists of factors that are allowed for some purpose. + const base::Value::List* pref_lists[] = { + &prefs->GetList(prefs::kQuickUnlockModeAllowlist), + &prefs->GetList(prefs::kWebAuthnFactors), + }; + + // Values in factor lists that match PINs. + const base::Value pref_list_values[] = { + base::Value("all"), + base::Value("PIN"), + }; + + for (const auto* pref_list : pref_lists) { + for (const auto& pref_list_value : pref_list_values) { + if (base::Contains(*pref_list, pref_list_value)) { + std::move(callback).Run(true); + return; + } + } + } + + std::move(callback).Run(false); + return; } } }
diff --git a/chromeos/ash/services/auth_factor_config/auth_factor_config.h b/chromeos/ash/services/auth_factor_config/auth_factor_config.h index 5ffb625b..725357a5 100644 --- a/chromeos/ash/services/auth_factor_config/auth_factor_config.h +++ b/chromeos/ash/services/auth_factor_config/auth_factor_config.h
@@ -5,8 +5,8 @@ #ifndef CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_AUTH_FACTOR_CONFIG_H_ #define CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_AUTH_FACTOR_CONFIG_H_ +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" #include "chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom.h" -#include "chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h b/chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h new file mode 100644 index 0000000..bd65f25 --- /dev/null +++ b/chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h
@@ -0,0 +1,54 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_CHROME_BROWSER_DELEGATES_H_ +#define CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_CHROME_BROWSER_DELEGATES_H_ + +#include <memory> +#include <string> +#include "base/functional/callback.h" +#include "chromeos/ash/components/login/auth/public/user_context.h" +#include "components/prefs/pref_service.h" +#include "components/user_manager/user.h" + +namespace ash::auth { + +class QuickUnlockStorageDelegate { + public: + QuickUnlockStorageDelegate() = default; + QuickUnlockStorageDelegate(const QuickUnlockStorageDelegate&) = delete; + QuickUnlockStorageDelegate& operator=(const QuickUnlockStorageDelegate&) = + delete; + virtual ~QuickUnlockStorageDelegate() = default; + + virtual UserContext* GetUserContext(const ::user_manager::User* user, + const std::string& token) = 0; + virtual void SetUserContext(const ::user_manager::User* user, + std::unique_ptr<UserContext> user_context) = 0; + + virtual PrefService* GetPrefService(const ::user_manager::User& user) = 0; +}; + +class PinBackendDelegate { + public: + using BoolCallback = base::OnceCallback<void(bool)>; + + PinBackendDelegate() = default; + PinBackendDelegate(const PinBackendDelegate&) = delete; + PinBackendDelegate& operator=(const PinBackendDelegate&) = delete; + virtual ~PinBackendDelegate() = default; + + virtual void Set(const AccountId& account_id, + const std::string& auth_token, + const std::string& pin, + BoolCallback did_set) = 0; + + virtual void Remove(const AccountId& account_id, + const std::string& auth_token, + BoolCallback did_remove) = 0; +}; + +} // namespace ash::auth + +#endif // CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_CHROME_BROWSER_DELEGATES_H_
diff --git a/chromeos/ash/services/auth_factor_config/in_process_instances.cc b/chromeos/ash/services/auth_factor_config/in_process_instances.cc index 686bdaa..6420a3c 100644 --- a/chromeos/ash/services/auth_factor_config/in_process_instances.cc +++ b/chromeos/ash/services/auth_factor_config/in_process_instances.cc
@@ -8,6 +8,7 @@ #include "base/no_destructor.h" #include "chromeos/ash/services/auth_factor_config/auth_factor_config.h" +#include "chromeos/ash/services/auth_factor_config/pin_factor_editor.h" #include "chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-test-utils.h" #include "chromeos/ash/services/auth_factor_config/recovery_factor_editor.h" @@ -28,6 +29,13 @@ return *recovery_factor_editor; } +PinFactorEditor& GetPinFactorEditorImpl(QuickUnlockStorageDelegate& storage, + PinBackendDelegate& pin_backend) { + static base::NoDestructor<PinFactorEditor> pin_factor_editor( + &GetAuthFactorConfigImpl(storage), &pin_backend, &storage); + return *pin_factor_editor; +} + } // namespace void BindToAuthFactorConfig( @@ -52,4 +60,12 @@ return GetRecoveryFactorEditorImpl(delegate); } +void BindToPinFactorEditor( + mojo::PendingReceiver<mojom::PinFactorEditor> receiver, + QuickUnlockStorageDelegate& storage, + PinBackendDelegate& pin_backend) { + GetPinFactorEditorImpl(storage, pin_backend) + .BindReceiver(std::move(receiver)); +} + } // namespace ash::auth
diff --git a/chromeos/ash/services/auth_factor_config/in_process_instances.h b/chromeos/ash/services/auth_factor_config/in_process_instances.h index d90fe86..91ff755 100644 --- a/chromeos/ash/services/auth_factor_config/in_process_instances.h +++ b/chromeos/ash/services/auth_factor_config/in_process_instances.h
@@ -5,8 +5,8 @@ #ifndef CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_IN_PROCESS_INSTANCES_H_ #define CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_IN_PROCESS_INSTANCES_H_ +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" #include "chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-forward.h" -#include "chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h" #include "chromeos/ash/services/auth_factor_config/recovery_factor_editor.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -32,6 +32,11 @@ mojom::RecoveryFactorEditor& GetRecoveryFactorEditor( QuickUnlockStorageDelegate&); +void BindToPinFactorEditor( + mojo::PendingReceiver<mojom::PinFactorEditor> receiver, + QuickUnlockStorageDelegate&, + PinBackendDelegate&); + } // namespace ash::auth #endif // CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_IN_PROCESS_INSTANCES_H_
diff --git a/chromeos/ash/services/auth_factor_config/pin_factor_editor.cc b/chromeos/ash/services/auth_factor_config/pin_factor_editor.cc new file mode 100644 index 0000000..373e4b36 --- /dev/null +++ b/chromeos/ash/services/auth_factor_config/pin_factor_editor.cc
@@ -0,0 +1,81 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/ash/services/auth_factor_config/pin_factor_editor.h" +#include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" +#include "chromeos/ash/services/auth_factor_config/auth_factor_config.h" +#include "components/user_manager/known_user.h" +#include "components/user_manager/user_manager.h" + +namespace ash::auth { + +PinFactorEditor::PinFactorEditor(AuthFactorConfig* auth_factor_config, + PinBackendDelegate* pin_backend, + QuickUnlockStorageDelegate* storage) + : auth_factor_config_(auth_factor_config), + pin_backend_(pin_backend), + quick_unlock_storage_(storage) { + CHECK(auth_factor_config_); + CHECK(pin_backend_); + CHECK(quick_unlock_storage_); +} + +PinFactorEditor::~PinFactorEditor() = default; + +void PinFactorEditor::SetPin( + const std::string& auth_token, + const std::string& pin, + base::OnceCallback<void(mojom::ConfigureResult)> callback) { + const auto* user = user_manager::UserManager::Get()->GetPrimaryUser(); + CHECK(user); + auto* user_context_ptr = + quick_unlock_storage_->GetUserContext(user, auth_token); + if (user_context_ptr == nullptr) { + LOG(ERROR) << "Invalid auth token"; + std::move(callback).Run(mojom::ConfigureResult::kInvalidTokenError); + return; + } + + pin_backend_->Set( + user->GetAccountId(), auth_token, pin, + base::BindOnce(&PinFactorEditor::OnPinConfigured, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void PinFactorEditor::RemovePin( + const std::string& auth_token, + base::OnceCallback<void(mojom::ConfigureResult)> callback) { + const auto* user = user_manager::UserManager::Get()->GetPrimaryUser(); + CHECK(user); + auto* user_context_ptr = + quick_unlock_storage_->GetUserContext(user, auth_token); + if (user_context_ptr == nullptr) { + LOG(ERROR) << "Invalid auth token"; + std::move(callback).Run(mojom::ConfigureResult::kInvalidTokenError); + return; + } + + pin_backend_->Remove( + user->GetAccountId(), auth_token, + base::BindOnce(&PinFactorEditor::OnPinConfigured, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void PinFactorEditor::OnPinConfigured( + base::OnceCallback<void(mojom::ConfigureResult)> callback, + bool success) { + const mojom::ConfigureResult result = + success ? mojom::ConfigureResult::kSuccess + : mojom::ConfigureResult::kFatalError; + std::move(callback).Run(result); + auth_factor_config_->NotifyFactorObservers(mojom::AuthFactor::kPin); +} + +void PinFactorEditor::BindReceiver( + mojo::PendingReceiver<mojom::PinFactorEditor> receiver) { + receivers_.Add(this, std::move(receiver)); +} + +} // namespace ash::auth
diff --git a/chromeos/ash/services/auth_factor_config/pin_factor_editor.h b/chromeos/ash/services/auth_factor_config/pin_factor_editor.h new file mode 100644 index 0000000..733767d --- /dev/null +++ b/chromeos/ash/services/auth_factor_config/pin_factor_editor.h
@@ -0,0 +1,57 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_PIN_FACTOR_EDITOR_H_ +#define CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_PIN_FACTOR_EDITOR_H_ + +#include "chromeos/ash/components/login/auth/auth_factor_editor.h" +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" +#include "chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom.h" +#include "mojo/public/cpp/bindings/receiver_set.h" + +namespace ash::auth { + +class AuthFactorConfig; + +// The implementation of the PinFactorEditor service. +// TODO(crbug.com/1327627): This is currently a fake and only flips a boolean +// corresponding to the current state. No changes are sent to cryptohome. +// Clients may use this API only if the CryptohomeRecoverySetup feature flag is +// enabled. +class PinFactorEditor : public mojom::PinFactorEditor { + public: + PinFactorEditor(AuthFactorConfig*, + PinBackendDelegate* pin_backend, + QuickUnlockStorageDelegate* storage); + ~PinFactorEditor() override; + + PinFactorEditor(const PinFactorEditor&) = delete; + PinFactorEditor& operator=(const PinFactorEditor&) = delete; + + void SetPin( + const std::string& auth_token, + const std::string& pin, + base::OnceCallback<void(mojom::ConfigureResult)> callback) override; + void RemovePin( + const std::string& auth_token, + base::OnceCallback<void(mojom::ConfigureResult)> callback) override; + + void BindReceiver(mojo::PendingReceiver<mojom::PinFactorEditor> receiver); + + private: + void OnPinConfigured( + base::OnceCallback<void(mojom::ConfigureResult)> callback, + bool success); + + raw_ptr<AuthFactorConfig> auth_factor_config_; + raw_ptr<PinBackendDelegate> pin_backend_; + raw_ptr<QuickUnlockStorageDelegate> quick_unlock_storage_; + mojo::ReceiverSet<mojom::PinFactorEditor> receivers_; + AuthFactorEditor auth_factor_editor_; + base::WeakPtrFactory<PinFactorEditor> weak_factory_{this}; +}; + +} // namespace ash::auth + +#endif // CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_PIN_FACTOR_EDITOR_H_
diff --git a/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom b/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom index b3d8169..d29d6a719 100644 --- a/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom +++ b/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom
@@ -21,9 +21,9 @@ // An enumeration of all authentication factors. enum AuthFactor { kRecovery, + kPin, // TODO(crbug.com/1327627): Add support for other authentication factors: // kPassword, - // kPin, // kFingerprint, }; @@ -69,21 +69,37 @@ IsEditable(string auth_token, AuthFactor factor) => (bool editable); }; +// Returned from various operations that change ("configure") something about +// an auth factor. +enum ConfigureResult { + // The configuration operation was successful. + kSuccess, + // Returned if the token used to access configuration was invalid. Clients + // should obtain a new token before trying again. + kInvalidTokenError, + // Returned if the client uses the API incorrectly or the backend could not + // process the request. + kFatalError, +}; + // Interface for methods specific to recovery authentication. Served from chrome // ash, intended to be consumed by the following webuis: // * chrome://os-settings // * chrome://oobe interface RecoveryFactorEditor { - // Return code of |Configure|. - enum ConfigureResult { - kSuccess, - kInvalidTokenError, - // Returned if the client uses the API incorrectly, e.g. if the client - // enables recovery even though it is not supported. - kClientError, - }; // Enables or disables recovery authentication. Clients must not attempt to // enable recovery if recovery is not editable. Enabling recovery when it is // already enabled is a no-op and succeeds; similarly for disabling. Configure(string auth_token, bool enabled) => (ConfigureResult result); }; + +// Interface for methods specific to pin authentication. Served from chrome +// ash, intended to be consumed by the following webuis: +// * chrome://os-settings +// * chrome://oobe +interface PinFactorEditor { + // Set the user pin to the desired value. + SetPin(string auth_token, string pin) => (ConfigureResult result); + // Remove the pin factor for the user. + RemovePin(string auth_token) => (ConfigureResult result); +};
diff --git a/chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h b/chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h deleted file mode 100644 index a61546b..0000000 --- a/chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_QUICK_UNLOCK_STORAGE_DELEGATE_H_ -#define CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_QUICK_UNLOCK_STORAGE_DELEGATE_H_ - -#include <memory> -#include <string> -#include "chromeos/ash/components/login/auth/public/user_context.h" -#include "components/prefs/pref_service.h" -#include "components/user_manager/user.h" - -namespace ash::auth { - -class QuickUnlockStorageDelegate { - public: - QuickUnlockStorageDelegate() = default; - QuickUnlockStorageDelegate(const QuickUnlockStorageDelegate&) = delete; - QuickUnlockStorageDelegate& operator=(const QuickUnlockStorageDelegate&) = - delete; - virtual ~QuickUnlockStorageDelegate() = default; - - virtual UserContext* GetUserContext(const ::user_manager::User* user, - const std::string& token) = 0; - virtual void SetUserContext(const ::user_manager::User* user, - std::unique_ptr<UserContext> user_context) = 0; - - virtual PrefService* GetPrefService(const ::user_manager::User& user) = 0; -}; - -} // namespace ash::auth - -#endif // CHROMEOS_ASH_SERVICES_AUTH_FACTOR_CONFIG_QUICK_UNLOCK_STORAGE_DELEGATE_H_
diff --git a/chromeos/ash/services/auth_factor_config/recovery_factor_editor.cc b/chromeos/ash/services/auth_factor_config/recovery_factor_editor.cc index dc8a25a32..0e536ec 100644 --- a/chromeos/ash/services/auth_factor_config/recovery_factor_editor.cc +++ b/chromeos/ash/services/auth_factor_config/recovery_factor_editor.cc
@@ -30,7 +30,7 @@ void RecoveryFactorEditor::Configure( const std::string& auth_token, bool enabled, - base::OnceCallback<void(ConfigureResult)> callback) { + base::OnceCallback<void(mojom::ConfigureResult)> callback) { DCHECK(features::IsCryptohomeRecoverySetupEnabled()); const auto* user = ::user_manager::UserManager::Get()->GetPrimaryUser(); @@ -38,7 +38,7 @@ quick_unlock_storage_->GetUserContext(user, auth_token); if (user_context_ptr == nullptr) { LOG(ERROR) << "Invalid auth token"; - std::move(callback).Run(ConfigureResult::kInvalidTokenError); + std::move(callback).Run(mojom::ConfigureResult::kInvalidTokenError); return; } @@ -47,7 +47,7 @@ cryptohome::AuthFactorType::kRecovery); if (enabled == currently_enabled) { - std::move(callback).Run(ConfigureResult::kSuccess); + std::move(callback).Run(mojom::ConfigureResult::kSuccess); return; } @@ -67,20 +67,20 @@ } void RecoveryFactorEditor::OnRecoveryFactorConfigured( - base::OnceCallback<void(ConfigureResult)> callback, + base::OnceCallback<void(mojom::ConfigureResult)> callback, std::unique_ptr<UserContext> context, absl::optional<AuthenticationError> error) { if (error.has_value()) { // Handle expired auth session gracefully. if (error->get_cryptohome_code() == user_data_auth::CRYPTOHOME_INVALID_AUTH_SESSION_TOKEN) { - std::move(callback).Run(ConfigureResult::kInvalidTokenError); + std::move(callback).Run(mojom::ConfigureResult::kInvalidTokenError); return; } LOG(ERROR) << "Configuring recovery factor failed, code " << error->get_cryptohome_code(); - std::move(callback).Run(ConfigureResult::kClientError); + std::move(callback).Run(mojom::ConfigureResult::kFatalError); return; } @@ -91,13 +91,13 @@ } void RecoveryFactorEditor::OnGetAuthFactorsConfiguration( - base::OnceCallback<void(ConfigureResult)> callback, + base::OnceCallback<void(mojom::ConfigureResult)> callback, std::unique_ptr<UserContext> context, absl::optional<AuthenticationError> error) { if (error.has_value()) { LOG(ERROR) << "Refreshing list of configured auth factors failed, code " << error->get_cryptohome_code(); - std::move(callback).Run(ConfigureResult::kClientError); + std::move(callback).Run(mojom::ConfigureResult::kFatalError); return; } @@ -125,7 +125,7 @@ quick_unlock_storage_->SetUserContext(user, std::move(context)); - std::move(callback).Run(ConfigureResult::kSuccess); + std::move(callback).Run(mojom::ConfigureResult::kSuccess); auth_factor_config_->NotifyFactorObservers(mojom::AuthFactor::kRecovery); }
diff --git a/chromeos/ash/services/auth_factor_config/recovery_factor_editor.h b/chromeos/ash/services/auth_factor_config/recovery_factor_editor.h index 6576129..5e6450b 100644 --- a/chromeos/ash/services/auth_factor_config/recovery_factor_editor.h +++ b/chromeos/ash/services/auth_factor_config/recovery_factor_editor.h
@@ -7,8 +7,8 @@ #include "chromeos/ash/components/login/auth/auth_factor_editor.h" #include "chromeos/ash/components/login/auth/public/authentication_error.h" +#include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" #include "chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom.h" -#include "chromeos/ash/services/auth_factor_config/quick_unlock_storage_delegate.h" #include "mojo/public/cpp/bindings/receiver_set.h" namespace ash::auth { @@ -28,16 +28,16 @@ void Configure(const std::string& auth_token, bool enabled, - base::OnceCallback<void(ConfigureResult)>) override; + base::OnceCallback<void(mojom::ConfigureResult)>) override; private: void OnRecoveryFactorConfigured( - base::OnceCallback<void(ConfigureResult)> callback, + base::OnceCallback<void(mojom::ConfigureResult)> callback, std::unique_ptr<UserContext> context, absl::optional<AuthenticationError> error); void OnGetAuthFactorsConfiguration( - base::OnceCallback<void(ConfigureResult)> callback, + base::OnceCallback<void(mojom::ConfigureResult)> callback, std::unique_ptr<UserContext> context, absl::optional<AuthenticationError> error);
diff --git a/chromeos/ash/services/hotspot_config/cros_hotspot_config.cc b/chromeos/ash/services/hotspot_config/cros_hotspot_config.cc index 1232628..31fc105 100644 --- a/chromeos/ash/services/hotspot_config/cros_hotspot_config.cc +++ b/chromeos/ash/services/hotspot_config/cros_hotspot_config.cc
@@ -10,16 +10,24 @@ namespace ash::hotspot_config { CrosHotspotConfig::CrosHotspotConfig() - : CrosHotspotConfig(NetworkHandler::Get()->hotspot_state_handler(), + : CrosHotspotConfig(NetworkHandler::Get()->hotspot_capabilities_provider(), + NetworkHandler::Get()->hotspot_state_handler(), NetworkHandler::Get()->hotspot_controller()) {} CrosHotspotConfig::CrosHotspotConfig( + ash::HotspotCapabilitiesProvider* hotspot_capabilities_provider, ash::HotspotStateHandler* hotspot_state_handler, ash::HotspotController* hotspot_controller) - : hotspot_state_handler_(hotspot_state_handler), + : hotspot_capabilities_provider_(hotspot_capabilities_provider), + hotspot_state_handler_(hotspot_state_handler), hotspot_controller_(hotspot_controller) {} CrosHotspotConfig::~CrosHotspotConfig() { + if (hotspot_capabilities_provider_ && + hotspot_capabilities_provider_->HasObserver(this)) { + hotspot_capabilities_provider_->RemoveObserver(this); + } + if (hotspot_state_handler_ && hotspot_state_handler_->HasObserver(this)) { hotspot_state_handler_->RemoveObserver(this); } @@ -32,8 +40,13 @@ void CrosHotspotConfig::AddObserver( mojo::PendingRemote<mojom::CrosHotspotConfigObserver> observer) { - if (hotspot_state_handler_ && !hotspot_state_handler_->HasObserver(this)) + if (hotspot_capabilities_provider_ && + !hotspot_capabilities_provider_->HasObserver(this)) { + hotspot_capabilities_provider_->AddObserver(this); + } + if (hotspot_state_handler_ && !hotspot_state_handler_->HasObserver(this)) { hotspot_state_handler_->AddObserver(this); + } observers_.Add(std::move(observer)); } @@ -45,9 +58,10 @@ result->client_count = hotspot_state_handler_->GetHotspotActiveClientCount(); result->config = hotspot_state_handler_->GetHotspotConfig(); result->allow_status = - hotspot_state_handler_->GetHotspotCapabilities().allow_status; + hotspot_capabilities_provider_->GetHotspotCapabilities().allow_status; result->allowed_wifi_security_modes = - hotspot_state_handler_->GetHotspotCapabilities().allowed_security_modes; + hotspot_capabilities_provider_->GetHotspotCapabilities() + .allowed_security_modes; std::move(callback).Run(std::move(result)); } @@ -72,6 +86,7 @@ observer->OnHotspotInfoChanged(); } +// HotspotCapabilitiesProvider::Observer: void CrosHotspotConfig::OnHotspotCapabilitiesChanged() { for (auto& observer : observers_) observer->OnHotspotInfoChanged();
diff --git a/chromeos/ash/services/hotspot_config/cros_hotspot_config.h b/chromeos/ash/services/hotspot_config/cros_hotspot_config.h index f655387..37fd682 100644 --- a/chromeos/ash/services/hotspot_config/cros_hotspot_config.h +++ b/chromeos/ash/services/hotspot_config/cros_hotspot_config.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_SERVICES_HOTSPOT_CONFIG_CROS_HOTSPOT_CONFIG_H_ #include "base/memory/weak_ptr.h" +#include "chromeos/ash/components/network/hotspot_capabilities_provider.h" #include "chromeos/ash/components/network/hotspot_state_handler.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -20,6 +21,7 @@ namespace hotspot_config { class CrosHotspotConfig : public mojom::CrosHotspotConfig, + public HotspotCapabilitiesProvider::Observer, public HotspotStateHandler::Observer { public: // Constructs an instance of CrosHotspotConfig with default network subsystem @@ -50,12 +52,15 @@ // Constructs an instance of CrosHotspotConfig with specific network subsystem // dependencies. This should only be used in test. - CrosHotspotConfig(HotspotStateHandler* hotspot_state_handler, + CrosHotspotConfig(HotspotCapabilitiesProvider* hotspot_capabilities_provider, + HotspotStateHandler* hotspot_state_handler, HotspotController* hotspot_controller); // HotspotStateHandler::Observer: void OnHotspotStatusChanged() override; + // HotspotCapabilitiesProvider::Observer: void OnHotspotCapabilitiesChanged() override; + HotspotCapabilitiesProvider* hotspot_capabilities_provider_; HotspotStateHandler* hotspot_state_handler_; ash::HotspotController* hotspot_controller_;
diff --git a/chromeos/ash/services/hotspot_config/cros_hotspot_config_unittest.cc b/chromeos/ash/services/hotspot_config/cros_hotspot_config_unittest.cc index 0bad3be..604d243 100644 --- a/chromeos/ash/services/hotspot_config/cros_hotspot_config_unittest.cc +++ b/chromeos/ash/services/hotspot_config/cros_hotspot_config_unittest.cc
@@ -59,7 +59,8 @@ // Use absl::WrapUnique(new CrosHotspotConfig(...)) instead of // std::make_unique<CrosHotspotConfig> to access a private constructor. cros_hotspot_config_ = absl::WrapUnique( - new CrosHotspotConfig(network_handler->hotspot_state_handler(), + new CrosHotspotConfig(network_handler->hotspot_capabilities_provider(), + network_handler->hotspot_state_handler(), network_handler->hotspot_controller())); base::RunLoop().RunUntilIdle(); }
diff --git a/chromeos/ash/services/nearby/public/mojom/BUILD.gn b/chromeos/ash/services/nearby/public/mojom/BUILD.gn index 41f7687..1cf2abc 100644 --- a/chromeos/ash/services/nearby/public/mojom/BUILD.gn +++ b/chromeos/ash/services/nearby/public/mojom/BUILD.gn
@@ -48,6 +48,8 @@ "//url/mojom:url_mojom_gurl", ] + cpp_only = true + cpp_typemaps = [ { types = [
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index f14585f..90f5412 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -2229,6 +2229,9 @@ <message name="IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_TRY_AGAIN" desc="Message for the try again button shown when something goes wrong in the Google Photos page in the wallpaper app."> Try again </message> + <message name="IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUM_SHARED" desc="Secondary text for Google Photos shared albums in the wallpaper app."> + Shared + </message> <message name="IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUMS_TAB" desc="Label for the Albums tab in the Google Photos page in the wallpaper app."> Albums </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUM_SHARED.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUM_SHARED.png.sha1 new file mode 100644 index 0000000..3d26384 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_GOOGLE_PHOTOS_ALBUM_SHARED.png.sha1
@@ -0,0 +1 @@ +5d1183f26d1634c7d292bc2e39a34a314fc95389 \ No newline at end of file
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn index b82d626..475b14a 100644 --- a/chromeos/crosapi/mojom/BUILD.gn +++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -300,6 +300,7 @@ "//components/tab_groups", "//components/webapps/browser:constants", "//ui/base:ui_data_pack", + "//ui/gfx/range", ] }, ]
diff --git a/chromeos/crosapi/mojom/desk_template_mojom_traits.h b/chromeos/crosapi/mojom/desk_template_mojom_traits.h index 32e37f8..4ec2799 100644 --- a/chromeos/crosapi/mojom/desk_template_mojom_traits.h +++ b/chromeos/crosapi/mojom/desk_template_mojom_traits.h
@@ -28,4 +28,4 @@ } // namespace mojo -#endif // CHROMEOS_CROSAPI_MOJOM_DESK_TEMPLATE_MOJOM_TRAITS_H_ \ No newline at end of file +#endif // CHROMEOS_CROSAPI_MOJOM_DESK_TEMPLATE_MOJOM_TRAITS_H_
diff --git a/chromeos/crosapi/mojom/probe_service.mojom b/chromeos/crosapi/mojom/probe_service.mojom index f864bb0..82047e3 100644 --- a/chromeos/crosapi/mojom/probe_service.mojom +++ b/chromeos/crosapi/mojom/probe_service.mojom
@@ -710,12 +710,17 @@ }; // The OS information. +// +// Next ID: 3 +// Next Version: 3 [Stable] struct ProbeOsInfo { // Contents of CrosConfig in /branding/oem-name. string? oem_name@0; // OS Version information. [MinVersion=1] ProbeOsVersion? os_version@1; + // Contents of CrosConfig in /branding/marketing-name. + [MinVersion=2] string? marketing_name@2; }; // System Information.
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt index fb50e3a3..2eaaaa63b 100644 --- a/chromeos/profiles/arm.afdo.newest.txt +++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-arm-none-111-5481.41-1674470533-benchmark-111.0.5557.0-r1-redacted.afdo.xz +chromeos-chrome-arm-none-111-5481.41-1674470533-benchmark-111.0.5559.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 2136203..e24ea0a44 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-111-5481.32-1673869449-benchmark-111.0.5550.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-111-5481.41-1674470533-benchmark-111.0.5558.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 18f1436e..3596c0f2 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-111-5481.41-1674472805-benchmark-111.0.5557.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-111-5481.41-1674472805-benchmark-111.0.5558.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 690ecac..375cb94 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-110-5481.21-1673266524-benchmark-110.0.5481.34-r1.orderfile.xz +chromeos-chrome-orderfile-field-111-5481.32-1673869449-benchmark-111.0.5544.0-r1.orderfile.xz
diff --git a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc index 30a2a366..2897edd 100644 --- a/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc +++ b/chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.cc
@@ -514,6 +514,11 @@ size_button_->SetEnabled( model_->IsEnabled(views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE) || use_zoom_icons); + + // Alpha may be not fully opaque from a previous tablet mode animation. + if (size_button_->GetVisible()) { + size_button_->SetAlpha(255); + } } void FrameCaptionButtonContainerView::UpdateSnapButtons() {
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.cc b/chromeos/ui/frame/caption_buttons/frame_size_button.cc index 20e7d1a5..846b2a9 100644 --- a/chromeos/ui/frame/caption_buttons/frame_size_button.cc +++ b/chromeos/ui/frame/caption_buttons/frame_size_button.cc
@@ -46,8 +46,6 @@ constexpr base::TimeDelta kPieAnimationPressDuration = base::Milliseconds(150); constexpr base::TimeDelta kPieAnimationHoverDuration = base::Milliseconds(500); -constexpr SkColor kPieColor = SkColorSetARGB(0x10, 0x00, 0x00, 0x00); - // Returns true if a mouse drag while in "snap mode" at |location_in_screen| // would hover/press |button| or keep it hovered/pressed. bool HitTestButton(const views::FrameCaptionButton* button, @@ -138,7 +136,8 @@ path.close(); cc::PaintFlags flags; - flags.setColor(kPieColor); + flags.setColor( + GetWidget()->GetColorProvider()->GetColor(ui::kColorSysStateHover)); flags.setAntiAlias(true); flags.setStyle(cc::PaintFlags::kFill_Style); canvas->DrawPath(path, flags); @@ -252,16 +251,14 @@ void FrameSizeButton::ToggleMultitaskMenu() { DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); DCHECK(!chromeos::TabletState::Get()->InTabletMode()); - if (!IsMultitaskMenuShown()) { + if (!multitask_menu_) { RecordMultitaskMenuEntryType(MultitaskMenuEntryType::kAccel); multitask_menu_ = new MultitaskMenu( /*anchor=*/this, GetWidget(), base::BindOnce(&FrameSizeButton::OnMultitaskMenuClosed, weak_factory_.GetWeakPtr())); - multitask_menu_->ShowBubble(); - } else { - multitask_menu_->HideBubble(); } + multitask_menu_->ToggleBubble(); } void FrameSizeButton::OnMultitaskMenuClosed() {
diff --git a/chromeos/ui/frame/caption_buttons/frame_size_button.h b/chromeos/ui/frame/caption_buttons/frame_size_button.h index 36c4f92..fb50f5ea 100644 --- a/chromeos/ui/frame/caption_buttons/frame_size_button.h +++ b/chromeos/ui/frame/caption_buttons/frame_size_button.h
@@ -44,11 +44,15 @@ ~FrameSizeButton() override; // Returns true if the multitask menu is created and shown. + // TODO(sophiewen): Remove this since it's currently only used for testing. bool IsMultitaskMenuShown() const; - // Note that `ShowMultitaskMenu()` recreates the menu if it is already shown, - // while `ToggleMultitaskMenu()` will hide it. + // Shows the MultitaskMenu, run when `this` is hovered or pressed. Recreates + // the menu if it is already shown. void ShowMultitaskMenu(MultitaskMenuEntryType entry_type); + + // Toggles the MultitaskMenu, called only by accelerators. Hides the menu + // if it is already shown. void ToggleMultitaskMenu(); // Clears menu references if it is closed. See `MultitaskMenu`.
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.cc b/chromeos/ui/frame/multitask_menu/multitask_menu.cc index cf5fb1c..ebb7d81d 100644 --- a/chromeos/ui/frame/multitask_menu/multitask_menu.cc +++ b/chromeos/ui/frame/multitask_menu/multitask_menu.cc
@@ -103,6 +103,18 @@ return bubble_widget_ && !bubble_widget_->IsClosed(); } +void MultitaskMenu::ToggleBubble() { + if (!bubble_widget_) { + ShowBubble(); + } else { + // If the menu is toggle closed by the accelerator on a browser window, the + // menu will get closed by deactivation and `HideBubble()` will do nothing + // since `IsClosed()` would be true. For non-browser Ash windows and + // non-accelerator close actions, `HideBubble()` will call `CloseNow()`. + HideBubble(); + } +} + void MultitaskMenu::ShowBubble() { DCHECK(parent_window()); bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(this);
diff --git a/chromeos/ui/frame/multitask_menu/multitask_menu.h b/chromeos/ui/frame/multitask_menu/multitask_menu.h index 686c3d6..f9615d4 100644 --- a/chromeos/ui/frame/multitask_menu/multitask_menu.h +++ b/chromeos/ui/frame/multitask_menu/multitask_menu.h
@@ -42,6 +42,10 @@ // Returns true if the bubble widget is created and shown. bool IsBubbleShown() const; + // Toggles the menu based on its state, i.e. shows the menu if it wasn't + // already shown, hides the menu if it was shown. + void ToggleBubble(); + // Displays the MultitaskMenu. void ShowBubble(); @@ -62,6 +66,7 @@ private: raw_ptr<views::Widget> bubble_widget_ = nullptr; + base::ScopedObservation<views::Widget, views::WidgetObserver> bubble_widget_observer_{this};
diff --git a/components/BUILD.gn b/components/BUILD.gn index 65e6122..b9c31b5 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -644,6 +644,7 @@ deps += [ "//components/safe_browsing/content/renderer:throttles_unittest", "//components/safe_browsing/core/browser:ping_manager_unittest", + "//components/safe_browsing/core/browser:safe_browsing_lookup_mechanism_experimenter_unittest", "//components/safe_browsing/core/browser:safe_browsing_url_checker_unittest", "//components/safe_browsing/core/browser:user_population_unittest", "//components/safe_browsing/core/browser:verdict_cache_manager_unittest",
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h index 6a98664ae..ffe35ec 100644 --- a/components/autofill/content/browser/content_autofill_driver.h +++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/memory/raw_ptr.h" -#include "base/supports_user_data.h" #include "build/build_config.h" #include "components/autofill/content/common/mojom/autofill_agent.mojom.h" #include "components/autofill/content/common/mojom/autofill_driver.mojom.h" @@ -119,11 +118,9 @@ static ContentAutofillDriver* GetForRenderFrameHost( content::RenderFrameHost* render_frame_host); - // Partially constructs the ContentAutofillDriver. The ContentAutofillDriver - // needs an AutofillManager that should be set via set_autofill_manager() (for - // Android Autofill) or set_browser_autofill_manager (for Chromium). - // Outside of unittests, ContentAutofillDriverFactory is instantiated and set - // up by the ContentAutofillDriverFactory. + // Partially constructs the ContentAutofillDriver: afterwards, the caller + // *must* set a non-null AutofillManager with set_autofill_manager(). + // Outside of unittests, this is done by ContentAutofillDriverFactory. ContentAutofillDriver(content::RenderFrameHost* render_frame_host, ContentAutofillRouter* autofill_router); ContentAutofillDriver(const ContentAutofillDriver&) = delete;
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h index 5ffd4ea2..74377a9d 100644 --- a/components/autofill/content/browser/content_autofill_driver_factory.h +++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -49,8 +49,8 @@ // Creates a factory for a WebContents object. // // The `driver_init_hook` is called whenever a driver is constructed, so it - // may configure the driver. In particular, it may create and set the driver's - // AutofillManager. + // may configure the driver. In particular, it must create and set the + // driver's AutofillManager. static void CreateForWebContentsAndDelegate( content::WebContents* contents, AutofillClient* client,
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index bb4e023..1850dfa 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -71,6 +71,7 @@ using blink::WebSelectElement; using blink::WebString; using blink::WebVector; +using blink::mojom::GenericIssueErrorType; namespace autofill { @@ -1441,7 +1442,7 @@ // be used. // TODO(crbug.com/1339277): Use `root` once the feature is launched. label.GetDocument().GetFrame()->AddGenericIssue( - blink::mojom::GenericIssueErrorType::kFormLabelForNameError, + GenericIssueErrorType::kFormLabelForNameError, label.GetDevToolsNodeId()); } } @@ -1463,7 +1464,7 @@ if (IsAutofillableElement(element) && id_count[element.GetIdAttribute()] > 1) { element.GetDocument().GetFrame()->AddGenericIssue( - blink::mojom::GenericIssueErrorType::kFormDuplicateIdForInputError, + GenericIssueErrorType::kFormDuplicateIdForInputError, element.GetDevToolsNodeId()); } } @@ -1490,11 +1491,23 @@ const WebFormControlElement& control_element = control_elements[element_index]; control_element.GetDocument().GetFrame()->AddGenericIssue( - blink::mojom::GenericIssueErrorType::kFormInputWithNoLabelError, + GenericIssueErrorType::kFormInputWithNoLabelError, control_element.GetDevToolsNodeId()); } } +void MaybeEmitInputWithEmptyIdAndNameIssue( + const WebFormControlElement& element) { + static base::NoDestructor<WebString> kName("name"); + + if (element.GetAttribute(*kName).IsEmpty() && + element.GetIdAttribute().IsEmpty()) { + element.GetDocument().GetFrame()->AddGenericIssue( + GenericIssueErrorType::kFormEmptyIdAndNameAttributesForInputError, + element.GetDevToolsNodeId()); + } +} + // Populates the |form|'s // * FormData::fields // * FormData::child_frames @@ -1565,6 +1578,10 @@ extract_mask, &form->fields.back(), &shadow_fields.back()); fields_extracted[i] = true; + if (base::FeatureList::IsEnabled(features::kAutofillEnableDevtoolsIssues)) { + MaybeEmitInputWithEmptyIdAndNameIssue(control_element); + } + if (base::FeatureList::IsEnabled(features::kAutofillAcrossIframes)) { const blink::WebFormElement& ancestor_hint = form_element ? *form_element : blink::WebFormElement(); @@ -2151,7 +2168,9 @@ field->name = field->name_attribute.empty() ? field->id_attribute : field->name_attribute; } - ValidateAutocompleteAttributeForElement(element); + if (base::FeatureList::IsEnabled(features::kAutofillEnableDevtoolsIssues)) { + ValidateAutocompleteAttributeForElement(element); + } if (field->autocomplete_attribute.empty()) { field->autocomplete_attribute = GetAutocompleteAttribute(host); field->parsed_autocomplete = ParseAutocompleteAttribute(
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 2fbee9a..f455b14 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -162,7 +162,7 @@ bool CanShowUsernameSuggestion(const PasswordFormFillData& fill_data, const std::u16string& typed_username) { std::u16string typed_username_lower = base::i18n::ToLower(typed_username); - if (base::StartsWith(base::i18n::ToLower(fill_data.username_field.value), + if (base::StartsWith(base::i18n::ToLower(fill_data.preferred_login.username), typed_username_lower, base::CompareCase::SENSITIVE)) { return true; } @@ -187,10 +187,10 @@ std::u16string* username, std::u16string* password) { // Look for any suitable matches to current field text. - if (DoUsernamesMatch(fill_data.username_field.value, current_username, + if (DoUsernamesMatch(fill_data.preferred_login.username, current_username, exact_username_match)) { - *username = fill_data.username_field.value; - *password = fill_data.password_field.value; + *username = fill_data.preferred_login.username; + *password = fill_data.preferred_login.password; LogMessage(logger, Logger::STRING_USERNAMES_MATCH); } else { // Scan additional logins for a match. @@ -1451,8 +1451,8 @@ } bool username_password_fields_not_set = - form_data.username_field.unique_renderer_id.is_null() && - form_data.password_field.unique_renderer_id.is_null(); + form_data.username_element_renderer_id.is_null() && + form_data.password_element_renderer_id.is_null(); if (username_password_fields_not_set) { // No fields for filling were found during parsing, which means filling // fallback case. So save data for fallback filling. @@ -1464,7 +1464,7 @@ std::tie(username_element, password_element) = FindUsernamePasswordElements(form_data); bool is_single_username_fill = - form_data.password_field.unique_renderer_id.is_null(); + form_data.password_element_renderer_id.is_null(); WebElement main_element = is_single_username_fill ? username_element : password_element; if (main_element.IsNull()) { @@ -1858,7 +1858,7 @@ // data that this value is placeholder. current_username = username_element.Value().Utf16(); } else if (IsElementEditable(username_element)) { - current_username = fill_data.username_field.value; + current_username = fill_data.preferred_login.username; } } @@ -2019,9 +2019,9 @@ PasswordAutofillAgent::FindUsernamePasswordElements( const PasswordFormFillData& form_data) { const FieldRendererId username_renderer_id = - form_data.username_field.unique_renderer_id; + form_data.username_element_renderer_id; const FieldRendererId password_renderer_id = - form_data.password_field.unique_renderer_id; + form_data.password_element_renderer_id; const bool is_username_present = !username_renderer_id.is_null(); const bool is_password_present = !password_renderer_id.is_null();
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 213a3cd..d7c379a1 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -90,6 +90,8 @@ "autofill_experiments.h", "autofill_external_delegate.cc", "autofill_external_delegate.h", + "autofill_feedback_data.cc", + "autofill_feedback_data.h", "autofill_field.cc", "autofill_field.h", "autofill_manager.cc", @@ -98,6 +100,8 @@ "autofill_observer.h", "autofill_profile_import_process.cc", "autofill_profile_import_process.h", + "autofill_profile_migration_strike_database.cc", + "autofill_profile_migration_strike_database.h", "autofill_profile_save_strike_database.cc", "autofill_profile_save_strike_database.h", "autofill_profile_sync_util.cc", @@ -829,9 +833,11 @@ "autofill_download_manager_unittest.cc", "autofill_experiments_unittest.cc", "autofill_external_delegate_unittest.cc", + "autofill_feedback_data_unittest.cc", "autofill_manager_unittest.cc", "autofill_merge_unittest.cc", "autofill_profile_import_process_unittest.cc", + "autofill_profile_migration_strike_database_unittest.cc", "autofill_profile_save_strike_database_unittest.cc", "autofill_profile_sync_util_unittest.cc", "autofill_profile_update_strike_database_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_feedback_data.cc b/components/autofill/core/browser/autofill_feedback_data.cc new file mode 100644 index 0000000..89720d65 --- /dev/null +++ b/components/autofill/core/browser/autofill_feedback_data.cc
@@ -0,0 +1,72 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/autofill_feedback_data.h" + +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/browser_autofill_manager.h" + +namespace autofill::data_logs { +namespace { +base::Value::Dict BuildFieldDataLogs(AutofillField* field) { + base::Value::Dict field_data; + field_data.Set("field_signature", + base::NumberToString(field->GetFieldSignature().value())); + field_data.Set("host_form_signature", + base::NumberToString(field->host_form_signature.value())); + field_data.Set("id_attribute", field->id_attribute); + field_data.Set("parseable_name_attribute", field->name_attribute); + field_data.Set("autocomplete_attribute", field->autocomplete_attribute); + field_data.Set("label_attribute", field->label); + field_data.Set("placeholder_attribute", field->placeholder); + field_data.Set("field_type", field->Type().ToString()); + field_data.Set("heuristic_type", + AutofillType(field->heuristic_type()).ToString()); + field_data.Set("server_type", AutofillType(field->server_type()).ToString()); + field_data.Set("server_type_is_override", + field->server_type_prediction_is_override()); + field_data.Set("html_type", FieldTypeToStringPiece(field->html_type())); + field_data.Set("section", field->section.ToString()); + + field_data.Set("is_empty", field->IsEmpty()); + field_data.Set("is_focusable", field->IsFocusable()); + field_data.Set("is_visible", field->is_visible); + return field_data; +} +} // namespace + +base::Value::Dict FetchAutofillFeedbackData(AutofillManager* manager) { + base::Value::Dict dict; + base::Value::List form_structures; + form_structures.reserve(manager->form_structures().size()); + + for (const auto& [form_id, form] : manager->form_structures()) { + base::Value::Dict form_data; + form_data.Set("form_signature", + base::NumberToString(form->form_signature().value())); + form_data.Set("renderer_id", + base::NumberToString(form->global_id().renderer_id.value())); + form_data.Set("host_frame", form->global_id().frame_token.ToString()); + form_data.Set("source_url", + url::Origin::Create(form->source_url()).Serialize()); + form_data.Set("main_frame_url", form->main_frame_origin().Serialize()); + form_data.Set("id_attribute", form->id_attribute()); + form_data.Set("name_attribute", form->name_attribute()); + + base::Value::List fields; + fields.reserve(form->fields().size()); + for (const auto& field : form->fields()) { + fields.Append(BuildFieldDataLogs(field.get())); + } + + form_data.Set("fields", std::move(fields)); + form_structures.Append(std::move(form_data)); + } + + dict.Set("form_structures", std::move(form_structures)); + + return dict; +} + +} // namespace autofill::data_logs
diff --git a/components/autofill/core/browser/autofill_feedback_data.h b/components/autofill/core/browser/autofill_feedback_data.h new file mode 100644 index 0000000..f077f9a --- /dev/null +++ b/components/autofill/core/browser/autofill_feedback_data.h
@@ -0,0 +1,60 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FEEDBACK_DATA_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FEEDBACK_DATA_H_ + +#include "base/values.h" + +namespace autofill { + +class AutofillManager; + +namespace data_logs { + +// The method extracts autofill metadata contained in the browser autofill +// manager related to form_structures, etc. It bundles these data points into a +// JSON like structure. Consider the example below a complete representation of +// the JSON structure returned by the function. +// { +// "form_structures": [ +// { +// "form_signature": 17674194124817378836, +// "renderer_id": 2, +// "host_frame": "DB42F98A7DF7AC8AFEE6B79AEFC7080B", +// "source_url": "https://www.example.com", +// "main_frame_url": "https://www.example.com", +// "id_attribute": "myId", +// "name_attribute": "myName", +// "fields": [ +// { +// "field_signature": 2666629521, +// "host_form_signature": 17674194124817378836, +// "autocomplete_attribute": "shipping name", +// "id_attribute": "shipping_name", +// "parseable_name_attribute": "shipping_name", +// "label_attribute": "Name", +// "placeholder_attribute": "Name", +// "field_type": "HTML_TYPE_NAME", +// "heuristic_type": "NAME_FULL", +// "server_type": "NAME_FULL", +// "server_type_is_override": false, +// "html_type": "HTML_TYPE_NAME", +// "section": "billing_fname_0_48", +// "is_empty": true, +// "is_focusable": true, +// "is_visible": true +// }, +// ... +// ] +// }, +// ... +// ] +// } +base::Value::Dict FetchAutofillFeedbackData(AutofillManager* manager); + +} // namespace data_logs +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FEEDBACK_DATA_H_
diff --git a/components/autofill/core/browser/autofill_feedback_data_unittest.cc b/components/autofill/core/browser/autofill_feedback_data_unittest.cc new file mode 100644 index 0000000..c24095b8 --- /dev/null +++ b/components/autofill/core/browser/autofill_feedback_data_unittest.cc
@@ -0,0 +1,137 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/autofill_feedback_data.h" + +#include "base/json/json_reader.h" +#include "base/test/task_environment.h" +#include "base/values.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/test_autofill_client.h" +#include "components/autofill/core/browser/test_autofill_driver.h" +#include "components/autofill/core/browser/test_browser_autofill_manager.h" +#include "components/autofill/core/common/form_data.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace autofill { +namespace { +void CreateFeedbackTestFormData(FormData* form) { + form->unique_renderer_id = test::MakeFormRendererId(); + form->name = u"MyForm"; + form->url = GURL("https://myform.com/form.html"); + form->action = GURL("https://myform.com/submit.html"); + form->main_frame_origin = + url::Origin::Create(GURL("https://myform_root.com/form.html")); + + FormFieldData field; + test::CreateTestFormField("First Name on Card", "firstnameoncard", "", "text", + "cc-given-name", &field); + form->fields.push_back(field); + test::CreateTestFormField("Last Name on Card", "lastnameoncard", "", "text", + "cc-family-name", &field); + form->fields.push_back(field); + test::CreateTestFormField("Email", "email", "", "email", &field); + form->fields.push_back(field); +} +} // namespace + +class AutofillFeedbackDataUnitTest : public testing::Test { + protected: + void SetUp() override { + autofill_driver_ = std::make_unique<TestAutofillDriver>(); + browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>( + autofill_driver_.get(), &autofill_client_); + } + + base::test::TaskEnvironment task_environment_; + test::AutofillEnvironment autofill_environment_; + + TestAutofillClient autofill_client_; + std::unique_ptr<TestAutofillDriver> autofill_driver_; + std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_; +}; + +TEST_F(AutofillFeedbackDataUnitTest, CreatesCompleteReport) { + FormData form; + CreateFeedbackTestFormData(&form); + browser_autofill_manager_->OnFormsSeen( + /*updated_forms=*/{form}, + /*removed_forms=*/{}); + + base::Value::Dict autofill_feedback_data = + data_logs::FetchAutofillFeedbackData(browser_autofill_manager_.get()); + + const char kExpectedFeedbackDataJSON[] = R"({ + "form_structures": [ { + "form_signature": "4232380759432074174", + "host_frame": "00000000000000000000000000000000", + "id_attribute": "", + "main_frame_url": "https://myform_root.com", + "name_attribute": "", + "renderer_id": "11", + "source_url": "https://myform.com", + "fields": [ { + "autocomplete_attribute": "cc-given-name", + "field_signature": "3879476562", + "field_type": "HTML_TYPE_CREDIT_CARD_NAME_FIRST", + "heuristic_type": "CREDIT_CARD_NAME_FIRST", + "host_form_signature": "0", + "html_type": "HTML_TYPE_CREDIT_CARD_NAME_FIRST", + "id_attribute": "", + "is_empty": true, + "is_focusable": true, + "is_visible": true, + "label_attribute": "First Name on Card", + "parseable_name_attribute": "", + "placeholder_attribute": "", + "section": "firstnameoncard_0_11", + "server_type": "NO_SERVER_DATA", + "server_type_is_override": false + }, { + "autocomplete_attribute": "cc-family-name", + "field_signature": "3213606822", + "field_type": "HTML_TYPE_CREDIT_CARD_NAME_LAST", + "heuristic_type": "CREDIT_CARD_NAME_LAST", + "host_form_signature": "0", + "html_type": "HTML_TYPE_CREDIT_CARD_NAME_LAST", + "id_attribute": "", + "is_empty": true, + "is_focusable": true, + "is_visible": true, + "label_attribute": "Last Name on Card", + "parseable_name_attribute": "", + "placeholder_attribute": "", + "section": "firstnameoncard_0_11", + "server_type": "NO_SERVER_DATA", + "server_type_is_override": false + }, { + "autocomplete_attribute": "cc-family-name", + "field_signature": "1029417091", + "field_type": "HTML_TYPE_CREDIT_CARD_NAME_LAST", + "heuristic_type": "EMAIL_ADDRESS", + "host_form_signature": "0", + "html_type": "HTML_TYPE_CREDIT_CARD_NAME_LAST", + "id_attribute": "", + "is_empty": true, + "is_focusable": true, + "is_visible": true, + "label_attribute": "Email", + "parseable_name_attribute": "", + "placeholder_attribute": "", + "section": "firstnameoncard_0_11", + "server_type": "NO_SERVER_DATA", + "server_type_is_override": false + } ] + } ] +})"; + + auto expected_data = base::JSONReader::ReadAndReturnValueWithError( + kExpectedFeedbackDataJSON, + base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS); + + ASSERT_TRUE(expected_data.has_value()) << expected_data.error().message; + ASSERT_TRUE(expected_data->is_dict()); + EXPECT_EQ(autofill_feedback_data, expected_data->GetDict()); +} +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc index 564ba79..11497a7 100644 --- a/components/autofill/core/browser/autofill_field.cc +++ b/components/autofill/core/browser/autofill_field.cc
@@ -365,7 +365,7 @@ return IsFillableFieldType(field_type); } -bool AutofillField::ShouldSuppressPromptDueToUnrecognizedAutocompleteAttribute() +bool AutofillField::HasPredictionDespiteUnrecognizedAutocompleteAttribute() const { return html_type_ == HtmlFieldType::kUnrecognized && !IsCreditCardPrediction() &&
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h index 5ae7fcd..d1140d4 100644 --- a/components/autofill/core/browser/autofill_field.h +++ b/components/autofill/core/browser/autofill_field.h
@@ -155,10 +155,14 @@ // field). bool IsFieldFillable() const; - // Returns true if suggestion prompts should not be shown for this field. - // Currently, prompts are suppressed if the autocomplete attribute is - // unrecognized unless it is a credit card form related field. - bool ShouldSuppressPromptDueToUnrecognizedAutocompleteAttribute() const; + // Address Autofill gets disabled by an unrecognized autocomplete attribute. + // If `kAutofillFillAndImportFromMoreFields` is enabled, this changes and the + // server/heuristic predictions overwrite the unrecognized autocomplete + // attribute. Depending on the feature's parameters, Autofill then fills or + // imports from these fields. + // This function returns true if the field's type prediction is only available + // due to the aforementioned feature. + bool HasPredictionDespiteUnrecognizedAutocompleteAttribute() const; void set_initial_value_hash(uint32_t value) { initial_value_hash_ = value; } absl::optional<uint32_t> initial_value_hash() { return initial_value_hash_; }
diff --git a/components/autofill/core/browser/autofill_profile_import_process.cc b/components/autofill/core/browser/autofill_profile_import_process.cc index 60e0f47..4dc29a5 100644 --- a/components/autofill/core/browser/autofill_profile_import_process.cc +++ b/components/autofill/core/browser/autofill_profile_import_process.cc
@@ -435,11 +435,16 @@ AutofillMetrics::LogNewProfileWithIgnoredCountryImportDecision( user_decision_); } + AutofillMetrics::LogNewProfileNumberOfAutocompleteUnrecognizedFields( + import_metadata_.num_autocomplete_unrecognized_fields); + LogUkmMetrics(num_edited_fields); } else if (import_type_ == AutofillProfileImportType::kConfirmableMerge || import_type_ == AutofillProfileImportType::kConfirmableMergeAndSilentUpdate) { AutofillMetrics::LogProfileUpdateImportDecision(user_decision_); + AutofillMetrics::LogProfileUpdateNumberOfAutocompleteUnrecognizedFields( + import_metadata_.num_autocomplete_unrecognized_fields); DCHECK(merge_candidate_.has_value() && import_candidate_.has_value()); // For all update prompts, log the field types and total number of fields
diff --git a/components/autofill/core/browser/autofill_profile_import_process.h b/components/autofill/core/browser/autofill_profile_import_process.h index 7de7c9a..40080c4 100644 --- a/components/autofill/core/browser/autofill_profile_import_process.h +++ b/components/autofill/core/browser/autofill_profile_import_process.h
@@ -87,6 +87,10 @@ bool did_import_from_unrecognized_autocomplete_field = false; // The origin that the form was submitted on. url::Origin origin; + // The number of fields with unrecognized autocomplete attribute that used to + // construct the observed profile. + // TODO(crbug.com/1301721): Remove. + int num_autocomplete_unrecognized_fields = 0; }; // This class holds the state associated with the import of an AutofillProfile
diff --git a/components/autofill/core/browser/autofill_profile_migration_strike_database.cc b/components/autofill/core/browser/autofill_profile_migration_strike_database.cc new file mode 100644 index 0000000..08c8b380 --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_migration_strike_database.cc
@@ -0,0 +1,60 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" + +#include "components/autofill/core/browser/proto/strike_data.pb.h" + +namespace autofill { + +// Limit the number of profiles for which a migration is blocked. +constexpr size_t kMaxStrikeEntities = 100; + +// Once the limit of blocked profiles is reached, delete 30 least recently +// blocked profiles to create a bit of headroom. +constexpr size_t kMaxStrikeEntitiesAfterCleanup = 70; + +// The number of days it takes for strikes to expire. +constexpr int kNumberOfDaysToExpire = 180; + +// The strike limit for suppressing migration prompts. +constexpr int kStrikeLimit = 3; + +AutofillProfileMigrationStrikeDatabase::AutofillProfileMigrationStrikeDatabase( + StrikeDatabaseBase* strike_database) + : StrikeDatabaseIntegratorBase(strike_database) { + RemoveExpiredStrikes(); +} + +AutofillProfileMigrationStrikeDatabase:: + ~AutofillProfileMigrationStrikeDatabase() = default; + +absl::optional<size_t> +AutofillProfileMigrationStrikeDatabase::GetMaximumEntries() const { + return kMaxStrikeEntities; +} + +absl::optional<size_t> +AutofillProfileMigrationStrikeDatabase::GetMaximumEntriesAfterCleanup() const { + return kMaxStrikeEntitiesAfterCleanup; +} + +std::string AutofillProfileMigrationStrikeDatabase::GetProjectPrefix() const { + return "AutofillProfileMigration"; +} + +int AutofillProfileMigrationStrikeDatabase::GetMaxStrikesLimit() const { + return kStrikeLimit; +} + +absl::optional<base::TimeDelta> +AutofillProfileMigrationStrikeDatabase::GetExpiryTimeDelta() const { + return base::Days(kNumberOfDaysToExpire); +} + +bool AutofillProfileMigrationStrikeDatabase::UniqueIdsRequired() const { + return true; +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_migration_strike_database.h b/components/autofill/core/browser/autofill_profile_migration_strike_database.h new file mode 100644 index 0000000..0d92008 --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_migration_strike_database.h
@@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_MIGRATION_STRIKE_DATABASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_MIGRATION_STRIKE_DATABASE_H_ + +#include <stdint.h> +#include <string> + +#include "components/autofill/core/browser/strike_database_base.h" +#include "components/autofill/core/browser/strike_database_integrator_base.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace autofill { + +// Implementation of StrikeDatabaseIntegratorBase for Autofill profile +// migrations. Records the number of times a user declines migrating their +// `kLocalOrSyncable` profile to `kAccount` profile and stops prompting the +// user to do so after reaching a strike limit. +class AutofillProfileMigrationStrikeDatabase + : public StrikeDatabaseIntegratorBase { + public: + explicit AutofillProfileMigrationStrikeDatabase( + StrikeDatabaseBase* strike_database); + ~AutofillProfileMigrationStrikeDatabase() override; + + absl::optional<size_t> GetMaximumEntries() const override; + absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override; + + std::string GetProjectPrefix() const override; + int GetMaxStrikesLimit() const override; + absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override; + bool UniqueIdsRequired() const override; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_MIGRATION_STRIKE_DATABASE_H_
diff --git a/components/autofill/core/browser/autofill_profile_migration_strike_database_unittest.cc b/components/autofill/core/browser/autofill_profile_migration_strike_database_unittest.cc new file mode 100644 index 0000000..159d0cf --- /dev/null +++ b/components/autofill/core/browser/autofill_profile_migration_strike_database_unittest.cc
@@ -0,0 +1,66 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h" + +#include <memory> + +#include "base/files/scoped_temp_dir.h" +#include "base/test/task_environment.h" +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" +#include "components/autofill/core/browser/proto/strike_data.pb.h" +#include "components/leveldb_proto/public/proto_database_provider.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +namespace { + +class AutofillProfileMigrationStrikeDatabaseTest : public ::testing::Test { + public: + AutofillProfileMigrationStrikeDatabaseTest() = default; + + void SetUp() override { + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); + db_provider_ = std::make_unique<leveldb_proto::ProtoDatabaseProvider>( + temp_dir_.GetPath()); + strike_database_service_ = std::make_unique<StrikeDatabase>( + db_provider_.get(), temp_dir_.GetPath()); + strike_database_ = std::make_unique<AutofillProfileMigrationStrikeDatabase>( + strike_database_service_.get()); + } + + void TearDown() override { + strike_database_.reset(); + strike_database_service_.reset(); + db_provider_.reset(); + task_environment_.RunUntilIdle(); + } + + protected: + base::ScopedTempDir temp_dir_; + base::test::TaskEnvironment task_environment_; + std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> db_provider_; + std::unique_ptr<StrikeDatabase> strike_database_service_; + std::unique_ptr<AutofillProfileMigrationStrikeDatabase> strike_database_; +}; + +TEST_F(AutofillProfileMigrationStrikeDatabaseTest, AddAndRemoveStrikes) { + std::string test_guid = "a21f010a-eac1-41fc-aee9-c06bbedfb292"; + strike_database_->AddStrike(test_guid); + EXPECT_EQ(strike_database_->GetStrikes(test_guid), 1); + EXPECT_FALSE(strike_database_->ShouldBlockFeature(test_guid)); + + strike_database_->AddStrikes(2, test_guid); + EXPECT_EQ(strike_database_->GetStrikes(test_guid), 3); + EXPECT_TRUE(strike_database_->ShouldBlockFeature(test_guid)); + + strike_database_->RemoveStrike(test_guid); + EXPECT_EQ(strike_database_->GetStrikes(test_guid), 2); + EXPECT_FALSE(strike_database_->ShouldBlockFeature(test_guid)); +} + +} // namespace + +} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_save_strike_database.cc b/components/autofill/core/browser/autofill_profile_save_strike_database.cc index 0fc9d14..514f5aa 100644 --- a/components/autofill/core/browser/autofill_profile_save_strike_database.cc +++ b/components/autofill/core/browser/autofill_profile_save_strike_database.cc
@@ -5,7 +5,6 @@ #include "components/autofill/core/browser/autofill_profile_save_strike_database.h" #include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/common/autofill_features.h" #include "url/gurl.h" namespace autofill {
diff --git a/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc b/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc index e74a118..33aa7654 100644 --- a/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc +++ b/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc
@@ -29,13 +29,10 @@ void SetUp() override { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - db_provider_ = std::make_unique<leveldb_proto::ProtoDatabaseProvider>( temp_dir_.GetPath()); - strike_database_service_ = std::make_unique<StrikeDatabase>( db_provider_.get(), temp_dir_.GetPath()); - strike_database_ = std::make_unique<AutofillProfileSaveStrikeDatabase>( strike_database_service_.get()); }
diff --git a/components/autofill/core/browser/autofill_profile_update_strike_database.cc b/components/autofill/core/browser/autofill_profile_update_strike_database.cc index d6ea21f..7ca14f5 100644 --- a/components/autofill/core/browser/autofill_profile_update_strike_database.cc +++ b/components/autofill/core/browser/autofill_profile_update_strike_database.cc
@@ -5,11 +5,10 @@ #include "components/autofill/core/browser/autofill_profile_update_strike_database.h" #include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/common/autofill_features.h" namespace autofill { -// Limit the number of profiles for which an update os blocked. +// Limit the number of profiles for which an update is blocked. constexpr size_t kMaxStrikeEntities = 100; // Once the limit of profiles is reached, delete 30 to create a bit of headroom.
diff --git a/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc b/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc index 8a6e9aa6..6c2b62c 100644 --- a/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc +++ b/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc
@@ -23,13 +23,10 @@ void SetUp() override { EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - db_provider_ = std::make_unique<leveldb_proto::ProtoDatabaseProvider>( temp_dir_.GetPath()); - strike_database_service_ = std::make_unique<StrikeDatabase>( db_provider_.get(), temp_dir_.GetPath()); - strike_database_ = std::make_unique<AutofillProfileUpdateStrikeDatabase>( strike_database_service_.get()); }
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc index 12d442d..5820625 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -67,16 +67,9 @@ } int GetObfuscationLength() { - // The kAutofillKeyboardAccessory feature is only available on Android. So for - // other platforms, we'd always use the obfuscation length of 4. This build - // flag also makes sure that tests involving kAutofillKeyboardAccessory - // feature is getting the correct obfuscation length. -#if BUILDFLAG(IS_ANDROID) - return base::FeatureList::IsEnabled(features::kAutofillKeyboardAccessory) ? 2 - : 4; -#else - return 4; -#endif + // The obfuscation length is 2 for the Android keyboard accessory. It is 4 for + // other platforms. + return IsKeyboardAccessoryEnabled() ? 2 : 4; } bool ShouldSplitCardNameAndLastFourDigits() { @@ -492,22 +485,21 @@ // We don't show card linked offers for virtual card options. AdjustVirtualCardSuggestionContent(suggestion, credit_card, type); } else if (card_linked_offer_available) { - // If Keyboard Accessory is not enabled (i.e. Desktop or Clank dropdown), - // populate an offer label. - if (!base::FeatureList::IsEnabled(features::kAutofillKeyboardAccessory)) { - suggestion.labels.push_back( - std::vector<Suggestion::Text>{Suggestion::Text( - l10n_util::GetStringUTF16(IDS_AUTOFILL_OFFERS_CASHBACK))}); - - // Otherwise for Keyboard Accessory, set Suggestion::feature_for_iph and - // change the suggestion icon only if card linked offers are also enabled. - } else if (base::FeatureList::IsEnabled( - features::kAutofillEnableOffersInClankKeyboardAccessory)) { + // For Keyboard Accessory, set Suggestion::feature_for_iph and change the + // suggestion icon only if card linked offers are also enabled. + if (IsKeyboardAccessoryEnabled() && + base::FeatureList::IsEnabled( + features::kAutofillEnableOffersInClankKeyboardAccessory)) { #if BUILDFLAG(IS_ANDROID) suggestion.feature_for_iph = feature_engagement::kIPHKeyboardAccessoryPaymentOfferFeature.name; suggestion.icon = "offerTag"; #endif + } else { + // On Desktop/Android dropdown, populate an offer label. + suggestion.labels.push_back( + std::vector<Suggestion::Text>{Suggestion::Text( + l10n_util::GetStringUTF16(IDS_AUTOFILL_OFFERS_CASHBACK))}); } } @@ -585,17 +577,15 @@ // If the focused field is not a card number field AND the card number is NOT // empty. -#if BUILDFLAG(IS_ANDROID) - // On Android devices, the label is formatted as - // "Product Description/Nickname/Network ••••1234" when the keyboard - // accessory experiment is disabled and as "••1234" when it's enabled. - if (base::FeatureList::IsEnabled(features::kAutofillKeyboardAccessory)) { + // On Android keyboard accessory, the label is formatted as "••1234". + if (IsKeyboardAccessoryEnabled()) { return { Suggestion::Text(credit_card.ObfuscatedNumberWithVisibleLastFourDigits( GetObfuscationLength()))}; } - // E.g. "Product Description/Nickname/Network ••••1234". If card name is too + // On Desktop/Android dropdown, the label is formatted as + // "Product Description/Nickname/Network ••••1234". If the card name is too // long, it will be truncated from the tail. if (ShouldSplitCardNameAndLastFourDigits()) { return { @@ -605,29 +595,20 @@ Suggestion::Text(credit_card.ObfuscatedNumberWithVisibleLastFourDigits( GetObfuscationLength()))}; } - // E.g. "Nickname/Network ••••1234". - return {Suggestion::Text( - credit_card.CardIdentifierStringForAutofillDisplay(nickname))}; -#elif BUILDFLAG(IS_IOS) - // E.g. "••••1234"". +#if BUILDFLAG(IS_IOS) + // On iOS, the label is formatted as "••••1234". return { Suggestion::Text(credit_card.ObfuscatedNumberWithVisibleLastFourDigits( GetObfuscationLength()))}; - +#elif BUILDFLAG(IS_ANDROID) + // On Android dropdown, the label is formatted as + // "Nickname/Network ••••1234". + return {Suggestion::Text( + credit_card.CardIdentifierStringForAutofillDisplay(nickname))}; #else - // E.g. "Product Description/Nickname/Network ••••1234". If card name is too - // long, it will be truncated from the tail. - if (ShouldSplitCardNameAndLastFourDigits()) { - return { - Suggestion::Text(credit_card.CardNameForAutofillDisplay(nickname), - Suggestion::Text::IsPrimary(false), - Suggestion::Text::ShouldTruncate(true)), - Suggestion::Text(credit_card.ObfuscatedNumberWithVisibleLastFourDigits( - GetObfuscationLength()))}; - } - - // E.g. "Product Description/Nickname/Network ••••1234, expires on 01/25". + // On Desktop, the label is formatted as + // "Product Description/Nickname/Network ••••1234, expires on 01/25". return {Suggestion::Text( credit_card.CardIdentifierStringAndDescriptiveExpiration(app_locale))}; #endif
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index 087402e9..cbef7dc4 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -2209,6 +2209,19 @@ continue; } + // If `kAutofillFillAndImportFromMoreFields` is enabled, predictions are + // generated for autocomplete=unrecognized fields. The fields are only + // filled when the `kAutofillFillAutocompleteUnrecognized` parameter is + // enabled. + if (form_structure->field(i) + ->HasPredictionDespiteUnrecognizedAutocompleteAttribute() && + !features::kAutofillFillAutocompleteUnrecognized.Get()) { + LOG_AF(buffer) + << Tr{} + << "Skipped: kAutofillFillAutoccompleteUnrecognized not enabled"; + continue; + } + // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime, // which may happen with refills. if (autofill_field->global_id() != result.fields[i].global_id()) { @@ -3078,7 +3091,7 @@ // attribute, unless those are credit card fields. if (context->focused_field && context->focused_field - ->ShouldSuppressPromptDueToUnrecognizedAutocompleteAttribute()) { + ->HasPredictionDespiteUnrecognizedAutocompleteAttribute()) { context->suppress_reason = SuppressReason::kAutocompleteUnrecognized; suggestions->clear(); return; @@ -3340,9 +3353,10 @@ OnSingleFieldSuggestionSelected(value, frontend_id); } -void BrowserAutofillManager::SetSuggestionOriginMetricState( - AutofillSuggestionMethod state) { - autofill_suggestion_method_ = state; +void BrowserAutofillManager::SetAutofillSuggestionMethod( + AutofillSuggestionMethod method) { + autofill_suggestion_method_ = method; + credit_card_form_event_logger_->set_autofill_suggestion_method(method); } void BrowserAutofillManager::SetShouldSuppressKeyboard(bool suppress) {
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h index 2d0672d..3294e62 100644 --- a/components/autofill/core/browser/browser_autofill_manager.h +++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -313,7 +313,7 @@ // Sets where the accepted autofill suggestion came from: touch to fill, // keyboard accessory, etc. - virtual void SetSuggestionOriginMetricState(AutofillSuggestionMethod state); + virtual void SetAutofillSuggestionMethod(AutofillSuggestionMethod state); // Forwards call to the same-named `AutofillDriver` function. virtual void SetShouldSuppressKeyboard(bool suppress);
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc index 6879264..b2cc9d9 100644 --- a/components/autofill/core/browser/form_data_importer.cc +++ b/components/autofill/core/browser/form_data_importer.cc
@@ -465,6 +465,15 @@ if (!field->IsFieldFillable() || value.empty()) continue; + // When `kAutofillImportFromAutoccompleteUnrecognized` is enabled, Autofill + // imports from fields despite an unrecognized autocomplete attribute. + if (field->HasPredictionDespiteUnrecognizedAutocompleteAttribute()) { + if (!features::kAutofillImportFromAutoccompleteUnrecognized.Get()) { + continue; + } + import_metadata.num_autocomplete_unrecognized_fields++; + } + AutofillType field_type = field->Type(); // Credit card fields are handled by ExtractCreditCard().
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h index b070305f..c6630eaa 100644 --- a/components/autofill/core/browser/form_data_importer.h +++ b/components/autofill/core/browser/form_data_importer.h
@@ -130,6 +130,10 @@ credit_card_import_type_ = credit_card_import_type; } + IBANSaveManager* iban_save_manager_for_testing() { + return iban_save_manager_.get(); + } + protected: void set_credit_card_save_manager_for_testing( std::unique_ptr<CreditCardSaveManager> credit_card_save_manager) {
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index f44d6e90..a122741f 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -1158,12 +1158,12 @@ // launched. if (field->is_autofilled) { ++num_of_accepted_autofilled_fields; - if (field->ShouldSuppressPromptDueToUnrecognizedAutocompleteAttribute()) { + if (field->HasPredictionDespiteUnrecognizedAutocompleteAttribute()) { ++num_of_accepted_autofilled_fields_with_autocomplete_unrecognized; } } else if (field->previously_autofilled()) { ++num_of_corrected_autofilled_fields; - if (field->ShouldSuppressPromptDueToUnrecognizedAutocompleteAttribute()) { + if (field->HasPredictionDespiteUnrecognizedAutocompleteAttribute()) { ++num_of_corrected_autofilled_fields_with_autocomplete_unrecognized; } }
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc index 132deb7..46a45412 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -3024,6 +3024,13 @@ "Autofill.ProfileImport.NewProfileWithIgnoredCountryDecision", decision); } +void AutofillMetrics::LogNewProfileNumberOfAutocompleteUnrecognizedFields( + int count) { + base::UmaHistogramExactLinear( + "Autofill.ProfileImport.NewProfileNumberOfAutocompleteUnrecognizedFields", + count, /*exclusive_max=*/20); +} + void AutofillMetrics::LogNewProfileEditedType(ServerFieldType edited_type) { base::UmaHistogramEnumeration( "Autofill.ProfileImport.NewProfileEditedType", @@ -3050,6 +3057,14 @@ decision); } +void AutofillMetrics::LogProfileUpdateNumberOfAutocompleteUnrecognizedFields( + int count) { + base::UmaHistogramExactLinear( + "Autofill.ProfileImport." + "UpdateProfileNumberOfAutocompleteUnrecognizedFields", + count, /*exclusive_max=*/20); +} + void AutofillMetrics::LogProfileUpdateAffectedType( ServerFieldType affected_type, AutofillClient::SaveAddressProfileOfferUserDecision decision) {
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.h b/components/autofill/core/browser/metrics/autofill_metrics.h index 8851a956..848355b 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.h +++ b/components/autofill/core/browser/metrics/autofill_metrics.h
@@ -1372,6 +1372,10 @@ static void LogNewProfileWithIgnoredCountryImportDecision( AutofillClient::SaveAddressProfileOfferUserDecision decision); + // Logs the number of fields with an unrecognized autocomplete attributed that + // were considered for the import due to AutofillFillAndImportFromMoreFields. + static void LogNewProfileNumberOfAutocompleteUnrecognizedFields(int count); + // Logs that a specific type was edited in a save prompt. static void LogNewProfileEditedType(ServerFieldType edited_type); @@ -1387,6 +1391,10 @@ static void LogProfileUpdateWithIgnoredCountryImportDecision( AutofillClient::SaveAddressProfileOfferUserDecision decision); + // Logs the number of fields with an unrecognized autocomplete attributed that + // were considered for the update due to AutofillFillAndImportFromMoreFields. + static void LogProfileUpdateNumberOfAutocompleteUnrecognizedFields(int count); + // Logs that a specific type changed in a profile update that received the // user |decision|. Note that additional manual edits in the update prompt are // not accounted for in this metric.
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc index 1fb5af52..3849451 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
@@ -7,6 +7,7 @@ #include "components/autofill/core/browser/autofill_form_test_utils.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/payments/credit_card_access_manager.h" +#include "components/autofill/core/browser/touch_to_fill_delegate_impl.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -77,6 +78,12 @@ external_delegate_ = external_delegate.get(); autofill_manager().SetExternalDelegateForTest(std::move(external_delegate)); + auto touch_to_fill_delegate_uptr = + std::make_unique<TouchToFillDelegateImpl>(&autofill_manager()); + touch_to_fill_delgate_ = touch_to_fill_delegate_uptr.get(); + autofill_manager().SetTouchToFillDelegateImplForTest( + std::move(touch_to_fill_delegate_uptr)); + #if !BUILDFLAG(IS_IOS) autofill_manager() .GetCreditCardAccessManager()
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h index d456e14d..f8bfe37 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
@@ -186,6 +186,7 @@ syncer::TestSyncService sync_service_; std::unique_ptr<TestAutofillDriver> autofill_driver_; raw_ptr<AutofillExternalDelegate> external_delegate_; + raw_ptr<TouchToFillDelegateImpl> touch_to_fill_delgate_; private: void CreateTestAutofillProfiles();
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index c0e2a37..0c2f3a69 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/autofill/core/browser/metrics/autofill_metrics.h" +#include "base/check.h" #include <stddef.h> @@ -746,80 +747,119 @@ BucketsAre(test_case.credit_card_buckets)); } -struct SuggestionOriginPerfectFillingTestCase { - std::string description; +struct TouchToFillForCreditCardsTestCase { std::vector<Field> fields; - bool expected_metric_value; + std::vector<bool> fields_is_autofilled_values; + bool is_all_autofilled; + bool is_all_accepted; }; -class SuggestionOriginPerfectFillingMetricsTest +class TouchToFillForCreditCardsTest : public AutofillMetricsTest, - public ::testing::WithParamInterface< - SuggestionOriginPerfectFillingTestCase> { + public ::testing::WithParamInterface<TouchToFillForCreditCardsTestCase> { public: - std::vector<test::FieldDescription> GetFields(std::vector<Field> fields) { - std::vector<test::FieldDescription> fields_to_return; + std::vector<FormFieldData> GetFields(std::vector<Field> fields) { + std::vector<FormFieldData> fields_to_return; + fields_to_return.reserve(fields.size()); for (const auto& field : fields) { - test::FieldDescription f; - if (field.value) { - f.value = field.value; - } else if (field.field_type == CREDIT_CARD_NAME_FULL) { - f.value = u"Elvis Aaron Presley"; + if (field.field_type == CREDIT_CARD_NAME_FULL) { + fields_to_return.push_back( + CreateField("Name on card", "cardName", "", "text")); } else if (field.field_type == CREDIT_CARD_NUMBER) { - f.value = u"01230123012399"; + fields_to_return.push_back( + CreateField("Credit card number", "cardNumber", "", "text")); + } else if (field.field_type == CREDIT_CARD_EXP_MONTH) { + fields_to_return.push_back( + CreateField("Expiration date", "cc_exp", "", "text")); + } else if (field.field_type == CREDIT_CARD_VERIFICATION_CODE) { + fields_to_return.push_back(CreateField("CVC", "CVC", "", "text")); } else { NOTREACHED(); } - f.role = field.field_type; - f.is_autofilled = field.is_autofilled; - fields_to_return.push_back(f); } return fields_to_return; } + + void SetFieldsAutofilledValues(FormData& form, + std::vector<bool>& fields_is_autofilled_values, + std::vector<Field>& server_field_types) { + DCHECK(form.fields.size() == fields_is_autofilled_values.size()); + DCHECK(form.fields.size() == server_field_types.size()); + for (size_t i = 0; i < fields_is_autofilled_values.size(); i++) { + form.fields[i].is_autofilled = fields_is_autofilled_values[i]; + CreditCard testCard = test::GetCreditCard(); + form.fields[i].value = + server_field_types[i].field_type != CREDIT_CARD_VERIFICATION_CODE + ? testCard.GetRawInfo(server_field_types[i].field_type) + : u"123"; + } + } }; -TEST_P(SuggestionOriginPerfectFillingMetricsTest, - PerfectFilling_TouchToFill_CreditCards) { - SuggestionOriginPerfectFillingTestCase test_case = GetParam(); - std::vector<Field> fields{{CREDIT_CARD_NAME_FULL}, {CREDIT_CARD_NUMBER}}; - FormData form = - test::GetFormData({.description_for_logging = test_case.description, - .fields = GetFields(test_case.fields), - .unique_renderer_id = test::MakeFormRendererId(), - .main_frame_origin = url::Origin::Create( - autofill_client_->form_origin())}); +TEST_P(TouchToFillForCreditCardsTest, + AllAutofilledAndAccepted_TouchToFill_CreditCards) { + RecreateCreditCards(true, false, false, false); + TouchToFillForCreditCardsTestCase test_case = GetParam(); + FormData form = CreateForm(GetFields(test_case.fields)); - std::vector<ServerFieldType> field_types; - for (const auto& f : test_case.fields) { - field_types.push_back(f.field_type); - } - - autofill_manager().AddSeenForm(form, field_types); + SeeForm(form); + autofill_manager().OnAskForValuesToFillTest(form, form.fields[0], {}, + AutoselectFirstSuggestion(false), + FormElementWasClicked(true)); base::HistogramTester histogram_tester; - autofill_manager().SetSuggestionOriginMetricState( - AutofillSuggestionMethod::KTouchToFillCreditCard); + // Simulate user selection in the payments bottom sheet + touch_to_fill_delgate_->SuggestionSelected(kTestLocalCardId); + // Simulate that fields were autofilled + SetFieldsAutofilledValues(form, test_case.fields_is_autofilled_values, + test_case.fields); + // Simulate user made change to autofilled field + if (!test_case.is_all_accepted) { + SimulateUserChangedTextField(form, form.fields[0]); + } + SubmitForm(form); + ResetDriverToCommitMetrics(); EXPECT_EQ(histogram_tester.GetBucketCount( "Autofill.TouchToFill.CreditCard.PerfectFilling", - test_case.expected_metric_value), + test_case.is_all_autofilled && test_case.is_all_accepted), + 1); + EXPECT_EQ(histogram_tester.GetBucketCount( + "Autofill.FillingCorrectnessByMethod.CreditCard.TouchToFill", + test_case.is_all_accepted), 1); } INSTANTIATE_TEST_SUITE_P( AutofillMetricsTest, - SuggestionOriginPerfectFillingMetricsTest, + TouchToFillForCreditCardsTest, testing::Values( - // Test that we log the perfect filling metric correctly for an address - // form in which every field is autofilled. - SuggestionOriginPerfectFillingTestCase{ - "PerfectFillingForCreditCardForm_AutofilledFromTTF", - {{CREDIT_CARD_NAME_FULL}, {CREDIT_CARD_NUMBER}}, - true}, - SuggestionOriginPerfectFillingTestCase{ - "PerfectFillingForCreditCardForm_NotAllAutofilledFromTTF", - {{CREDIT_CARD_NAME_FULL}, {CREDIT_CARD_NUMBER, false}}, - false})); + // All autofilled and nothing edited manually + TouchToFillForCreditCardsTestCase{ + {{CREDIT_CARD_NAME_FULL}, + {CREDIT_CARD_NUMBER}, + {CREDIT_CARD_EXP_MONTH}}, + /*fields_is_autofilled_values=*/{true, true, true}, + /*is_all_autofilled=*/true, + /*is_all_accepted=*/true}, + // Not all autofilled and nothing edited manually + TouchToFillForCreditCardsTestCase{ + {{CREDIT_CARD_NAME_FULL}, + {CREDIT_CARD_NUMBER}, + {CREDIT_CARD_EXP_MONTH}, + {CREDIT_CARD_VERIFICATION_CODE}}, + /*fields_is_autofilled_values=*/{true, true, true, false}, + /*is_all_autofilled=*/false, + /*is_all_accepted=*/true}, + // Not all autofilled and something edited manually + TouchToFillForCreditCardsTestCase{ + {{CREDIT_CARD_NAME_FULL}, + {CREDIT_CARD_NUMBER}, + {CREDIT_CARD_EXP_MONTH}, + {CREDIT_CARD_VERIFICATION_CODE}}, + /*fields_is_autofilled_values=*/{true, true, true, false}, + /*is_all_autofilled=*/false, + /*is_all_accepted=*/false})); // Test the emission of collisions between NUMERIC_QUANTITY and server // predictions as well as the potential false positives.
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_utils.cc b/components/autofill/core/browser/metrics/autofill_metrics_utils.cc index 510bbac..767a4da 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_utils.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_utils.cc
@@ -81,4 +81,16 @@ return FieldFillingStatus::kManuallyFilledToDifferentType; } +std::string GetMetricsSuffixByAutofillMethod(AutofillSuggestionMethod method) { + switch (method) { + case AutofillSuggestionMethod::KTouchToFillCreditCard: + return "TouchToFill"; + case AutofillSuggestionMethod::kUnknown: + NOTREACHED(); + break; + } + NOTREACHED(); + return ""; +} + } // namespace autofill
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_utils.h b/components/autofill/core/browser/metrics/autofill_metrics_utils.h index 6e4ddde2..0fd1744 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_utils.h +++ b/components/autofill/core/browser/metrics/autofill_metrics_utils.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_AUTOFILL_METRICS_UTILS_H_ #include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/metrics/autofill_metrics.h" namespace autofill { @@ -51,6 +52,11 @@ AutofillMetrics::FieldFillingStatus GetFieldFillingStatus( const AutofillField& field); +// Returns the suffix for metrics histogram name depending on the autofill +// suggestions method used to fill in the value and the form type. +// E. g. "CreditCard.TouchToFill". +std::string GetMetricsSuffixByAutofillMethod(AutofillSuggestionMethod method); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_AUTOFILL_METRICS_UTILS_H_
diff --git a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc index bbfe341..7aa4fba 100644 --- a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc +++ b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.cc
@@ -11,7 +11,9 @@ #include "base/strings/strcat.h" #include "base/time/time.h" #include "components/autofill/core/browser/form_parsing/form_field.h" +#include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/logging/log_manager.h" +#include "components/autofill/core/browser/metrics/autofill_metrics_utils.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/autofill_internals/logging_scope.h" @@ -275,7 +277,6 @@ LOG_AF(funnel_rows) << Tr{} << "Form Type: " << form_type_name_; LOG_AF(key_metrics_rows) << Tr{} << "Form Type: " << form_type_name_; - UmaHistogramBoolean("Autofill.Funnel.ParsedAsType." + form_type_name_, has_parsed_form_); // Log chronological funnel. @@ -343,6 +344,8 @@ !has_logged_edited_autofilled_field_); LOG_AF(key_metrics_rows) << Tr{} << "FillingCorrectness" << !has_logged_edited_autofilled_field_; + LogFillingCorrectnessByFillingMethod(autofill_suggestion_method_, + form_type_name_); } // Whether a submitted form was filled. UmaHistogramBoolean( @@ -487,4 +490,19 @@ flow_id_ = client_->GetCurrentFormInteractionsFlowId(); } +void FormEventLoggerBase::LogFillingCorrectnessByFillingMethod( + AutofillSuggestionMethod method, + const std::string& form_type) { + if (method == AutofillSuggestionMethod::kUnknown) { + return; + } + + // Log the correctness metric by autofill suggestion method (touch to fill, + // keyboard accessory, etc) and the form type (credit card, address, etc.) + const std::string method_name = GetMetricsSuffixByAutofillMethod(method); + base::UmaHistogramBoolean( + "Autofill.FillingCorrectnessByMethod." + form_type + "." + method_name, + !has_logged_edited_autofilled_field_); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h index 14d7c8e..4d9059d 100644 --- a/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h +++ b/components/autofill/core/browser/metrics/form_events/form_event_logger_base.h
@@ -38,6 +38,10 @@ local_record_type_count_ = local_record_type_count; } + inline void set_autofill_suggestion_method(AutofillSuggestionMethod method) { + autofill_suggestion_method_ = method; + } + void OnDidInteractWithAutofillableForm(const FormStructure& form, AutofillSyncSigninState sync_state); @@ -135,6 +139,12 @@ void UpdateFlowId(); + // Records UMA metric: correctness filling in relation to the autofill + // suggestion method that was used (touch to fill for credit cards, keyboard + // accessory, etc.) and the form type (credit card, address, etc.) + void LogFillingCorrectnessByFillingMethod(AutofillSuggestionMethod method, + const std::string& form_type); + // Constructor parameters. std::string form_type_name_; bool is_in_any_main_frame_; @@ -158,6 +168,8 @@ false; AblationGroup ablation_group_ = AblationGroup::kDefault; AblationGroup conditional_ablation_group_ = AblationGroup::kDefault; + AutofillSuggestionMethod autofill_suggestion_method_ = + AutofillSuggestionMethod::kUnknown; absl::optional<base::TimeDelta> time_from_interaction_to_submission_; // The last field that was polled for suggestions.
diff --git a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc index 214b7f9..6fea090 100644 --- a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc +++ b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
@@ -30,22 +30,37 @@ namespace autofill { -AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( - bool upload, +// static +std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> +AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( AutofillClient::SaveCreditCardOptions options, const CreditCard& card, + AutofillClient::LocalSaveCardPromptCallback callback) { + return base::WrapUnique(new AutofillSaveCardInfoBarDelegateMobile( + options, card, std::move(callback), LegalMessageLines(), AccountInfo())); +} + +// static +std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> +AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( + AutofillClient::SaveCreditCardOptions options, + const CreditCard& card, + AutofillClient::UploadSaveCardPromptCallback callback, const LegalMessageLines& legal_message_lines, - AutofillClient::UploadSaveCardPromptCallback - upload_save_card_prompt_callback, - AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback, + const AccountInfo& account_info) { + return base::WrapUnique(new AutofillSaveCardInfoBarDelegateMobile( + options, card, std::move(callback), legal_message_lines, account_info)); +} + +AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( + AutofillClient::SaveCreditCardOptions options, + const CreditCard& card, + absl::variant<AutofillClient::LocalSaveCardPromptCallback, + AutofillClient::UploadSaveCardPromptCallback> callback, + const LegalMessageLines& legal_message_lines, const AccountInfo& displayed_target_account) - : ConfirmInfoBarDelegate(), - upload_(upload), - options_(options), - upload_save_card_prompt_callback_( - std::move(upload_save_card_prompt_callback)), - local_save_card_prompt_callback_( - std::move(local_save_card_prompt_callback)), + : options_(options), + callback_(std::move(callback)), had_user_interaction_(false), issuer_icon_id_(CreditCard::IconResourceId(card.network())), card_label_(card.CardIdentifierStringForAutofillDisplay()), @@ -58,15 +73,12 @@ displayed_target_account_email_( base::UTF8ToUTF16((displayed_target_account.email))), displayed_target_account_avatar_(displayed_target_account.account_image) { - DCHECK_EQ(upload, !upload_save_card_prompt_callback_.is_null()); - DCHECK_EQ(upload, local_save_card_prompt_callback_.is_null()); - if (!upload) { + if (!is_for_upload()) { DCHECK(displayed_target_account_email_.empty()); DCHECK(displayed_target_account_avatar_.IsEmpty()); } - AutofillMetrics::LogCreditCardInfoBarMetric(AutofillMetrics::INFOBAR_SHOWN, - upload_, options_); + is_for_upload(), options_); } AutofillSaveCardInfoBarDelegateMobile:: @@ -76,7 +88,7 @@ AutofillClient::SaveCardOfferUserDecision::kIgnored, /*user_provided_details=*/{}); LogSaveCreditCardPromptResult( - autofill_metrics::SaveCreditCardPromptResult::kIgnored, upload_, + autofill_metrics::SaveCreditCardPromptResult::kIgnored, is_for_upload(), options_); LogUserAction(AutofillMetrics::INFOBAR_IGNORED); } @@ -98,7 +110,7 @@ bool AutofillSaveCardInfoBarDelegateMobile::IsGooglePayBrandingEnabled() const { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - return upload_; + return is_for_upload(); #else return false; #endif @@ -123,8 +135,8 @@ return l10n_util::GetStringUTF16( IsGooglePayBrandingEnabled() ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V3 - : upload_ ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD - : IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_LOCAL); + : is_for_upload() ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD + : IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_LOCAL); } infobars::InfoBarDelegate::InfoBarIdentifier @@ -158,7 +170,8 @@ /*user_provided_details=*/{}); LogUserAction(AutofillMetrics::INFOBAR_DENIED); LogSaveCreditCardPromptResult( - autofill_metrics::SaveCreditCardPromptResult::kDenied, upload_, options_); + autofill_metrics::SaveCreditCardPromptResult::kDenied, is_for_upload(), + options_); } bool AutofillSaveCardInfoBarDelegateMobile::Cancel() { @@ -167,7 +180,8 @@ /*user_provided_details=*/{}); LogUserAction(AutofillMetrics::INFOBAR_DENIED); LogSaveCreditCardPromptResult( - autofill_metrics::SaveCreditCardPromptResult::kDenied, upload_, options_); + autofill_metrics::SaveCreditCardPromptResult::kDenied, is_for_upload(), + options_); return true; } @@ -189,8 +203,8 @@ if (button == BUTTON_CANCEL) { return l10n_util::GetStringUTF16( - upload_ ? IDS_AUTOFILL_NO_THANKS_MOBILE_UPLOAD_SAVE - : IDS_AUTOFILL_NO_THANKS_MOBILE_LOCAL_SAVE); + is_for_upload() ? IDS_AUTOFILL_NO_THANKS_MOBILE_UPLOAD_SAVE + : IDS_AUTOFILL_NO_THANKS_MOBILE_LOCAL_SAVE); } NOTREACHED() << "Unsupported button label requested."; @@ -201,11 +215,12 @@ // Acceptance can be logged immediately if: // 1. the user is accepting local save. // 2. or when we don't need more info in order to upload. - if (!upload_ || (!options_.should_request_name_from_user && - !options_.should_request_expiration_date_from_user)) { + if (!is_for_upload() || + (!options_.should_request_name_from_user && + !options_.should_request_expiration_date_from_user)) { LogSaveCreditCardPromptResult( - autofill_metrics::SaveCreditCardPromptResult::kAccepted, upload_, - options_); + autofill_metrics::SaveCreditCardPromptResult::kAccepted, + is_for_upload(), options_); } RunSaveCardPromptCallback( AutofillClient::SaveCardOfferUserDecision::kAccepted, @@ -234,11 +249,13 @@ void AutofillSaveCardInfoBarDelegateMobile::RunSaveCardPromptCallback( AutofillClient::SaveCardOfferUserDecision user_decision, AutofillClient::UserProvidedCardDetails user_provided_details) { - if (upload_) { - std::move(upload_save_card_prompt_callback_) + if (is_for_upload()) { + absl::get<AutofillClient::UploadSaveCardPromptCallback>( + std::move(callback_)) .Run(user_decision, user_provided_details); } else { - std::move(local_save_card_prompt_callback_).Run(user_decision); + absl::get<AutofillClient::LocalSaveCardPromptCallback>(std::move(callback_)) + .Run(user_decision); } } @@ -246,7 +263,8 @@ AutofillMetrics::InfoBarMetric user_action) { DCHECK(!had_user_interaction_); - AutofillMetrics::LogCreditCardInfoBarMetric(user_action, upload_, options_); + AutofillMetrics::LogCreditCardInfoBarMetric(user_action, is_for_upload(), + options_); had_user_interaction_ = true; }
diff --git a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h index fa6fba80..208489b5 100644 --- a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h +++ b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
@@ -15,9 +15,11 @@ #include "components/autofill/core/browser/metrics/autofill_metrics.h" #include "components/autofill/core/browser/payments/legal_message_line.h" #include "components/infobars/core/confirm_infobar_delegate.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "ui/gfx/image/image.h" struct AccountInfo; +class MockAutofillSaveCardInfoBarDelegateMobile; namespace autofill { @@ -27,25 +29,17 @@ // card information gathered from a form submission. Only used on mobile. class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate { public: - // |upload| must be true iff the infobar should offer to save the card in the - // cloud, as opposed to saving locally. Only one of - // |upload_save_card_prompt_callback| and |local_save_card_prompt_callback| - // will be executed. - // If |upload| is true, |displayed_target_account| should be the account to - // which the card will be saved. If |upload| is false, it must be empty. - // TODO(crbug.com/1277904): Split into 2 static constructors (local/cloud), - // each with the minimum set of required parameters. Also consider merging - // the 2 callbacks into one. - AutofillSaveCardInfoBarDelegateMobile( - bool upload, - AutofillClient::SaveCreditCardOptions options, - const CreditCard& card, - const LegalMessageLines& legal_message_lines, - AutofillClient::UploadSaveCardPromptCallback - upload_save_card_prompt_callback, - AutofillClient::LocalSaveCardPromptCallback - local_save_card_prompt_callback, - const AccountInfo& displayed_target_account); + static std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> + CreateForLocalSave(AutofillClient::SaveCreditCardOptions options, + const CreditCard& card, + AutofillClient::LocalSaveCardPromptCallback callback); + + static std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> + CreateForUploadSave(AutofillClient::SaveCreditCardOptions options, + const CreditCard& card, + AutofillClient::UploadSaveCardPromptCallback callback, + const LegalMessageLines& legal_message_lines, + const AccountInfo& displayed_target_account); AutofillSaveCardInfoBarDelegateMobile( const AutofillSaveCardInfoBarDelegateMobile&) = delete; @@ -59,7 +53,10 @@ static AutofillSaveCardInfoBarDelegateMobile* FromInfobarDelegate( infobars::InfoBarDelegate* delegate); - bool upload() const { return upload_; } + bool is_for_upload() const { + return absl::holds_alternative< + AutofillClient::UploadSaveCardPromptCallback>(callback_); + } int issuer_icon_id() const { return issuer_icon_id_; } const std::u16string& card_label() const { return card_label_; } const std::u16string& card_sub_label() const { return card_sub_label_; } @@ -114,6 +111,18 @@ #endif // BUILDFLAG(IS_IOS) private: + friend class ::MockAutofillSaveCardInfoBarDelegateMobile; + + // If an `callback` is an upload callback, `displayed_target_account` should + // be the account to which the card will be saved. + AutofillSaveCardInfoBarDelegateMobile( + AutofillClient::SaveCreditCardOptions options, + const CreditCard& card, + absl::variant<AutofillClient::LocalSaveCardPromptCallback, + AutofillClient::UploadSaveCardPromptCallback> callback, + const LegalMessageLines& legal_message_lines, + const AccountInfo& displayed_target_account); + // Runs the appropriate local or upload save callback with the given // |user_decision|, using the |user_provided_details|. If // |user_provided_details| is empty then the current Card values will be used. @@ -126,22 +135,16 @@ void LogUserAction(AutofillMetrics::InfoBarMetric user_action); - // Whether the action is an upload or a local save. - bool upload_; - // If the cardholder name is missing, request the name from the user before // saving the card. If the expiration date is missing, request the missing // data from the user before saving the card. AutofillClient::SaveCreditCardOptions options_; // The callback to run once the user makes a decision with respect to the - // credit card upload offer-to-save prompt (if |upload_| is true). - AutofillClient::UploadSaveCardPromptCallback - upload_save_card_prompt_callback_; - - // The callback to run once the user makes a decision with respect to the - // local credit card offer-to-save prompt (if |upload_| is false). - AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback_; + // credit card offer-to-save prompt. + absl::variant<AutofillClient::LocalSaveCardPromptCallback, + AutofillClient::UploadSaveCardPromptCallback> + callback_; // Did the user ever explicitly accept or dismiss this infobar? bool had_user_interaction_;
diff --git a/components/autofill/core/browser/payments/iban_save_manager.cc b/components/autofill/core/browser/payments/iban_save_manager.cc index 267bb11..2afac78 100644 --- a/components/autofill/core/browser/payments/iban_save_manager.cc +++ b/components/autofill/core/browser/payments/iban_save_manager.cc
@@ -26,6 +26,10 @@ base::UTF16ToUTF8(iban_import_candidate.value())); iban_save_candidate_ = iban_import_candidate; + if (observer_for_testing_) { + observer_for_testing_->OnOfferLocalSave(); + } + // If `show_save_prompt`'s value is false, desktop builds will still offer // save in the omnibox without popping-up the bubble. client_->ConfirmSaveIBANLocally( @@ -65,11 +69,17 @@ base::UTF16ToUTF8(iban_save_candidate_.value())); client_->GetPersonalDataManager()->OnAcceptedLocalIBANSave( iban_save_candidate_); + if (observer_for_testing_) { + observer_for_testing_->OnAcceptSaveIbanComplete(); + } break; case AutofillClient::SaveIBANOfferUserDecision::kIgnored: case AutofillClient::SaveIBANOfferUserDecision::kDeclined: GetIBANSaveStrikeDatabase()->AddStrike( base::UTF16ToUTF8(iban_save_candidate_.value())); + if (observer_for_testing_) { + observer_for_testing_->OnDeclineSaveIbanComplete(); + } break; } }
diff --git a/components/autofill/core/browser/payments/iban_save_manager.h b/components/autofill/core/browser/payments/iban_save_manager.h index 162bad33..9df2f1f 100644 --- a/components/autofill/core/browser/payments/iban_save_manager.h +++ b/components/autofill/core/browser/payments/iban_save_manager.h
@@ -19,6 +19,16 @@ // for local saves. class IBANSaveManager { public: + // An observer class used by browsertests that gets notified whenever + // particular actions occur. + class ObserverForTest { + public: + virtual ~ObserverForTest() = default; + virtual void OnOfferLocalSave() {} + virtual void OnAcceptSaveIbanComplete() {} + virtual void OnDeclineSaveIbanComplete() {} + }; + explicit IBANSaveManager(AutofillClient* client); IBANSaveManager(const IBANSaveManager&) = delete; IBANSaveManager& operator=(const IBANSaveManager&) = delete; @@ -38,6 +48,15 @@ OnUserDidDecideOnLocalSave(user_decision, nickname); } + // Returns the IBANSaveStrikeDatabase for `client_`. + IBANSaveStrikeDatabase* GetIBANSaveStrikeDatabaseForTesting() { + return GetIBANSaveStrikeDatabase(); + } + + void SetEventObserverForTesting(ObserverForTest* observer) { + observer_for_testing_ = observer; + } + private: // Returns the IBANSaveStrikeDatabase for `client_`; IBANSaveStrikeDatabase* GetIBANSaveStrikeDatabase(); @@ -59,6 +78,9 @@ // StrikeDatabase used to check whether to offer to save the IBAN or not. std::unique_ptr<IBANSaveStrikeDatabase> iban_save_strike_database_; + // May be null. + raw_ptr<ObserverForTest> observer_for_testing_ = nullptr; + base::WeakPtrFactory<IBANSaveManager> weak_ptr_factory_{this}; };
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 42cb57c..0cd5c6a 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -34,7 +34,9 @@ #include "components/autofill/core/browser/autofill_download_manager.h" #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/autofill_profile_save_strike_database.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_profile_comparator.h" #include "components/autofill/core/browser/data_model/credit_card_art_image.h" #include "components/autofill/core/browser/data_model/phone_number.h" @@ -318,6 +320,9 @@ } if (strike_database) { + profile_migration_strike_database_ = + std::make_unique<AutofillProfileMigrationStrikeDatabase>( + strike_database); profile_save_strike_database_ = std::make_unique<AutofillProfileSaveStrikeDatabase>(strike_database); profile_update_strike_database_ = @@ -781,7 +786,7 @@ } AutofillProfile* PersonalDataManager::GetProfileByGUID( - const std::string& guid) { + const std::string& guid) const { // GUIDs are unique among profile sources. return GetProfileFromProfilesByGUID(guid, GetProfiles()); } @@ -1713,6 +1718,33 @@ return change_happened; } +bool PersonalDataManager::IsProfileMigrationBlocked( + const std::string& guid) const { + AutofillProfile* profile = GetProfileByGUID(guid); + DCHECK(profile == nullptr || + profile->source() == AutofillProfile::Source::kLocalOrSyncable); + if (!GetProfileMigrationStrikeDatabase()) { + return false; + } + return GetProfileMigrationStrikeDatabase()->ShouldBlockFeature(guid); +} + +void PersonalDataManager::AddStrikeToBlockProfileMigration( + const std::string& guid) { + if (!GetProfileMigrationStrikeDatabase()) { + return; + } + GetProfileMigrationStrikeDatabase()->AddStrike(guid); +} + +void PersonalDataManager::RemoveStrikesToBlockProfileMigration( + const std::string& guid) { + if (!GetProfileMigrationStrikeDatabase()) { + return; + } + GetProfileMigrationStrikeDatabase()->ClearStrikes(guid); +} + bool PersonalDataManager::IsNewProfileImportBlockedForDomain( const GURL& url) const { if (!GetProfileSaveStrikeDatabase() || !url.is_valid() || !url.has_host()) { @@ -1743,7 +1775,6 @@ if (!GetProfileUpdateStrikeDatabase()) { return false; } - return GetProfileUpdateStrikeDatabase()->ShouldBlockFeature(guid); } @@ -1751,7 +1782,6 @@ const std::string& guid) { if (!GetProfileUpdateStrikeDatabase()) return; - GetProfileUpdateStrikeDatabase()->AddStrike(guid); } @@ -1763,6 +1793,17 @@ GetProfileUpdateStrikeDatabase()->ClearStrikes(guid); } +AutofillProfileMigrationStrikeDatabase* +PersonalDataManager::GetProfileMigrationStrikeDatabase() { + return const_cast<AutofillProfileMigrationStrikeDatabase*>( + std::as_const(*this).GetProfileMigrationStrikeDatabase()); +} + +const AutofillProfileMigrationStrikeDatabase* +PersonalDataManager::GetProfileMigrationStrikeDatabase() const { + return profile_migration_strike_database_.get(); +} + AutofillProfileSaveStrikeDatabase* PersonalDataManager::GetProfileSaveStrikeDatabase() { return const_cast<AutofillProfileSaveStrikeDatabase*>(
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 7d662dd..3a5d6c3 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -20,6 +20,7 @@ #include "base/observer_list.h" #include "base/scoped_observation.h" #include "build/build_config.h" +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/autofill_profile_save_strike_database.h" #include "components/autofill/core/browser/autofill_profile_update_strike_database.h" #include "components/autofill/core/browser/data_model/autofill_offer_data.h" @@ -202,7 +203,7 @@ // Returns the profile with the specified |guid|, or nullptr if there is no // profile with the specified |guid|. - virtual AutofillProfile* GetProfileByGUID(const std::string& guid); + virtual AutofillProfile* GetProfileByGUID(const std::string& guid) const; // Returns the profile with the specified |guid| from the given |profiles|, or // nullptr if there is no profile with the specified |guid|. @@ -503,6 +504,18 @@ virtual void SetProfilesForAllSources( std::vector<AutofillProfile>* new_profiles); + // Returns true if a `kLocalOrSyncable` profile identified by its guid is + // blocked for migration to a `kAccount` profile. + bool IsProfileMigrationBlocked(const std::string& guid) const; + + // Adds a strike to block a profile identified by its `guid` for migrations. + // Does nothing if the strike database is not available. + void AddStrikeToBlockProfileMigration(const std::string& guid); + + // Removes potential strikes to block a profile identified by its `guid` for + // migrations. Does nothing if the strike database is not available. + void RemoveStrikesToBlockProfileMigration(const std::string& guid); + // Returns true if the import of new profiles should be blocked on `url`. // Returns false if the strike database is not available, the `url` is not // valid or has no host. @@ -608,14 +621,23 @@ friend void SetTestProfiles(Profile* base_profile, std::vector<AutofillProfile>* profiles); + // Used to get a pointer to the strike database for migrating existing + // profiles. Note, the result can be a nullptr, for example, on incognito + // mode. + AutofillProfileMigrationStrikeDatabase* GetProfileMigrationStrikeDatabase(); + virtual const AutofillProfileMigrationStrikeDatabase* + GetProfileMigrationStrikeDatabase() const; + // Used to get a pointer to the strike database for importing new profiles. - // Note, the result can be a nullptr. + // Note, the result can be a nullptr, for example, on incognito + // mode. AutofillProfileSaveStrikeDatabase* GetProfileSaveStrikeDatabase(); virtual const AutofillProfileSaveStrikeDatabase* GetProfileSaveStrikeDatabase() const; // Used to get a pointer to the strike database for updating existing - // profiles. Note, the result can be a nullptr. + // profiles. Note, the result can be a nullptr, for example, on incognito + // mode. AutofillProfileUpdateStrikeDatabase* GetProfileUpdateStrikeDatabase(); virtual const AutofillProfileUpdateStrikeDatabase* GetProfileUpdateStrikeDatabase() const; @@ -945,6 +967,11 @@ // An observer to listen for changes to prefs::kAutofillWalletImportEnabled. std::unique_ptr<BooleanPrefMember> wallet_enabled_pref_; + // The database that is used to count guid-keyed strikes to suppress the + // migration-prompt of new profiles. + std::unique_ptr<AutofillProfileMigrationStrikeDatabase> + profile_migration_strike_database_; + // The database that is used to count domain-keyed strikes to suppress the // import of new profiles. std::unique_ptr<AutofillProfileSaveStrikeDatabase>
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index f33c6175..a482b71 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -66,6 +66,7 @@ using testing::Pointee; using testing::UnorderedElementsAre; +const char kGuid[] = "a21f010a-eac1-41fc-aee9-c06bbedfb292"; const char kPrimaryAccountEmail[] = "syncuser@example.com"; const char16_t kPrimaryAccountEmail16[] = u"syncuser@example.com"; const std::string kAddressEntryIcon = "accountIcon"; @@ -5374,24 +5375,40 @@ EXPECT_TRUE(prefs_->GetDict(prefs::kAutofillSyncTransportOptIn).empty()); } -TEST_F(PersonalDataManagerTest, SaveProfileUpdateStrikes) { - std::string guid = "a21f010a-eac1-41fc-aee9-c06bbedfb292"; +TEST_F(PersonalDataManagerTest, SaveProfileMigrationStrikes) { + EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid)); - EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid)); + personal_data_->AddStrikeToBlockProfileMigration(kGuid); + EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid)); - personal_data_->AddStrikeToBlockProfileUpdate(guid); - EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid)); - - personal_data_->AddStrikeToBlockProfileUpdate(guid); - EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid)); + personal_data_->AddStrikeToBlockProfileMigration(kGuid); + EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid)); // After the third strike, the guid should be blocked. - personal_data_->AddStrikeToBlockProfileUpdate(guid); - EXPECT_TRUE(personal_data_->IsProfileUpdateBlocked(guid)); + personal_data_->AddStrikeToBlockProfileMigration(kGuid); + EXPECT_TRUE(personal_data_->IsProfileMigrationBlocked(kGuid)); // Until the strikes are removed again. - personal_data_->RemoveStrikesToBlockProfileUpdate(guid); - EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid)); + personal_data_->RemoveStrikesToBlockProfileMigration(kGuid); + EXPECT_FALSE(personal_data_->IsProfileMigrationBlocked(kGuid)); +} + +TEST_F(PersonalDataManagerTest, SaveProfileUpdateStrikes) { + EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid)); + + personal_data_->AddStrikeToBlockProfileUpdate(kGuid); + EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid)); + + personal_data_->AddStrikeToBlockProfileUpdate(kGuid); + EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid)); + + // After the third strike, the guid should be blocked. + personal_data_->AddStrikeToBlockProfileUpdate(kGuid); + EXPECT_TRUE(personal_data_->IsProfileUpdateBlocked(kGuid)); + + // Until the strikes are removed again. + personal_data_->RemoveStrikesToBlockProfileUpdate(kGuid); + EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(kGuid)); } TEST_F(PersonalDataManagerTest, SaveProfileSaveStrikes) {
diff --git a/components/autofill/core/browser/test_personal_data_manager.cc b/components/autofill/core/browser/test_personal_data_manager.cc index ea5a7f4..388c082 100644 --- a/components/autofill/core/browser/test_personal_data_manager.cc +++ b/components/autofill/core/browser/test_personal_data_manager.cc
@@ -6,6 +6,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/common/autofill_features.h" @@ -315,6 +316,11 @@ return account_info_; } +const AutofillProfileMigrationStrikeDatabase* +TestPersonalDataManager::GetProfileMigrationStrikeDatabase() const { + return &inmemory_profile_migration_strike_database_; +} + const AutofillProfileSaveStrikeDatabase* TestPersonalDataManager::GetProfileSaveStrikeDatabase() const { return &inmemory_profile_save_strike_database_;
diff --git a/components/autofill/core/browser/test_personal_data_manager.h b/components/autofill/core/browser/test_personal_data_manager.h index f22bffc..004df5f8 100644 --- a/components/autofill/core/browser/test_personal_data_manager.h +++ b/components/autofill/core/browser/test_personal_data_manager.h
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "components/autofill/core/browser/autofill_profile_migration_strike_database.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/iban.h" @@ -76,6 +77,8 @@ bool IsDataLoaded() const override; bool IsSyncFeatureEnabled() const override; CoreAccountInfo GetAccountInfoForPaymentsServer() const override; + const AutofillProfileMigrationStrikeDatabase* + GetProfileMigrationStrikeDatabase() const override; const AutofillProfileSaveStrikeDatabase* GetProfileSaveStrikeDatabase() const override; const AutofillProfileUpdateStrikeDatabase* GetProfileUpdateStrikeDatabase() @@ -179,6 +182,8 @@ CoreAccountInfo account_info_; TestInMemoryStrikeDatabase inmemory_strike_database_; + AutofillProfileMigrationStrikeDatabase + inmemory_profile_migration_strike_database_{&inmemory_strike_database_}; AutofillProfileSaveStrikeDatabase inmemory_profile_save_strike_database_{ &inmemory_strike_database_}; AutofillProfileUpdateStrikeDatabase inmemory_profile_update_strike_database_{
diff --git a/components/autofill/core/browser/touch_to_fill_delegate_impl.cc b/components/autofill/core/browser/touch_to_fill_delegate_impl.cc index 0e95cca9..7b194a5 100644 --- a/components/autofill/core/browser/touch_to_fill_delegate_impl.cc +++ b/components/autofill/core/browser/touch_to_fill_delegate_impl.cc
@@ -143,7 +143,7 @@ CreditCard* card = pdm->GetCreditCardByGUID(unique_id); manager_->FillOrPreviewCreditCardForm(mojom::RendererFormDataAction::kFill, query_form_, query_field_, card); - manager_->SetSuggestionOriginMetricState( + manager_->SetAutofillSuggestionMethod( AutofillSuggestionMethod::KTouchToFillCreditCard); }
diff --git a/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc b/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc index 6c90ad36..bc5b573 100644 --- a/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc +++ b/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc
@@ -108,7 +108,7 @@ const FormFieldData& field, const CreditCard* credit_card)); MOCK_METHOD(void, - SetSuggestionOriginMetricState, + SetAutofillSuggestionMethod, (AutofillSuggestionMethod state), (override)); }; @@ -534,7 +534,7 @@ TryToShowTouchToFill(/*expected_success=*/true); EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewCreditCardForm); - EXPECT_CALL(*browser_autofill_manager_, SetSuggestionOriginMetricState); + EXPECT_CALL(*browser_autofill_manager_, SetAutofillSuggestionMethod); touch_to_fill_delegate_->SuggestionSelected(credit_card.server_id()); }
diff --git a/components/autofill/core/common/autofill_data_validation.cc b/components/autofill/core/common/autofill_data_validation.cc index 7144f4de..e8852a5 100644 --- a/components/autofill/core/common/autofill_data_validation.cc +++ b/components/autofill/core/common/autofill_data_validation.cc
@@ -40,9 +40,10 @@ } bool IsValidPasswordFormFillData(const PasswordFormFillData& form) { - return IsValidGURL(form.url) && IsValidFormFieldData(form.username_field) && - IsValidFormFieldData(form.password_field) && - IsValidString(form.preferred_realm) && + return IsValidGURL(form.url) && + IsValidString16(form.preferred_login.username) && + IsValidString16(form.preferred_login.password) && + IsValidString(form.preferred_login.realm) && base::ranges::all_of(form.additional_logins, [](const auto& login) { return IsValidString16(login.username) && IsValidString16(login.password) && IsValidString(login.realm);
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 99515b83..eb2ba68 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -141,14 +141,25 @@ "AutofillDeferSubmissionClassificationAfterAjax", base::FEATURE_DISABLED_BY_DEFAULT); -// If enabled, we try to fill and import from fields based on available -// heuristic or server suggestions even if the autocomplete attribute is not -// specified by the web standard. This does not affect the moments when the UI -// is shown. +// If enabled, server/heuristic predictions take precedence over an unrecognized +// autocomplete attribute. Depending on the parameters, these fields are then +// filled or imported from. Independently of any parameters, suggestions are +// suppressed for such fields. +// Predicting a type for a field can influence other fields due to +// rationalization and sectioning. This also affects metrics like +// Autofill.FieldFillingStats, which rely on the types. +// When only the importing part of this feature is enabled, only the importing +// metrics are reliable. // TODO(crbug.com/1295728): Remove the feature when the experiment is completed. BASE_FEATURE(kAutofillFillAndImportFromMoreFields, "AutofillFillAndImportFromMoreFields", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<bool> kAutofillFillAutocompleteUnrecognized{ + &kAutofillFillAndImportFromMoreFields, "fill_unrecognized_autocomplete", + false}; +const base::FeatureParam<bool> kAutofillImportFromAutoccompleteUnrecognized{ + &kAutofillFillAndImportFromMoreFields, + "import_from_unrecognized_autocomplete", false}; // Kill switch for Autofill filling. BASE_FEATURE(kAutofillDisableFilling,
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index f2321bf4..f0ce8b3a 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -55,6 +55,11 @@ COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillCreateDataForTest); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillFillAndImportFromMoreFields); +COMPONENT_EXPORT(AUTOFILL) +extern const base::FeatureParam<bool> kAutofillFillAutocompleteUnrecognized; +COMPONENT_EXPORT(AUTOFILL) +extern const base::FeatureParam<bool> + kAutofillImportFromAutoccompleteUnrecognized; COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillDisableFilling); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillDisableAddressImport); COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/autofill/core/common/mojom/autofill_types.mojom b/components/autofill/core/common/mojom/autofill_types.mojom index 1ff82c3..6c51ca1 100644 --- a/components/autofill/core/common/mojom/autofill_types.mojom +++ b/components/autofill/core/common/mojom/autofill_types.mojom
@@ -398,11 +398,10 @@ struct PasswordFormFillData { FormRendererId form_renderer_id; url.mojom.Url url; - FormFieldData username_field; - FormFieldData password_field; + FieldRendererId username_element_renderer_id; + FieldRendererId password_element_renderer_id; bool username_may_use_prefilled_placeholder; - string preferred_realm; - bool uses_account_store; + PasswordAndMetadata preferred_login; array<PasswordAndMetadata> additional_logins; bool wait_for_username; };
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc index 9d50acc..9379fe3 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -358,14 +358,13 @@ autofill::PasswordFormFillData* out) { if (!data.ReadFormRendererId(&out->form_renderer_id) || !data.ReadUrl(&out->url) || - !data.ReadUsernameField(&out->username_field) || - !data.ReadPasswordField(&out->password_field) || - !data.ReadPreferredRealm(&out->preferred_realm) || + !data.ReadUsernameElementRendererId(&out->username_element_renderer_id) || + !data.ReadPasswordElementRendererId(&out->password_element_renderer_id) || + !data.ReadPreferredLogin(&out->preferred_login) || !data.ReadAdditionalLogins(&out->additional_logins)) { return false; } - out->uses_account_store = data.uses_account_store(); out->wait_for_username = data.wait_for_username(); out->username_may_use_prefilled_placeholder = data.username_may_use_prefilled_placeholder();
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h index 0ee7938..e0d2b1f9 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -519,14 +519,14 @@ return r.url; } - static const autofill::FormFieldData& username_field( + static const autofill::FieldRendererId& username_element_renderer_id( const autofill::PasswordFormFillData& r) { - return r.username_field; + return r.username_element_renderer_id; } - static const autofill::FormFieldData& password_field( + static const autofill::FieldRendererId& password_element_renderer_id( const autofill::PasswordFormFillData& r) { - return r.password_field; + return r.password_element_renderer_id; } static bool username_may_use_prefilled_placeholder( @@ -534,13 +534,9 @@ return r.username_may_use_prefilled_placeholder; } - static const std::string& preferred_realm( + static const autofill::PasswordAndMetadata& preferred_login( const autofill::PasswordFormFillData& r) { - return r.preferred_realm; - } - - static bool uses_account_store(const autofill::PasswordFormFillData& r) { - return r.uses_account_store; + return r.preferred_login; } static const autofill::PasswordFormFillData::LoginCollection&
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc index 12574492..964b648 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -14,6 +14,7 @@ #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/html_field_types.h" #include "components/autofill/core/common/mojom/test_autofill_types.mojom.h" +#include "components/autofill/core/common/password_form_fill_data.h" #include "components/autofill/core/common/password_generation_util.h" #include "components/autofill/core/common/signatures.h" #include "components/autofill/core/common/unique_ids.h" @@ -24,6 +25,13 @@ namespace autofill { +bool operator==(const PasswordAndMetadata& lhs, + const PasswordAndMetadata& rhs) { + return lhs.username == rhs.username && lhs.password == rhs.password && + lhs.realm == rhs.realm && + lhs.uses_account_store == rhs.uses_account_store; +} + const std::vector<const char*> kOptions = {"Option1", "Option2", "Option3", "Option4"}; namespace { @@ -42,14 +50,12 @@ void CreateTestPasswordFormFillData(PasswordFormFillData* fill_data) { fill_data->form_renderer_id = autofill::FormRendererId(1234); fill_data->url = GURL("https://foo.com/"); - test::CreateTestSelectField("TestUsernameFieldLabel", "TestUsernameFieldName", - "TestUsernameFieldValue", kOptions, kOptions, - &fill_data->username_field); - test::CreateTestSelectField("TestPasswordFieldLabel", "TestPasswordFieldName", - "TestPasswordFieldValue", kOptions, kOptions, - &fill_data->password_field); - fill_data->preferred_realm = "https://foo.com/"; - fill_data->uses_account_store = true; + fill_data->preferred_login.username = u"TestUsernameFieldValue"; + fill_data->username_element_renderer_id = test::MakeFieldRendererId(); + fill_data->preferred_login.password = u"TestPasswordFieldValue"; + fill_data->password_element_renderer_id = test::MakeFieldRendererId(); + fill_data->preferred_login.realm = "https://foo.com/"; + fill_data->preferred_login.uses_account_store = true; PasswordAndMetadata pr; pr.password = u"Tom_Password"; @@ -79,32 +85,12 @@ void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected, const PasswordFormFillData& actual) { EXPECT_EQ(expected.form_renderer_id, actual.form_renderer_id); - EXPECT_TRUE(FormFieldData::DeepEqual( - test::WithoutUnserializedData(expected.username_field), - actual.username_field)); - EXPECT_TRUE(FormFieldData::DeepEqual( - test::WithoutUnserializedData(expected.password_field), - actual.password_field)); - EXPECT_EQ(expected.preferred_realm, actual.preferred_realm); - EXPECT_EQ(expected.uses_account_store, actual.uses_account_store); - - { - EXPECT_EQ(expected.additional_logins.size(), - actual.additional_logins.size()); - auto iter1 = expected.additional_logins.begin(); - auto end1 = expected.additional_logins.end(); - auto iter2 = actual.additional_logins.begin(); - auto end2 = actual.additional_logins.end(); - for (; iter1 != end1 && iter2 != end2; ++iter1, ++iter2) { - EXPECT_EQ(iter1->username, iter2->username); - EXPECT_EQ(iter1->password, iter2->password); - EXPECT_EQ(iter1->realm, iter2->realm); - EXPECT_EQ(iter1->uses_account_store, iter2->uses_account_store); - } - ASSERT_EQ(iter1, end1); - ASSERT_EQ(iter2, end2); - } - + EXPECT_EQ(expected.username_element_renderer_id, + actual.username_element_renderer_id); + EXPECT_EQ(expected.password_element_renderer_id, + actual.password_element_renderer_id); + EXPECT_EQ(expected.preferred_login, actual.preferred_login); + EXPECT_EQ(expected.additional_logins, actual.additional_logins); EXPECT_EQ(expected.wait_for_username, actual.wait_for_username); }
diff --git a/components/autofill/core/common/password_form_fill_data.cc b/components/autofill/core/common/password_form_fill_data.cc index 4e9e4702..f71f002 100644 --- a/components/autofill/core/common/password_form_fill_data.cc +++ b/components/autofill/core/common/password_form_fill_data.cc
@@ -37,11 +37,11 @@ // credentials from |additional_logins| could be used for filling on load. So // in case of filling on load nor |password_field| nor |additional_logins| // can't be cleared - bool is_fallback = data.password_field.unique_renderer_id.is_null(); + bool is_fallback = data.password_element_renderer_id.is_null(); if (!data.wait_for_username && !is_fallback) return data; PasswordFormFillData result(data); - result.password_field.value.clear(); + result.preferred_login.password.clear(); for (auto& credentials : result.additional_logins) credentials.password.clear(); return result;
diff --git a/components/autofill/core/common/password_form_fill_data.h b/components/autofill/core/common/password_form_fill_data.h index fec8e770..f1b0db7e 100644 --- a/components/autofill/core/common/password_form_fill_data.h +++ b/components/autofill/core/common/password_form_fill_data.h
@@ -58,20 +58,16 @@ // An URL consisting of the scheme, host, port and path; the rest is stripped. GURL url; - // Username and password input fields in the form. - FormFieldData username_field; - FormFieldData password_field; + // Identifiers of the username and password fields. + FieldRendererId username_element_renderer_id; + FieldRendererId password_element_renderer_id; // True if the server-side classification believes that the field may be // pre-filled with a placeholder in the value attribute. bool username_may_use_prefilled_placeholder = false; - // The signon realm of the preferred user/pass pair. - std::string preferred_realm; - - // True iff the password originated from the account store rather than the - // local password store. - bool uses_account_store = false; + // The preferred credential. See |IsBetterMatch| for how it is selected. + PasswordAndMetadata preferred_login; // A list of other matching username->PasswordAndMetadata pairs for the form. LoginCollection additional_logins;
diff --git a/components/autofill/ios/form_util/form_activity_observer.h b/components/autofill/ios/form_util/form_activity_observer.h index 27ee38d..4b2ac79 100644 --- a/components/autofill/ios/form_util/form_activity_observer.h +++ b/components/autofill/ios/form_util/form_activity_observer.h
@@ -33,8 +33,6 @@ // same-origin iframe. |params.input_missing| is indicating if there is any // error when parsing the form field information. // |sender_frame| is the WebFrame that sent the form activity message. - // |sender_frame| can be null if frame messaging is not enabled (see - // web::WebState::ScriptCommandCallback comment for details). virtual void FormActivityRegistered(web::WebState* web_state, web::WebFrame* sender_frame, const FormActivityParams& params) {} @@ -48,10 +46,7 @@ // computed ('name', 'action', ...) and a 'field' element containing a list of // dictionaries, each representing a field of the form and containing some // attributes ('name', 'type', ...). |sender_frame| is the WebFrame that sent - // the form submission message. |sender_frame| can be null if frame messaging - // is not enabled (see web::WebState::ScriptCommandCallback comment for - // details). - // TODO(crbug.com/881816): Update comment once WebFrame cannot be null. + // the form submission message. virtual void DocumentSubmitted(web::WebState* web_state, web::WebFrame* sender_frame, const std::string& form_name, @@ -62,8 +57,6 @@ // iframe. |params.input_missing| is indicating if there is any // error when parsing the form field information. // |sender_frame| is the WebFrame that sent the form activity message. - // |sender_frame| can be null if frame messaging is not enabled (see - // web::WebState::ScriptCommandCallback comment for details). virtual void FormRemoved(web::WebState* web_state, web::WebFrame* sender_frame, const FormRemovalParams& params) {}
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp index 00f9c794..4dabfb3 100644 --- a/components/autofill_payments_strings.grdp +++ b/components/autofill_payments_strings.grdp
@@ -8,6 +8,9 @@ <message name="IDS_AUTOFILL_NO_THANKS_DESKTOP_UPLOAD_SAVE" desc="The label for cancel button used in autofill credit card upload save bubble on desktop."> No thanks </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS" desc="The text label for `No thanks` button used in autofill prompt IBAN (International Bank Account Number) local save bubble on desktop."> + No thanks + </message> </if> <if expr="use_titlecase"> <message name="IDS_AUTOFILL_NO_THANKS_DESKTOP_LOCAL_SAVE" desc="In Title Case: The label for cancel button used in autofill credit card local save bubble on desktop."> @@ -16,6 +19,9 @@ <message name="IDS_AUTOFILL_NO_THANKS_DESKTOP_UPLOAD_SAVE" desc="In Title Case: The label for cancel button used in autofill credit card upload save bubble on desktop."> No Thanks </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS" desc="The text label for `No Thanks` button used in autofill prompt IBAN (International Bank Account Number) local save bubble on desktop."> + No Thanks + </message> </if> <if expr="is_android or is_ios"> @@ -501,6 +507,23 @@ From Google Pay </message> + <!--IBAN (International Bank Account Number) related strings - start --> + <message name="IDS_AUTOFILL_SAVE_IBAN_PROMPT_TITLE_LOCAL" desc="Title text for the Autofill save IBAN (International Bank Account Number) prompt when a user submits a form with a valid IBAN."> + Save IBAN to this device? + </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_LABEL" desc="Text to show for the Autofill prompt IBAN (International Bank Account Number) label where user can see the IBAN to be saved."> + IBAN + </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_ACCEPT" desc="The text label for `Save` button used in autofill prompt IBAN (International Bank Account Number) save bubble on desktop."> + Save + </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME" desc="Text to show for the autofill prompt IBAN (International Bank Account Number) save bubble where user can enter nickname optionally."> + Nickname + </message> + <message name="IDS_AUTOFILL_SAVE_IBAN_PLACEHOLDER" desc="The placeholder/label text to show for the autofill prompt IBAN (International Bank Account Number) save bubble to indicate that user can enter nickname optionally."> + Optional + </message> + <!-- virtual cards related strings - start --> <if expr="not is_ios and not is_android"> <message name="IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL" desc="Text shown in the button in the Autofill dropdown menu when a credit card form field is queried, to offer the option to use a virtual card.">
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_ACCEPT.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_ACCEPT.png.sha1 new file mode 100644 index 0000000..8f7c691 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_ACCEPT.png.sha1
@@ -0,0 +1 @@ +3584b6e9ac6b5141d80eebae4743c3349ceb9fbd \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS.png.sha1 new file mode 100644 index 0000000..91f8be8 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_BUBBLE_LOCAL_SAVE_NO_THANKS.png.sha1
@@ -0,0 +1 @@ +117771d4c9ac8c82f03bbbdb005868732f0a4e2e \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_LABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_LABEL.png.sha1 new file mode 100644 index 0000000..c4eef9c --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_LABEL.png.sha1
@@ -0,0 +1 @@ +aeba033fd2bdbb30304c0434cb6e904e353a77b9 \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PLACEHOLDER.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PLACEHOLDER.png.sha1 new file mode 100644 index 0000000..535a380 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PLACEHOLDER.png.sha1
@@ -0,0 +1 @@ +441d18b5116afde8b3fb9839647f972903ba8a4d \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME.png.sha1 new file mode 100644 index 0000000..bf8b7b2 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_NICKNAME.png.sha1
@@ -0,0 +1 @@ +1651001138aa450d36e3c3ee4b9c35b6b4e5e5d7 \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_TITLE_LOCAL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_TITLE_LOCAL.png.sha1 new file mode 100644 index 0000000..12ac4cfd --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_SAVE_IBAN_PROMPT_TITLE_LOCAL.png.sha1
@@ -0,0 +1 @@ +1e7cd0fc31236334f5d1277fd1baa4f72d03ffe0 \ No newline at end of file
diff --git a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java index a88c8ee4..fde90e5 100644 --- a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java +++ b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java
@@ -70,7 +70,7 @@ @Feature({"BackgroundTaskScheduler"}) public void testOneOffTaskDoesNotStartExactlyAtDeadline() { JobParameters jobParameters = - buildOneOffJobParameters(TaskIds.TEST, sClock.currentTimeMillis(), new Long(0)); + buildOneOffJobParameters(TaskIds.TEST, sClock.currentTimeMillis(), Long.valueOf(0)); BackgroundTaskJobService jobService = new BackgroundTaskJobService(); jobService.setClockForTesting(sClock); @@ -83,8 +83,8 @@ @Test @Feature({"BackgroundTaskScheduler"}) public void testOneOffTaskDoesNotStartAfterDeadline() { - JobParameters jobParameters = - buildOneOffJobParameters(TaskIds.TEST, sZeroClock.currentTimeMillis(), new Long(0)); + JobParameters jobParameters = buildOneOffJobParameters( + TaskIds.TEST, sZeroClock.currentTimeMillis(), Long.valueOf(0)); BackgroundTaskJobService jobService = new BackgroundTaskJobService(); jobService.setClockForTesting(sClock);
diff --git a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/TaskInfoTest.java b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/TaskInfoTest.java index 0d3baee..980658e 100644 --- a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/TaskInfoTest.java +++ b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/TaskInfoTest.java
@@ -94,7 +94,7 @@ public void testOneOffNoParamsSet() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create().build(); TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); - CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(null, new Long(0), false); + CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(null, Long.valueOf(0), false); oneOffTask.getTimingInfo().accept(visitor); } @@ -129,7 +129,7 @@ public void testPeriodicNoParamsSet() { TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create().build(); TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); - CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(new Long(0), null, false); + CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(Long.valueOf(0), null, false); periodicTask.getTimingInfo().accept(visitor); } @@ -185,4 +185,4 @@ assertEquals(mStartOrIntervalOrTriggerMs.longValue(), exactInfo.getTriggerAtMs()); } } -} \ No newline at end of file +}
diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmarks/browser/bookmark_codec.cc index 6483958..5d7f6c7 100644 --- a/components/bookmarks/browser/bookmark_codec.cc +++ b/components/bookmarks/browser/bookmark_codec.cc
@@ -216,7 +216,7 @@ if (!version || *version != kCurrentVersion) return false; // Unknown version. - const base::Value* checksum_value = value.FindKey(kChecksumKey); + const base::Value* checksum_value = value.GetDict().Find(kChecksumKey); if (checksum_value) { const std::string* checksum = checksum_value->GetIfString(); if (checksum) @@ -441,7 +441,7 @@ DCHECK(meta_info_map); meta_info_map->clear(); - const base::Value* meta_info = value.FindKey(kMetaInfo); + const base::Value* meta_info = value.GetDict().Find(kMetaInfo); if (!meta_info) return true; @@ -462,7 +462,7 @@ // dictionary of meta info values. if (!meta_info->is_dict()) return false; - DecodeMetaInfoHelper(*meta_info, std::string(), meta_info_map); + DecodeMetaInfoHelper(meta_info->GetDict(), std::string(), meta_info_map); return true; } @@ -474,30 +474,31 @@ DCHECK(meta_info_map); meta_info_map->clear(); - const base::Value* meta_info = value.FindKey(kUnsyncedMetaInfo); + const base::Value* meta_info = value.GetDict().Find(kUnsyncedMetaInfo); if (!meta_info) return true; if (!meta_info->is_dict()) return false; - DecodeMetaInfoHelper(*meta_info, std::string(), meta_info_map); + DecodeMetaInfoHelper(meta_info->GetDict(), std::string(), meta_info_map); return true; } void BookmarkCodec::DecodeMetaInfoHelper( - const base::Value& dict, + const base::Value::Dict& dict, const std::string& prefix, BookmarkNode::MetaInfoMap* meta_info_map) { - DCHECK(dict.is_dict()); - for (const auto it : dict.DictItems()) { + for (const auto it : dict) { // Deprecated keys should be excluded after removing enhanced bookmarks // feature crrev.com/1638413003. - if (base::StartsWith(it.first, "stars.", base::CompareCase::SENSITIVE)) + if (base::StartsWith(it.first, "stars.", base::CompareCase::SENSITIVE)) { continue; + } if (it.second.is_dict()) { - DecodeMetaInfoHelper(it.second, prefix + it.first + ".", meta_info_map); + DecodeMetaInfoHelper(it.second.GetDict(), prefix + it.first + ".", + meta_info_map); } else { const std::string* str = it.second.GetIfString(); if (str)
diff --git a/components/bookmarks/browser/bookmark_codec.h b/components/bookmarks/browser/bookmark_codec.h index fac93c1..de968f0 100644 --- a/components/bookmarks/browser/bookmark_codec.h +++ b/components/bookmarks/browser/bookmark_codec.h
@@ -13,12 +13,9 @@ #include "base/guid.h" #include "base/hash/md5.h" +#include "base/values.h" #include "components/bookmarks/browser/bookmark_node.h" -namespace base { -class Value; -} - namespace bookmarks { class BookmarkModel; @@ -167,7 +164,7 @@ // Decodes the meta info from the supplied sub-node dictionary. The values // found will be inserted in meta_info_map with the given prefix added to the // start of their keys. - void DecodeMetaInfoHelper(const base::Value& dict, + void DecodeMetaInfoHelper(const base::Value::Dict& dict, const std::string& prefix, BookmarkNode::MetaInfoMap* meta_info_map);
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java index a149fc5d..77f841d 100644 --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
@@ -82,8 +82,8 @@ if (mDelegate.showPageZoomSettingsUI()) { mTextScalePref.setVisible(false); - mPageZoomDefaultZoomPref.setInitialValue( - PageZoomUtils.getDefaultZoomAsSeekValue(mDelegate.getBrowserContextHandle())); + mPageZoomDefaultZoomPref.setInitialValue(PageZoomUtils.getDefaultZoomAsSeekBarValue( + mDelegate.getBrowserContextHandle())); mPageZoomDefaultZoomPref.setOnPreferenceChangeListener(this); mPageZoomAlwaysShowPref.setChecked(PageZoomUtils.shouldShowZoomMenuItem()); mPageZoomAlwaysShowPref.setOnPreferenceChangeListener(this);
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java index 284e8988..3e7039b5 100644 --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtils.java
@@ -133,7 +133,7 @@ * This is part of the Profile and is set in Desktop through Settings > Appearance. * @return int */ - public static int getDefaultZoomAsSeekValue(BrowserContextHandle context) { + public static int getDefaultZoomAsSeekBarValue(BrowserContextHandle context) { return convertZoomFactorToSeekBarValue(getDefaultZoomLevel(context)); }
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtilsUnitTest.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtilsUnitTest.java index fc3dc7b..a5ec9f8 100644 --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtilsUnitTest.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/PageZoomUtilsUnitTest.java
@@ -4,6 +4,11 @@ package org.chromium.components.browser_ui.accessibility; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import androidx.test.filters.SmallTest; import org.junit.Assert; @@ -16,8 +21,11 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; +import org.chromium.content.browser.ContentFeatureListImpl; +import org.chromium.content.browser.ContentFeatureListImplJni; import org.chromium.content.browser.HostZoomMapImpl; import org.chromium.content.browser.HostZoomMapImplJni; +import org.chromium.content_public.browser.BrowserContextHandle; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.modelutil.PropertyModel; @@ -38,6 +46,16 @@ private static final String GET_NEXT_INDEX_INCREASE_FAILURE = "Failure to get next index in increasing direction."; + private static final String SET_DEFAULT_FAILURE_NO_JNI = + "Failure in set default zoom by seekbar value. Expected 1 JNI call but none occurred."; + private static final String GET_DEFAULT_FAILURE_NO_JNI = + "Failure in get default zoom as seekbar value. Expected 1 JNI call but none occurred."; + private static final String GET_DEFAULT_FAILURE = + "Failure to get default zoom as seekbar value."; + + private static final String SHOULD_SHOW_ZOOM_MENU_ITEM_FAILURE_EXPECTED_FALSE = + "Failure in should show zoom menu item method. Expected false but returned true."; + @Rule public JniMocker mJniMocker = new JniMocker(); @@ -47,6 +65,12 @@ @Mock private HostZoomMapImpl.Natives mHostZoomMapMock; + @Mock + private ContentFeatureListImpl.Natives mContentFeatureListMock; + + @Mock + private BrowserContextHandle mContextMock; + private PropertyModel mModel; @Before @@ -54,6 +78,7 @@ MockitoAnnotations.initMocks(this); mJniMocker.mock(HostZoomMapImplJni.TEST_HOOKS, mHostZoomMapMock); + mJniMocker.mock(ContentFeatureListImplJni.TEST_HOOKS, mContentFeatureListMock); } @Test @@ -90,6 +115,29 @@ } @Test + public void testSetDefaultZoomBySeekbarValue() { + PageZoomUtils.setDefaultZoomBySeekBarValue(mContextMock, 110); + verify(mHostZoomMapMock, times(1).description(SET_DEFAULT_FAILURE_NO_JNI)) + .setDefaultZoomLevel(mContextMock, 2.58); + } + + @Test + public void testGetDefaultZoomBySeekbarValue() { + when(mHostZoomMapMock.getDefaultZoomLevel(mContextMock)).thenReturn(2.58); + Assert.assertEquals(GET_DEFAULT_FAILURE, 110, + PageZoomUtils.getDefaultZoomAsSeekBarValue(mContextMock), 0.0001); + verify(mHostZoomMapMock, times(1).description(GET_DEFAULT_FAILURE_NO_JNI)) + .getDefaultZoomLevel(mContextMock); + } + + @Test + public void testShouldAlwaysShowZoomMenuItem_featureFlagOff() { + when(mContentFeatureListMock.isEnabled(any())).thenReturn(false); + Assert.assertEquals(SHOULD_SHOW_ZOOM_MENU_ITEM_FAILURE_EXPECTED_FALSE, false, + PageZoomUtils.shouldAlwaysShowZoomMenuItem()); + } + + @Test public void testGetNextIndexIncrease() { Assert.assertEquals(GET_NEXT_INDEX_INCREASE_FAILURE, 7, PageZoomUtils.getNextIndex(false, 1.00), 0.0001);
diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn index a9b64c2..48855a7 100644 --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn
@@ -108,6 +108,7 @@ "//base:base_java", "//base:jni_java", "//build/android:build_java", + "//components/browser_ui/modaldialog/android:java", "//components/browser_ui/settings/android:java", "//components/browser_ui/site_settings/android:constants_java", "//components/browser_ui/styles/android:java",
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java index 38e8f42e..be37c76 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -47,6 +47,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.build.annotations.UsedByReflection; +import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -73,6 +74,13 @@ import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.BrowserContextHandle; import org.chromium.content_public.browser.ContentFeatureList; +import org.chromium.ui.modaldialog.DialogDismissalCause; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.modaldialog.ModalDialogProperties.ButtonType; +import org.chromium.ui.modaldialog.ModalDialogProperties.Controller; +import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.widget.Toast; import java.lang.annotation.Retention; @@ -608,25 +616,48 @@ private void showDisableSiteDataConfirmationDialog() { assert mCategory.getType() == SiteSettingsCategory.Type.SITE_DATA; - BrowserContextHandle browserContextHandle = - getSiteSettingsDelegate().getBrowserContextHandle(); - AlertDialog.Builder builder = - new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog); - builder.setTitle(R.string.website_settings_site_data_page_block_confirm_dialog_title) - .setMessage( - R.string.website_settings_site_data_page_block_confirm_dialog_description) - .setNegativeButton( - R.string.website_settings_site_data_page_block_confirm_dialog_cancel_button, - null) - .setPositiveButton( - R.string.website_settings_site_data_page_block_confirm_dialog_confirm_button, - (dialog, which) -> { - WebsitePreferenceBridge.setCategoryEnabled(browserContextHandle, - mCategory.getContentSettingsType(), false); - getInfoForOrigins(); - dialog.dismiss(); - }); - builder.show(); + + var manager = + new ModalDialogManager(new AppModalPresenter(getContext()), ModalDialogType.APP); + var controller = new Controller() { + @Override + public void onClick(PropertyModel model, @ButtonType int buttonType) { + switch (buttonType) { + case ButtonType.POSITIVE: + WebsitePreferenceBridge.setCategoryEnabled( + getSiteSettingsDelegate().getBrowserContextHandle(), + mCategory.getContentSettingsType(), false); + getInfoForOrigins(); + manager.dismissDialog(model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED); + break; + case ButtonType.NEGATIVE: + manager.dismissDialog(model, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED); + break; + default: + assert false; + break; + } + } + @Override + public void onDismiss(PropertyModel model, int dismissalCause) {} + }; + var resources = getContext().getResources(); + var builder = + new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) + .with(ModalDialogProperties.CONTROLLER, controller) + .with(ModalDialogProperties.TITLE, resources, + R.string.website_settings_site_data_page_block_confirm_dialog_title) + .with(ModalDialogProperties.MESSAGE_PARAGRAPH_1, + resources.getString( + R.string.website_settings_site_data_page_block_confirm_dialog_description)) + .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, + R.string.website_settings_site_data_page_block_confirm_dialog_confirm_button) + .with(ModalDialogProperties.BUTTON_STYLES, + ModalDialogProperties.ButtonStyles.PRIMARY_FILLED_NEGATIVE_OUTLINE) + .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources, + R.string.website_settings_site_data_page_block_confirm_dialog_cancel_button); + var model = builder.build(); + manager.showDialog(model, ModalDialogType.APP); } private void setCookieSettingsPreference(CookieSettingsState state) {
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index 80b9d47..f193db0c 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -954,7 +954,7 @@ <!-- Page Zoom --> <message name="IDS_PAGE_ZOOM_TITLE" desc="Title of the preference that allows the user to update the accessibility page zoom feature that applies to the web contents."> - Zoom + Default zoom </message> <message name="IDS_PAGE_ZOOM_LABEL" desc="Accessibility label for control to allow user to change page zoom"> Page zoom @@ -963,7 +963,7 @@ Current zoom is <ph name="ZOOM_LEVEL">%1$d<ex>100</ex></ph> %% </message> <message name="IDS_PAGE_ZOOM_SUMMARY" desc="Summary of the preference that allows the user to update the accessibility page zoom feature that applies to the web contents."> - Make the default text and images on sites smaller or larger + Make text and images larger or smaller for all sites you visit </message> <message name="IDS_PAGE_ZOOM_DECREASE_ZOOM_BUTTON_TEXT" desc="Accessibility label for button to allow user to decrease page zoom"> Decrease zoom @@ -975,10 +975,10 @@ <ph name="ZOOM_LEVEL">%1$d<ex>100</ex></ph> %% </message> <message name="IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_TITLE" desc="Title of the preference that allows the user to always show the menu item for zoom"> - Show zoom + Show zoom option in main menu </message> <message name="IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_SUMMARY" desc="Summary of the preference that allows the user to always show the menu item for zoom."> - Zoom in or out on a page from the main menu + Make it easier to zoom in on text and images for a site you visit </message> <message name="IDS_PAGE_ZOOM_PREVIEW_TITLE" desc="Label of the section of sample text shown to the user to preview zoom level."> Preview
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_SUMMARY.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_SUMMARY.png.sha1 index 8e09563..b2013c9e 100644 --- a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_SUMMARY.png.sha1 +++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_SUMMARY.png.sha1
@@ -1 +1 @@ -35567ca38fcc25c9b5d8555eb7ffbacdeef459be \ No newline at end of file +4193d8f628b83b0e41ab13c7ae1a9dbeccfe1e20 \ No newline at end of file
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_TITLE.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_TITLE.png.sha1 index aa271ce..b2013c9e 100644 --- a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_TITLE.png.sha1 +++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_ALWAYS_SHOW_PREFERENCE_TITLE.png.sha1
@@ -1 +1 @@ -e804030fe0acd36452306df88389f61390b5cceb \ No newline at end of file +4193d8f628b83b0e41ab13c7ae1a9dbeccfe1e20 \ No newline at end of file
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_SUMMARY.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_SUMMARY.png.sha1 index 1dce946d..b2013c9e 100644 --- a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_SUMMARY.png.sha1 +++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_SUMMARY.png.sha1
@@ -1 +1 @@ -b9ba4e164c73712289760a5e9a5d23c3138320fb \ No newline at end of file +4193d8f628b83b0e41ab13c7ae1a9dbeccfe1e20 \ No newline at end of file
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_TITLE.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_TITLE.png.sha1 index 409e203..b2013c9e 100644 --- a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_TITLE.png.sha1 +++ b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_ZOOM_TITLE.png.sha1
@@ -1 +1 @@ -2109e8c7337a48f04d9e8edd9d07be646da1677c \ No newline at end of file +4193d8f628b83b0e41ab13c7ae1a9dbeccfe1e20 \ No newline at end of file
diff --git a/components/browsing_data/content/browsing_data_model.cc b/components/browsing_data/content/browsing_data_model.cc index b27d51b..1a58aa2 100644 --- a/components/browsing_data/content/browsing_data_model.cc +++ b/components/browsing_data/content/browsing_data_model.cc
@@ -79,6 +79,14 @@ return data_key.owner.host(); } +template <> +std::string GetPrimaryHost::operator()<content::AttributionDataModel::DataKey>( + const content::AttributionDataModel::DataKey& data_key) const { + DCHECK_EQ(BrowsingDataModel::StorageType::kAttributionReporting, + storage_type_); + return data_key.reporting_origin().host(); +} + // Helper which allows the lifetime management of a deletion action to occur // separately from the BrowsingDataModel itself. struct StorageRemoverHelper { @@ -190,6 +198,19 @@ } } +template <> +void StorageRemoverHelper::Visitor::operator()< + content::AttributionDataModel::DataKey>( + const content::AttributionDataModel::DataKey& data_key) { + if (types.Has(BrowsingDataModel::StorageType::kAttributionReporting)) { + helper->storage_partition_->GetAttributionDataModel() + ->RemoveAttributionDataByDataKey(data_key, + helper->GetCompleteCallback()); + } else { + NOTREACHED(); + } +} + base::OnceClosure StorageRemoverHelper::GetCompleteCallback() { callbacks_expected_++; return base::BindOnce(&StorageRemoverHelper::BackendFinished, @@ -247,6 +268,18 @@ std::move(loaded_callback).Run(); } +void OnAttributionReportingLoaded( + BrowsingDataModel* model, + base::OnceClosure loaded_callback, + std::vector<content::AttributionDataModel::DataKey> attribution_reporting) { + for (const auto& data_key : attribution_reporting) { + model->AddBrowsingData( + data_key, BrowsingDataModel::StorageType::kAttributionReporting, + kSmallAmountOfDataInBytes); + } + std::move(loaded_callback).Run(); +} + } // namespace BrowsingDataModel::DataDetails::~DataDetails() = default; @@ -393,13 +426,21 @@ base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI); bool is_interest_group_enabled = base::FeatureList::IsEnabled(blink::features::kAdInterestGroupAPI); + bool is_attribution_reporting_enabled = + base::FeatureList::IsEnabled(blink::features::kConversionMeasurement); + // TODO(crbug.com/1271155): Derive this from the StorageTypeSet directly. int storage_backend_count = 1; - if (is_shared_storage_enabled) + if (is_shared_storage_enabled) { storage_backend_count++; - if (is_interest_group_enabled) + } + if (is_interest_group_enabled) { storage_backend_count++; + } + if (is_attribution_reporting_enabled) { + storage_backend_count++; + } base::RepeatingClosure completion = base::BarrierClosure(storage_backend_count, std::move(finished_callback)); @@ -422,6 +463,12 @@ storage_partition_->GetInterestGroupManager()->GetAllInterestGroupDataKeys( base::BindOnce(&OnInterestGroupsLoaded, this, completion)); } + + // Attribution Reporting + if (is_attribution_reporting_enabled) { + storage_partition_->GetAttributionDataModel()->GetAllDataKeys( + base::BindOnce(&OnAttributionReportingLoaded, this, completion)); + } } BrowsingDataModel::BrowsingDataModel(
diff --git a/components/browsing_data/content/browsing_data_model.h b/components/browsing_data/content/browsing_data_model.h index 2c05240..543386c 100644 --- a/components/browsing_data/content/browsing_data_model.h +++ b/components/browsing_data/content/browsing_data_model.h
@@ -11,6 +11,7 @@ #include "base/containers/enum_set.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ref.h" +#include "content/public/browser/attribution_data_model.h" #include "content/public/browser/interest_group_manager.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -35,6 +36,7 @@ kTrustTokens, // Only issuance information considered. kSharedStorage, kInterestGroup, + kAttributionReporting, kPartitionedQuotaStorage, // Not fetched from disk or deleted. kUnpartitionedQuotaStorage, // Not fetched from disk or deleted. @@ -49,7 +51,8 @@ // using this information. typedef absl::variant<url::Origin, // Single origin, e.g. Trust Tokens blink::StorageKey, // Partitioned JS storage - content::InterestGroupManager::InterestGroupDataKey + content::InterestGroupManager::InterestGroupDataKey, + content::AttributionDataModel::DataKey // TODO(crbug.com/1271155): Additional backend keys. > DataKey;
diff --git a/components/cast/named_message_port_connector/BUILD.gn b/components/cast/named_message_port_connector/BUILD.gn index b82f9bd..bfa6417 100644 --- a/components/cast/named_message_port_connector/BUILD.gn +++ b/components/cast/named_message_port_connector/BUILD.gn
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//third_party/closure_compiler/compile_js.gni") import("//tools/grit/grit_rule.gni") source_set("named_message_port_connector") { @@ -22,7 +21,6 @@ grit("resources") { source = "named_message_port_connector_resources.grd" - deps = [ ":js_type_check" ] outputs = [ "grit/named_message_port_connector_resources.h", "named_message_port_connector_resources.pak", @@ -31,9 +29,3 @@ # Allow GRIT to assign IDs using its default set of base IDs. resource_ids = "" } - -js_binary("js_type_check") { - sources = [ "named_message_port_connector.js" ] - checks_only = true - closure_flags = strict_error_checking_closure_args -}
diff --git a/components/cdm/renderer/external_clear_key_key_system_info.cc b/components/cdm/renderer/external_clear_key_key_system_info.cc index af6bd44..4ea8b3b1 100644 --- a/components/cdm/renderer/external_clear_key_key_system_info.cc +++ b/components/cdm/renderer/external_clear_key_key_system_info.cc
@@ -7,19 +7,16 @@ #include "base/notreached.h" #include "media/base/eme_constants.h" #include "media/base/key_system_names.h" +#include "media/cdm/clear_key_cdm_common.h" namespace cdm { -const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; -const char kExternalClearKeyInvalidKeySystem[] = - "org.chromium.externalclearkey.invalid"; - ExternalClearKeySystemInfo::ExternalClearKeySystemInfo() = default; ExternalClearKeySystemInfo::~ExternalClearKeySystemInfo() = default; std::string ExternalClearKeySystemInfo::GetBaseKeySystemName() const { - return kExternalClearKeyKeySystem; + return media::kExternalClearKeyKeySystem; } bool ExternalClearKeySystemInfo::IsSupportedKeySystem( @@ -27,9 +24,10 @@ // Supports kExternalClearKeyKeySystem and all its sub key systems, except for // the explicitly "invalid" one. See the test // EncryptedMediaSupportedTypesExternalClearKeyTest.InvalidKeySystems. - return (key_system == kExternalClearKeyKeySystem || - media::IsSubKeySystemOf(key_system, kExternalClearKeyKeySystem)) && - key_system != kExternalClearKeyInvalidKeySystem; + return (key_system == media::kExternalClearKeyKeySystem || + media::IsSubKeySystemOf(key_system, + media::kExternalClearKeyKeySystem)) && + key_system != media::kExternalClearKeyInvalidKeySystem; } bool ExternalClearKeySystemInfo::IsSupportedInitDataType(
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json index dfeaa31..33bbb1e 100644 --- a/components/certificate_transparency/data/log_list.json +++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@ { - "version": "17.55", - "log_list_timestamp": "2023-01-25T12:54:57Z", + "version": "17.56", + "log_list_timestamp": "2023-01-26T12:56:36Z", "operators": [ { "name": "Google",
diff --git a/components/commerce/core/shopping_bookmark_model_observer.cc b/components/commerce/core/shopping_bookmark_model_observer.cc index e82b2c4a..2e2977f6 100644 --- a/components/commerce/core/shopping_bookmark_model_observer.cc +++ b/components/commerce/core/shopping_bookmark_model_observer.cc
@@ -17,6 +17,7 @@ #include "components/power_bookmarks/core/power_bookmark_utils.h" #include "components/power_bookmarks/core/proto/power_bookmark_meta.pb.h" #include "components/power_bookmarks/core/proto/shopping_specifics.pb.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace commerce { @@ -106,24 +107,11 @@ void ShoppingBookmarkModelObserver::BookmarkMetaInfoChanged( bookmarks::BookmarkModel* model, const bookmarks::BookmarkNode* node) { - std::unique_ptr<power_bookmarks::PowerBookmarkMeta> meta = - power_bookmarks::GetNodePowerBookmarkMeta(model, node); - - // If the changed bookmark is a shopping item, we check its tracking status - // with local subscriptions and if inconsistent, we need to sync local - // subscriptions with the server. This is mainly used to keep local - // subscriptions up to date when users operate on multiple devices. - if (meta && meta->has_shopping_specifics() && subscriptions_manager_) { - power_bookmarks::ShoppingSpecifics* specifics = - meta->mutable_shopping_specifics(); - uint64_t cluster_id = specifics->product_cluster_id(); - - CommerceSubscription sub( - SubscriptionType::kPriceTrack, IdentifierType::kProductClusterId, - base::NumberToString(cluster_id), ManagementType::kUserManaged); - - subscriptions_manager_->VerifyIfSubscriptionExists( - std::move(sub), specifics->is_price_tracked()); + absl::optional<int64_t> last_subscription_change_time = + GetBookmarkLastSubscriptionChangeTime(model, node); + if (last_subscription_change_time.has_value() && subscriptions_manager_) { + subscriptions_manager_->CheckTimestampOnBookmarkChange( + last_subscription_change_time.value()); } }
diff --git a/components/commerce/core/subscriptions/subscriptions_manager.cc b/components/commerce/core/subscriptions/subscriptions_manager.cc index 2d42a6c..6520ebb 100644 --- a/components/commerce/core/subscriptions/subscriptions_manager.cc +++ b/components/commerce/core/subscriptions/subscriptions_manager.cc
@@ -5,6 +5,7 @@ #include "components/commerce/core/subscriptions/subscriptions_manager.h" #include "base/metrics/histogram_functions.h" #include "base/task/sequenced_task_runner.h" +#include "base/time/time.h" #include "components/commerce/core/commerce_feature_list.h" #include "components/commerce/core/subscriptions/commerce_subscription.h" #include "components/commerce/core/subscriptions/subscriptions_observer.h" @@ -71,11 +72,8 @@ base::OnceCallback<void(bool)> callback) { CHECK(subscriptions->size() > 0); - // If there is a coming subscribe request but the last sync with the server - // failed, we should re-try the sync, or this request will fail directly. - if (!last_sync_succeeded_ && !HasRequestRunning()) { - SyncSubscriptions(); - } + SyncIfNeeded(); + pending_requests_.emplace( AsyncOperation::kSubscribe, base::BindOnce(&SubscriptionsManager::HandleSubscribe, @@ -89,11 +87,8 @@ base::OnceCallback<void(bool)> callback) { CHECK(subscriptions->size() > 0); - // If there is a coming unsubscribe request but the last sync with the server - // failed, we should re-try the sync, or this request will fail directly. - if (!last_sync_succeeded_ && !HasRequestRunning()) { - SyncSubscriptions(); - } + SyncIfNeeded(); + pending_requests_.emplace( AsyncOperation::kUnsubscribe, base::BindOnce(&SubscriptionsManager::HandleUnsubscribe, @@ -109,6 +104,41 @@ CheckAndProcessRequest(); } +void SubscriptionsManager::IsSubscribed( + CommerceSubscription subscription, + base::OnceCallback<void(bool)> callback) { + SyncIfNeeded(); + + pending_requests_.emplace( + AsyncOperation::kLookupOne, + base::BindOnce(&SubscriptionsManager::HandleLookup, + weak_ptr_factory_.GetWeakPtr(), std::move(subscription), + std::move(callback))); + CheckAndProcessRequest(); +} + +void SubscriptionsManager::GetAllSubscriptions( + SubscriptionType type, + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback) { + SyncIfNeeded(); + + pending_requests_.emplace(AsyncOperation::kGetAll, + base::BindOnce(&SubscriptionsManager::HandleGetAll, + weak_ptr_factory_.GetWeakPtr(), type, + std::move(callback))); + CheckAndProcessRequest(); +} + +void SubscriptionsManager::CheckTimestampOnBookmarkChange( + int64_t bookmark_subscription_change_time) { + pending_requests_.emplace( + AsyncOperation::kCheckOnBookmarkChange, + base::BindOnce( + &SubscriptionsManager::HandleCheckTimestampOnBookmarkChange, + weak_ptr_factory_.GetWeakPtr(), bookmark_subscription_change_time)); + CheckAndProcessRequest(); +} + void SubscriptionsManager::CheckAndProcessRequest() { if (HasRequestRunning() || pending_requests_.empty()) return; @@ -123,13 +153,28 @@ std::move(request.callback).Run(); } +void SubscriptionsManager::SyncIfNeeded() { + if (!last_sync_succeeded_ && !HasRequestRunning()) { + SyncSubscriptions(); + } +} + void SubscriptionsManager::OnRequestCompletion() { has_request_running_ = false; CheckAndProcessRequest(); } +void SubscriptionsManager::UpdateSyncStates(bool sync_succeeded) { + last_sync_succeeded_ = sync_succeeded; + if (sync_succeeded) { + // Always use the Windows epoch to keep consistency with the timestamp in + // bookmark. + last_sync_time_ = + base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds(); + } +} + void SubscriptionsManager::HandleSync() { - last_sync_succeeded_ = false; if (account_checker_ && account_checker_->IsSignedIn() && account_checker_->IsAnonymizedUrlDataCollectionEnabled()) { GetRemoteSubscriptionsAndUpdateStorage( @@ -141,7 +186,7 @@ void SubscriptionsManager::OnSyncStatusFetched( SubscriptionsRequestStatus result) { - last_sync_succeeded_ = result == SubscriptionsRequestStatus::kSuccess; + UpdateSyncStates(result == SubscriptionsRequestStatus::kSuccess); OnRequestCompletion(); } @@ -180,6 +225,13 @@ observer.OnSubscribe(notified_subscriptions, succeeded); } std::move(callback).Run(succeeded); + // We sync local cache with server only when the product is successfully added + // on server. The sync states should be updated after notifying all observers + // and running the callback so |last_sync_time_| is larger than external + // timestamp (e.g. in bookmarks). + if (result == SubscriptionsRequestStatus::kSuccess) { + UpdateSyncStates(true); + } OnRequestCompletion(); } @@ -235,6 +287,13 @@ observer.OnUnsubscribe(notified_subscriptions, succeeded); } std::move(callback).Run(succeeded); + // We sync local cache with server only when the product is successfully + // removed on server. The sync states should be updated after notifying all + // observers and running the callback so |last_sync_time_| is larger than + // external timestamp (e.g. in bookmarks). + if (result == SubscriptionsRequestStatus::kSuccess) { + UpdateSyncStates(true); + } OnRequestCompletion(); } @@ -289,30 +348,49 @@ } } -void SubscriptionsManager::VerifyIfSubscriptionExists( - CommerceSubscription subscription, - bool should_exist) { - storage_->IsSubscribed( - std::move(subscription), - base::BindOnce( - &SubscriptionsManager::HandleCheckLocalSubscriptionResponse, - weak_ptr_factory_.GetWeakPtr(), should_exist)); -} - -void SubscriptionsManager::IsSubscribed( +void SubscriptionsManager::HandleLookup( CommerceSubscription subscription, base::OnceCallback<void(bool)> callback) { - storage_->IsSubscribed(std::move(subscription), std::move(callback)); + storage_->IsSubscribed( + std::move(subscription), + base::BindOnce(&SubscriptionsManager::OnLookupResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } -void SubscriptionsManager::HandleCheckLocalSubscriptionResponse( - bool should_exist, +void SubscriptionsManager::OnLookupResult( + base::OnceCallback<void(bool)> callback, bool is_subscribed) { - // Don't sync if there is already a request running to avoid redundant server - // calls. - if (should_exist != is_subscribed && !HasRequestRunning()) { - SyncSubscriptions(); + std::move(callback).Run(is_subscribed); + OnRequestCompletion(); +} + +void SubscriptionsManager::HandleGetAll( + SubscriptionType type, + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback) { + storage_->LoadAllSubscriptionsForType( + type, + base::BindOnce(&SubscriptionsManager::OnGetAllResult, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void SubscriptionsManager::OnGetAllResult( + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback, + std::unique_ptr<std::vector<CommerceSubscription>> subscriptions) { + std::move(callback).Run(std::move(*subscriptions)); + OnRequestCompletion(); +} + +void SubscriptionsManager::HandleCheckTimestampOnBookmarkChange( + int64_t bookmark_subscription_change_time) { + // Do nothing if current local cache is newer than the bookmark change. + if (bookmark_subscription_change_time <= last_sync_time_) { + OnRequestCompletion(); + return; } + GetRemoteSubscriptionsAndUpdateStorage( + SubscriptionType::kPriceTrack, + base::BindOnce(&SubscriptionsManager::OnSyncStatusFetched, + weak_ptr_factory_.GetWeakPtr())); } void SubscriptionsManager::OnPrimaryAccountChanged( @@ -353,6 +431,10 @@ return last_sync_succeeded_; } +int64_t SubscriptionsManager::GetLastSyncTimeForTesting() { + return last_sync_time_; +} + void SubscriptionsManager::SetHasRequestRunningForTesting( bool has_request_running) { has_request_running_ = has_request_running;
diff --git a/components/commerce/core/subscriptions/subscriptions_manager.h b/components/commerce/core/subscriptions/subscriptions_manager.h index 5eb1d8e6..6019a31 100644 --- a/components/commerce/core/subscriptions/subscriptions_manager.h +++ b/components/commerce/core/subscriptions/subscriptions_manager.h
@@ -93,23 +93,32 @@ std::unique_ptr<std::vector<CommerceSubscription>> subscriptions, base::OnceCallback<void(bool)> callback); - // If a |subscription| should exist but we cannot find it in local - // subscriptions, or vice versa, we should sync local subscriptions with the - // server. This is mainly used to keep local subscriptions up to date when - // users operate on multiple devices. - void VerifyIfSubscriptionExists(CommerceSubscription subscription, - bool should_exist); - // Check if a |subscription| exists in the local database. void IsSubscribed(CommerceSubscription subscription, base::OnceCallback<void(bool)> callback); + // Get all subscriptions that match the provided |type|. + void GetAllSubscriptions( + SubscriptionType type, + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback); + + // On bookmark meta info change, we check its |last_subscription_change_time| + // against last time we sync server subscriptions with local cache. If the + // latter one is older, the local cache is outdated and we need to fetch the + // newest subscriptions from server. This is mainly used to keep local + // subscriptions up to date when users operate on multiple devices. + void CheckTimestampOnBookmarkChange( + int64_t bookmark_subscription_change_time); + void AddObserver(SubscriptionsObserver* observer); void RemoveObserver(SubscriptionsObserver* observer); // For tests only, return last_sync_succeeded_. bool GetLastSyncSucceededForTesting(); + // For tests only, return last_sync_time_; + int64_t GetLastSyncTimeForTesting(); + // For tests only, set has_request_running_. void SetHasRequestRunningForTesting(bool has_request_running); @@ -123,6 +132,9 @@ kSync = 0, kSubscribe = 1, kUnsubscribe = 2, + kLookupOne = 3, + kGetAll = 4, + kCheckOnBookmarkChange = 5, }; struct Request { @@ -144,10 +156,20 @@ // the queue. void CheckAndProcessRequest(); + // Before adding certain operations (Subscribe, Unsubscribe, LookupOne, and + // GetAll) to the pending requests, if the last sync with server failed, we + // should re-try the sync first. + void SyncIfNeeded(); + // On request completion, mark that no request is running and then check next - // request. This is chained to the main callback when Request object is built. + // request. This must be chained to the end of callback in every Request. void OnRequestCompletion(); + // In certain operations (Sync, Subscribe, Unsubscribe, and + // CheckOnBookmarkChange), we may sync local cache with server and need to + // update |last_sync_succeeded_| and |last_sync_time_|. + void UpdateSyncStates(bool sync_succeeded); + void HandleSync(); void OnSyncStatusFetched(SubscriptionsRequestStatus result); @@ -194,8 +216,22 @@ SubscriptionsRequestCallback callback, SubscriptionsRequestStatus status); - void HandleCheckLocalSubscriptionResponse(bool should_exisit, - bool is_subscribed); + void HandleLookup(CommerceSubscription subscription, + base::OnceCallback<void(bool)> callback); + + void OnLookupResult(base::OnceCallback<void(bool)> callback, + bool is_subscribed); + + void HandleGetAll( + SubscriptionType type, + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback); + + void OnGetAllResult( + base::OnceCallback<void(std::vector<CommerceSubscription>)> callback, + std::unique_ptr<std::vector<CommerceSubscription>> subscriptions); + + void HandleCheckTimestampOnBookmarkChange( + int64_t bookmark_subscription_change_time); void OnPrimaryAccountChanged( const signin::PrimaryAccountChangeEvent& event_details) override; @@ -209,6 +245,8 @@ // Whether the last sync with server is successful. If not, all (un)subscribe // operations will fail immediately. bool last_sync_succeeded_ = false; + // Last time we successfully synced with server. + int64_t last_sync_time_{0L}; // Whether there is any request running. bool has_request_running_ = false;
diff --git a/components/commerce/core/subscriptions/subscriptions_manager_unittest.cc b/components/commerce/core/subscriptions/subscriptions_manager_unittest.cc index b3f34a01..ae9a68d1 100644 --- a/components/commerce/core/subscriptions/subscriptions_manager_unittest.cc +++ b/components/commerce/core/subscriptions/subscriptions_manager_unittest.cc
@@ -149,6 +149,10 @@ (CommerceSubscription subscription, base::OnceCallback<void(bool)> callback), (override)); + MOCK_METHOD(void, + LoadAllSubscriptionsForType, + (SubscriptionType type, GetLocalSubscriptionsCallback callback), + (override)); // Mock the local fetch responses for Get* requests. |subscription_id| is used // to generate a CommerceSubscription to be returned. @@ -209,6 +213,15 @@ std::move(callback).Run(is_subscribed); }); } + + void MockLoadAllSubscriptionsResponses(std::string subscription_id) { + ON_CALL(*this, LoadAllSubscriptionsForType) + .WillByDefault( + [subscription_id](SubscriptionType type, + GetLocalSubscriptionsCallback callback) { + std::move(callback).Run(BuildSubscriptions(subscription_id)); + }); + } }; class SubscriptionsManagerTest : public testing::Test, @@ -284,6 +297,7 @@ .Times(1); CreateManagerAndVerify(true); + ASSERT_LT(0L, subscriptions_manager_->GetLastSyncTimeForTesting()); } TEST_F(SubscriptionsManagerTest, TestSyncFailedDueToStorage) { @@ -296,6 +310,7 @@ .Times(1); CreateManagerAndVerify(false); + ASSERT_EQ(0L, subscriptions_manager_->GetLastSyncTimeForTesting()); } TEST_F(SubscriptionsManagerTest, TestSyncFailedDueToServer) { @@ -306,6 +321,7 @@ EXPECT_CALL(*mock_storage_, UpdateStorage).Times(0); CreateManagerAndVerify(false); + ASSERT_EQ(0L, subscriptions_manager_->GetLastSyncTimeForTesting()); } TEST_F(SubscriptionsManagerTest, TestNotSignedIn) { @@ -340,6 +356,7 @@ } CreateManagerAndVerify(true); + int64_t last_sync_time = subscriptions_manager_->GetLastSyncTimeForTesting(); base::RunLoop run_loop; subscriptions_manager_->Subscribe( BuildSubscriptions("333"), @@ -351,6 +368,8 @@ &run_loop)); // The callback should eventually quit the run loop. run_loop.Run(); + EXPECT_LT(last_sync_time, + subscriptions_manager_->GetLastSyncTimeForTesting()); histogram_tester.ExpectTotalCount(kTrackResultHistogramName, 1); histogram_tester.ExpectBucketCount(kTrackResultHistogramName, 0, 1); @@ -377,6 +396,7 @@ } CreateManagerAndVerify(true); + int64_t last_sync_time = subscriptions_manager_->GetLastSyncTimeForTesting(); base::RunLoop run_loop; subscriptions_manager_->Subscribe( BuildSubscriptions("333"), @@ -388,6 +408,8 @@ &run_loop)); // The callback should eventually quit the run loop. run_loop.Run(); + EXPECT_EQ(last_sync_time, + subscriptions_manager_->GetLastSyncTimeForTesting()); histogram_tester.ExpectTotalCount(kTrackResultHistogramName, 1); histogram_tester.ExpectBucketCount(kTrackResultHistogramName, 1, 1); @@ -626,6 +648,7 @@ } CreateManagerAndVerify(true); + int64_t last_sync_time = subscriptions_manager_->GetLastSyncTimeForTesting(); base::RunLoop run_loop; subscriptions_manager_->Unsubscribe( BuildSubscriptions("333"), @@ -636,6 +659,8 @@ }, &run_loop)); run_loop.Run(); + EXPECT_LT(last_sync_time, + subscriptions_manager_->GetLastSyncTimeForTesting()); histogram_tester.ExpectTotalCount(kUntrackResultHistogramName, 1); histogram_tester.ExpectBucketCount(kUntrackResultHistogramName, 0, 1); @@ -767,71 +792,15 @@ signin::ConsentLevel::kSync); } -TEST_F(SubscriptionsManagerTest, TestVerifyIfSubscriptionExists_Consistent) { - SetAccountStatus(true, true); - mock_server_proxy_->MockGetResponses("111"); - mock_storage_->MockUpdateResponses(true); - mock_storage_->MockIsSubscribedResponses(true); - - EXPECT_CALL(*mock_server_proxy_, Get).Times(1); - EXPECT_CALL(*mock_storage_, - UpdateStorage(_, _, AreExpectedSubscriptions("111"))) - .Times(1); - - CreateManagerAndVerify(true); - subscriptions_manager_->VerifyIfSubscriptionExists(BuildSubscription("222"), - true); -} - -TEST_F(SubscriptionsManagerTest, TestVerifyIfSubscriptionExists_Inconsistent) { - SetAccountStatus(true, true); - mock_server_proxy_->MockGetResponses("111"); - mock_storage_->MockUpdateResponses(true); - mock_storage_->MockIsSubscribedResponses(false); - - { - InSequence s; - // First sync on manager instantiation. - EXPECT_CALL(*mock_server_proxy_, Get); - EXPECT_CALL(*mock_storage_, - UpdateStorage(_, _, AreExpectedSubscriptions("111"))); - // Second sync since local subscriptions are out of sync. - EXPECT_CALL(*mock_server_proxy_, Get); - EXPECT_CALL(*mock_storage_, - UpdateStorage(_, _, AreExpectedSubscriptions("111"))); - } - - CreateManagerAndVerify(true); - subscriptions_manager_->VerifyIfSubscriptionExists(BuildSubscription("222"), - true); -} - -TEST_F(SubscriptionsManagerTest, - TestVerifyIfSubscriptionExists_InconsistentWithRunningRequest) { - SetAccountStatus(true, true); - mock_server_proxy_->MockGetResponses("111"); - mock_storage_->MockUpdateResponses(true); - mock_storage_->MockIsSubscribedResponses(false); - - EXPECT_CALL(*mock_server_proxy_, Get).Times(1); - EXPECT_CALL(*mock_storage_, - UpdateStorage(_, _, AreExpectedSubscriptions("111"))) - .Times(1); - - CreateManagerAndVerify(true); - MockHasRequestRunning(true); - subscriptions_manager_->VerifyIfSubscriptionExists(BuildSubscription("222"), - true); -} - TEST_F(SubscriptionsManagerTest, TestIsSubscribed) { SetAccountStatus(true, true); mock_server_proxy_->MockGetResponses("111"); mock_storage_->MockUpdateResponses(true); mock_storage_->MockIsSubscribedResponses(true); - CreateManagerAndVerify(true); + EXPECT_CALL(*mock_storage_, IsSubscribed); + CreateManagerAndVerify(true); base::RunLoop run_loop; subscriptions_manager_->IsSubscribed( BuildSubscription("111"), @@ -844,6 +813,138 @@ run_loop.Run(); } +TEST_F(SubscriptionsManagerTest, TestIsSubscribed_LastSyncFailed) { + SetAccountStatus(true, true); + mock_server_proxy_->MockGetResponses("111"); + mock_storage_->MockUpdateResponses(false); + mock_storage_->MockIsSubscribedResponses(true); + + { + InSequence s; + // First sync. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + // Re-try the sync when a look up request comes. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + EXPECT_CALL(*mock_storage_, IsSubscribed); + } + + CreateManagerAndVerify(false); + base::RunLoop run_loop; + subscriptions_manager_->IsSubscribed( + BuildSubscription("111"), + base::BindOnce( + [](base::RunLoop* looper, bool is_subscribed) { + EXPECT_TRUE(is_subscribed); + looper->Quit(); + }, + &run_loop)); + run_loop.Run(); +} + +TEST_F(SubscriptionsManagerTest, TestGetAllSubscriptions) { + SetAccountStatus(true, true); + mock_server_proxy_->MockGetResponses("111"); + mock_storage_->MockUpdateResponses(true); + mock_storage_->MockLoadAllSubscriptionsResponses("222"); + + EXPECT_CALL(*mock_storage_, LoadAllSubscriptionsForType); + + CreateManagerAndVerify(true); + base::RunLoop run_loop; + subscriptions_manager_->GetAllSubscriptions( + SubscriptionType::kPriceTrack, + base::BindOnce( + [](base::RunLoop* looper, + std::vector<CommerceSubscription> subscriptions) { + AreExpectedSubscriptions("222"); + looper->Quit(); + }, + &run_loop)); + run_loop.Run(); +} + +TEST_F(SubscriptionsManagerTest, TestGetAllSubscriptions_LastSyncFailed) { + SetAccountStatus(true, true); + mock_server_proxy_->MockGetResponses("111"); + mock_storage_->MockUpdateResponses(false); + mock_storage_->MockLoadAllSubscriptionsResponses("222"); + + { + InSequence s; + // First sync. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + // Re-try the sync when a look up request comes. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + EXPECT_CALL(*mock_storage_, LoadAllSubscriptionsForType); + } + + CreateManagerAndVerify(false); + base::RunLoop run_loop; + subscriptions_manager_->GetAllSubscriptions( + SubscriptionType::kPriceTrack, + base::BindOnce( + [](base::RunLoop* looper, + std::vector<CommerceSubscription> subscriptions) { + AreExpectedSubscriptions("222"); + looper->Quit(); + }, + &run_loop)); + run_loop.Run(); +} + +TEST_F(SubscriptionsManagerTest, + TestCheckTimestampOnBookmarkChange_NeedToSync) { + SetAccountStatus(true, true); + mock_server_proxy_->MockGetResponses("111"); + mock_storage_->MockUpdateResponses(true); + + { + InSequence s; + // First sync. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + // Re-try the sync when local cache is outdated. + EXPECT_CALL(*mock_server_proxy_, Get); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))); + } + + CreateManagerAndVerify(true); + int64_t last_sync_time = subscriptions_manager_->GetLastSyncTimeForTesting(); + subscriptions_manager_->CheckTimestampOnBookmarkChange( + subscriptions_manager_->GetLastSyncTimeForTesting() + 100); + EXPECT_LT(last_sync_time, + subscriptions_manager_->GetLastSyncTimeForTesting()); +} + +TEST_F(SubscriptionsManagerTest, + TestCheckTimestampOnBookmarkChange_NoNeedToSync) { + SetAccountStatus(true, true); + mock_server_proxy_->MockGetResponses("111"); + mock_storage_->MockUpdateResponses(true); + + EXPECT_CALL(*mock_server_proxy_, Get).Times(1); + EXPECT_CALL(*mock_storage_, + UpdateStorage(_, _, AreExpectedSubscriptions("111"))) + .Times(1); + + CreateManagerAndVerify(true); + int64_t last_sync_time = subscriptions_manager_->GetLastSyncTimeForTesting(); + subscriptions_manager_->CheckTimestampOnBookmarkChange( + subscriptions_manager_->GetLastSyncTimeForTesting() - 100); + EXPECT_EQ(last_sync_time, + subscriptions_manager_->GetLastSyncTimeForTesting()); +} + TEST_F(SubscriptionsManagerTest, TestSubscriptionsObserver) { SetAccountStatus(true, true); mock_server_proxy_->MockGetResponses("111");
diff --git a/components/commerce/core/subscriptions/subscriptions_storage.h b/components/commerce/core/subscriptions/subscriptions_storage.h index b4fdce4..ebb5258 100644 --- a/components/commerce/core/subscriptions/subscriptions_storage.h +++ b/components/commerce/core/subscriptions/subscriptions_storage.h
@@ -74,6 +74,11 @@ virtual void IsSubscribed(CommerceSubscription subscription, base::OnceCallback<void(bool)> callback); + // Get all subscriptions that match the provided |type|. + virtual void LoadAllSubscriptionsForType( + SubscriptionType type, + GetLocalSubscriptionsCallback callback); + private: std::string GetSubscriptionKey(const CommerceSubscription& subscription); @@ -83,9 +88,6 @@ void DeleteSubscription(CommerceSubscription subscription, base::OnceCallback<void(bool)> callback); - void LoadAllSubscriptionsForType(SubscriptionType type, - GetLocalSubscriptionsCallback callback); - CommerceSubscription GetSubscriptionFromProto( const SessionProtoStorage<CommerceSubscriptionProto>::KeyAndValue& kv);
diff --git a/components/components_strings.grd b/components/components_strings.grd index 21a34cf..2751b11 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -497,11 +497,20 @@ <message name="IDS_ACCNAME_LOCATION" desc="The accessible name for the editable-text portion of the omnibox."> Address and search bar </message> + <message name="IDS_ACCNAME_TAB_LIST" desc="The accessible name for the tab strip."> + Tab list + </message> <message name="IDS_ACCNAME_PARTICLE_DISC" desc="The accessible name for the Account Consistency Disc on New Tab Page"> Google Account </message> - <message name="IDS_ACCNAME_TAB_LIST" desc="The accessible name for the tab strip."> - Tab list + <message name="IDS_IDENTITY_DISC_WITH_NAME_AND_EMAIL" desc="The content description for a toolbar button displaying user profile picture. Tapping on this button navigates to 'Sync and Google services' page in settings"> + Signed in as <ph name="USER_NAME">%1$s<ex>Peter Parker</ex></ph>. <ph name="USER_EMAIL">%2$s<ex>peter.parker@gmail.com</ex></ph>. Opens settings. + </message> + <message name="IDS_IDENTITY_DISC_WITH_NAME" desc="The content description for a toolbar button displaying user profile picture, for users who don't have a readable email address. Tapping on this button navigates to 'Sync and Google services' page in settings"> + Signed in as <ph name="USER_NAME">%s<ex>Bruce Wayne</ex></ph>. Opens settings. + </message> + <message name="IDS_SIGNED_OUT_IDENTITY_DISC" desc="The content description for a toolbar button displaying the signed-out avatar. Tapping on this button navigates to 'Turn on Sync' page in settings"> + Signed out. Opens dialog to sign in and turn on sync. </message> <message name="IDS_UTILITY_PROCESS_JSON_PARSER_NAME" desc="The name of the utility process used for parsing JSON files.">
diff --git a/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME.png.sha1 b/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME.png.sha1 new file mode 100644 index 0000000..a37a4bf1 --- /dev/null +++ b/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME.png.sha1
@@ -0,0 +1 @@ +2004014b1f780d9d7cc38e3366d47da5d6c4f706 \ No newline at end of file
diff --git a/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME_AND_EMAIL.png.sha1 b/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME_AND_EMAIL.png.sha1 new file mode 100644 index 0000000..a37a4bf1 --- /dev/null +++ b/components/components_strings_grd/IDS_IDENTITY_DISC_WITH_NAME_AND_EMAIL.png.sha1
@@ -0,0 +1 @@ +2004014b1f780d9d7cc38e3366d47da5d6c4f706 \ No newline at end of file
diff --git a/components/components_strings_grd/IDS_SIGNED_OUT_IDENTITY_DISC.png.sha1 b/components/components_strings_grd/IDS_SIGNED_OUT_IDENTITY_DISC.png.sha1 new file mode 100644 index 0000000..831c49f1 --- /dev/null +++ b/components/components_strings_grd/IDS_SIGNED_OUT_IDENTITY_DISC.png.sha1
@@ -0,0 +1 @@ +d44cefb4888b6b325bdd38fbfc9fffc3382734fe \ No newline at end of file
diff --git a/components/content_capture/android/test_support/content_capture_test_support_android.cc b/components/content_capture/android/test_support/content_capture_test_support_android.cc index 7ab2088..bd176baf 100644 --- a/components/content_capture/android/test_support/content_capture_test_support_android.cc +++ b/components/content_capture/android/test_support/content_capture_test_support_android.cc
@@ -4,13 +4,17 @@ #include "components/content_capture/android/test_support/jni_headers/ContentCaptureTestSupport_jni.h" +#include <string> + #include "base/android/jni_string.h" +#include "base/check_deref.h" #include "base/json/json_reader.h" #include "base/notreached.h" #include "base/values.h" #include "components/content_capture/browser/content_capture_receiver.h" #include "components/content_capture/browser/onscreen_content_provider.h" #include "content/public/browser/web_contents.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "ui/gfx/geometry/size.h" @@ -51,22 +55,28 @@ CHECK(root); CHECK(root->is_list()); std::vector<blink::mojom::FaviconURLPtr> favicon_urls; - for (const base::Value& icon : root->GetList()) { + for (const base::Value& icon_val : root->GetList()) { + const base::Value::Dict& icon = icon_val.GetDict(); std::vector<gfx::Size> sizes; // The sizes is optional. - if (auto* icon_sizes = icon.FindKey("sizes")) { - for (const base::Value& size : icon_sizes->GetList()) { - CHECK(size.FindKey("width")); - CHECK(size.FindKey("height")); - sizes.emplace_back(size.FindKey("width")->GetInt(), - size.FindKey("height")->GetInt()); + if (const base::Value::List* icon_sizes = icon.FindList("sizes")) { + for (const base::Value& size_val : CHECK_DEREF(icon_sizes)) { + const base::Value::Dict& size = size_val.GetDict(); + + const absl::optional<int> width = size.FindInt("width"); + const absl::optional<int> height = size.FindInt("height"); + CHECK(width); + CHECK(height); + sizes.emplace_back(width.value(), height.value()); } } - CHECK(icon.FindKey("url")); - CHECK(icon.FindKey("type")); - favicon_urls.push_back(blink::mojom::FaviconURL::New( - GURL(*icon.FindKey("url")->GetIfString()), - ToType(*icon.FindKey("type")->GetIfString()), sizes)); + + const std::string* url = icon.FindString("url"); + const std::string* type = icon.FindString("type"); + CHECK(url); + CHECK(type); + favicon_urls.push_back( + blink::mojom::FaviconURL::New(GURL(*url), ToType(*type), sizes)); } CHECK(!favicon_urls.empty()); provider->NotifyFaviconURLUpdatedForTesting(
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc index ffc05b6..9bb7496 100644 --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -222,7 +222,10 @@ } } - if (block && ShouldConsiderTopLevelStorageAccessGrants(query_reason)) { + if (block && + overrides.Has( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible) && + ShouldConsiderTopLevelStorageAccessGrants(query_reason)) { ContentSetting host_setting = host_content_settings_map_->GetContentSetting( url, first_party_url, ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS);
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc index 9df434b..6ac216c1 100644 --- a/components/content_settings/core/browser/cookie_settings_unittest.cc +++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -76,6 +76,7 @@ struct TestCase { std::string test_name; bool storage_access_api_enabled; + bool top_level_storage_access_grant_eligible; bool force_allow_third_party_cookies; }; @@ -146,12 +147,20 @@ return GetParam().storage_access_api_enabled; } + bool IsTopLevelStorageAccessGrantEligible() const { + return GetParam().top_level_storage_access_grant_eligible; + } + bool IsForceAllowThirdPartyCookies() const { return GetParam().force_allow_third_party_cookies; } net::CookieSettingOverrides GetCookieSettingOverrides() const { net::CookieSettingOverrides overrides; + if (IsTopLevelStorageAccessGrantEligible()) { + overrides.Put( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible); + } if (IsForceAllowThirdPartyCookies()) { overrides.Put(net::CookieSettingOverride::kForceThirdPartyByUser); } @@ -166,11 +175,25 @@ : CONTENT_SETTING_BLOCK; } + // A version of above that considers Top-Level Storage Access API grant + // instead of Storage Access API grant, and user force allow. + ContentSetting SettingWithEitherOverrideForTopLevel() const { + // TODO(crbug.com/1385156): Check TopLevelStorageAccessAPI instead after + // separating the feature flag. + return (IsStorageAccessAPIEnabled() && + IsTopLevelStorageAccessGrantEligible()) || + IsForceAllowThirdPartyCookies() + ? CONTENT_SETTING_ALLOW + : CONTENT_SETTING_BLOCK; + } + ContentSetting SettingWithForceAllowThirdPartyCookies() const { return IsForceAllowThirdPartyCookies() ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; } + // The cookie access result would be blocked if not for a Storage Access API + // grant or force allow. net::cookie_util::StorageAccessResult BlockedStorageAccessResultWithEitherOverride() const { if (IsStorageAccessAPIEnabled()) { @@ -183,9 +206,16 @@ return net::cookie_util::StorageAccessResult::ACCESS_BLOCKED; } + // A version of above that considers Top-Level Storage Access API grant + // instead of Storage Access API grant, and user force allow to allow cookie + // access. net::cookie_util::StorageAccessResult BlockedStorageAccessResultWithTopLevelOverride() const { - if (IsStorageAccessAPIEnabled()) { + // TODO(crbug.com/1385156): Check TopLevelStorageAccessAPI instead after + // separating the feature flag. + if (IsStorageAccessAPIEnabled() && IsTopLevelStorageAccessGrantEligible()) { + // TODO(crbug.com/1385156): Separate metrics between StorageAccessAPI + // and the page-level variant. return net::cookie_util::StorageAccessResult:: ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT; } @@ -766,9 +796,9 @@ // grants. TODO(crbug.com/1385156): as requirements for the two APIs solidify, // this will likely not continue to be true. TEST_P(CookieSettingsTest, GetCookieSettingTopLevelStorageAccess) { - const GURL top_level_url = GURL(kFirstPartySite); - const GURL url = GURL(kAllowedSite); - const GURL third_url = GURL(kBlockedSite); + const GURL top_level_url(kFirstPartySite); + const GURL url(kAllowedSite); + const GURL third_url(kBlockedSite); base::HistogramTester histogram_tester; histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0); @@ -784,7 +814,7 @@ EXPECT_EQ(cookie_settings_->GetCookieSetting(url, top_level_url, GetCookieSettingOverrides(), nullptr, QueryReason::kCookies), - SettingWithEitherOverride()); + SettingWithEitherOverrideForTopLevel()); histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1); histogram_tester.ExpectBucketCount( kAllowedRequestsHistogram, @@ -1107,10 +1137,14 @@ /* no prefix */, CookieSettingsTest, testing::ValuesIn<TestCase>({ - {"disable_SAA", false, false}, - {"enable_SAA", true, false}, - {"disable_SAA_force_3PCs", false, true}, - {"enable_SAA_force_3PCs", true, true}, + {"disable_all", false, false, false}, + {"disable_SAA_disable_TopLevel_force_3PCs", false, false, true}, + {"disable_SAA_enable_TopLevel", false, true, false}, + {"disable_SAA_enable_TopLevel_force_3PCs", false, true, true}, + {"enable_SAA_disable_TopLevel", true, false, false}, + {"enable_SAA_disable_TopLevel_force_3PCs", true, false, true}, + {"enable_SAA_enable_TopLevel", true, true, false}, + {"enable_all", true, true, true}, }), [](const testing::TestParamInfo<CookieSettingsTest::ParamType>& info) { return info.param.test_name; @@ -1121,10 +1155,14 @@ /* no prefix */, CookieSettingsTestSandboxV4Enabled, testing::ValuesIn<TestCase>({ - {"disable_SAA", false, false}, - {"enable_SAA", true, false}, - {"disable_SAA_force_3PCs", false, true}, - {"enable_SAA_force_3PCs", true, true}, + {"disable_all", false, false, false}, + {"disable_SAA_disable_TopLevel_force_3PCs", false, false, true}, + {"disable_SAA_enable_TopLevel", false, true, false}, + {"disable_SAA_enable_TopLevel_force_3PCs", false, true, true}, + {"enable_SAA_disable_TopLevel", true, false, false}, + {"enable_SAA_disable_TopLevel_force_3PCs", true, false, true}, + {"enable_SAA_enable_TopLevel", true, true, false}, + {"enable_all", true, true, true}, }), [](const testing::TestParamInfo<CookieSettingsTest::ParamType>& info) { return info.param.test_name;
diff --git a/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java b/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java index a13e1801..0670d29 100644 --- a/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java +++ b/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java
@@ -39,7 +39,11 @@ public static final String PRODUCT = "prod"; public static final String ANDROID_BUILD_ID = "android_build_id"; public static final String ANDROID_BUILD_FP = "android_build_fp"; + // android-sdk-int and sdk are expected to have the same value. + // android-sdk-int is needed for compatibility with the C++ crashpad implementation. + // sdk should be maintained for potential custom monitoring. public static final String SDK = "sdk"; + public static final String ANDROID_SDK_INT = "android-sdk-int"; public static final String DEVICE = "device"; public static final String GMS_CORE_VERSION = "gms_core_version"; public static final String INSTALLER_PACKAGE_NAME = "installer_package_name"; @@ -132,7 +136,11 @@ addPairedString(BRAND, Build.BRAND); addPairedString(BOARD, Build.BOARD); addPairedString(ANDROID_BUILD_FP, buildInfo.androidBuildFingerprint); + // ANDROID_SDK_INT and SDK are expected to have the same value. + // ANDROID_SDK_INT is needed for compatibility with the C++ crashpad implementation. + // SDK should be maintained for potential custom monitoring. addPairedString(SDK, String.valueOf(Build.VERSION.SDK_INT)); + addPairedString(ANDROID_SDK_INT, String.valueOf(Build.VERSION.SDK_INT)); addPairedString(GMS_CORE_VERSION, buildInfo.gmsVersionCode); addPairedString(INSTALLER_PACKAGE_NAME, buildInfo.installerPackageName); addPairedString(ABI_NAME, buildInfo.abiString);
diff --git a/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java b/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java index 0d96aabf..5f76623 100644 --- a/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java +++ b/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java
@@ -73,8 +73,8 @@ private static final String[] REPORT_FIELDS = {PureJavaExceptionReporter.CHANNEL, PureJavaExceptionReporter.VERSION, PureJavaExceptionReporter.PRODUCT, PureJavaExceptionReporter.ANDROID_BUILD_ID, PureJavaExceptionReporter.ANDROID_BUILD_FP, - PureJavaExceptionReporter.SDK, PureJavaExceptionReporter.DEVICE, - PureJavaExceptionReporter.GMS_CORE_VERSION, + PureJavaExceptionReporter.SDK, PureJavaExceptionReporter.ANDROID_SDK_INT, + PureJavaExceptionReporter.DEVICE, PureJavaExceptionReporter.GMS_CORE_VERSION, PureJavaExceptionReporter.INSTALLER_PACKAGE_NAME, PureJavaExceptionReporter.ABI_NAME, PureJavaExceptionReporter.PACKAGE, PureJavaExceptionReporter.MODEL, PureJavaExceptionReporter.BRAND, PureJavaExceptionReporter.BOARD,
diff --git a/components/cronet/tools/generate_javadoc.py b/components/cronet/tools/generate_javadoc.py index 1f10311..556067c 100755 --- a/components/cronet/tools/generate_javadoc.py +++ b/components/cronet/tools/generate_javadoc.py
@@ -25,8 +25,11 @@ DOCLAVA_DIR = os.path.join(REPOSITORY_ROOT, 'buildtools', 'android', 'doclava') SDK_DIR = os.path.join(REPOSITORY_ROOT, 'third_party', 'android_sdk', 'public') -JAVADOC_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'javadoc') -JAR_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'jar') +# TODO(b/260694901) Remove this usage of Java 11 as soon as Doclava supports it. +# Doclava support for JDK17 was actively being worked on as of Jan 2023. +JAVADOC_PATH = os.path.join(build_utils.JAVA_11_HOME_DEPRECATED, 'bin', + 'javadoc') +JAR_PATH = os.path.join(build_utils.JAVA_11_HOME_DEPRECATED, 'bin', 'jar') JAVADOC_WARNING = """\ javadoc: warning - The old Doclet and Taglet APIs in the packages
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 29931ca..aed8dcc 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -280,6 +280,7 @@ "test/wayland_server_test.h", "test/wayland_server_test_base.cc", "test/wayland_server_test_base.h", + "wayland_aura_shell_server_test.cc", "wayland_display_observer_unittest.cc", "wayland_display_util_unittest.cc", "wayland_keyboard_delegate_unittest.cc",
diff --git a/components/exo/wayland/test/integration/buffer_checker_test.cc b/components/exo/wayland/test/integration/buffer_checker_test.cc index 8edad36..7679ebc 100644 --- a/components/exo/wayland/test/integration/buffer_checker_test.cc +++ b/components/exo/wayland/test/integration/buffer_checker_test.cc
@@ -63,7 +63,7 @@ explicit BufferCheckerTestClient() = default; ~BufferCheckerTestClient() override = default; - bool HasAnySupportedUsages(uint32_t format) { + int GetNumSupportedUsages(uint32_t format) { std::vector<gfx::BufferUsage> supported_usages; bool callback_pending = false; std::unique_ptr<wl_callback> frame_callback; @@ -88,7 +88,7 @@ if (wl_display_get_error(display_.get())) { LOG(ERROR) << "Wayland error encountered"; - return false; + return -1; } // Buffers may fail to be created, so loop until we get one or return @@ -105,7 +105,7 @@ << DrmCodeToBufferFormatString(format) << " gfx::BufferUsages: [" << base::JoinString(supported_usage_strings, ", ") << "]"; - return supported_usages.size() > 0; + return supported_usages.size(); } current_usage = usages_to_test.front(); @@ -145,11 +145,11 @@ LOG(ERROR) << "Expected to return from inside the loop. Wayland disconnected?"; - return false; + return -1; } - bool FormatAndModifierSupported(uint32_t format, - std::vector<uint64_t> modifiers) { + int GetNumSupportedFormatsAndModifier(uint32_t format, + std::vector<uint64_t> modifiers) { std::vector<gfx::BufferUsage> supported_usages; bool callback_pending = false; std::unique_ptr<wl_callback> frame_callback; @@ -169,12 +169,12 @@ << " drm modifiers: " << DrmModifiersToString(modifiers) << " gfx::BufferFormat: " << DrmCodeToBufferFormatString(format); - return true; + return 1; } if (wl_display_get_error(display_.get())) { LOG(ERROR) << "Wayland error encountered"; - return false; + return -1; } if (modifiers.size() == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { @@ -195,7 +195,7 @@ << " drm modifiers: " << DrmModifiersToString(modifiers) << " gfx::BufferFormat: " << DrmCodeToBufferFormatString(format); - return false; + return 0; } LOG(INFO) << "Attempting to use buffer with format drm format: " @@ -219,7 +219,7 @@ LOG(ERROR) << "Expected to return from inside the loop. Wayland disconnected?"; - return false; + return -1; } std::vector<uint32_t> reported_formats; @@ -460,7 +460,7 @@ << base::JoinString(buffer_names, ", "); } -TEST_F(BufferCheckerClientTest, CanUseAllReportedBufferFormatsLegacy) { +TEST_F(BufferCheckerClientTest, CanUseAnyReportedBufferFormatsLegacy) { exo::wayland::test::BufferCheckerTestClient client; auto params = base_params_; // Initialize no buffers when we start, wait until we've gotten the list @@ -471,8 +471,15 @@ EXPECT_TRUE(!client.reported_formats.empty()); PrintReportedFormats(client.reported_formats); - for (auto format : client.reported_formats) - EXPECT_TRUE(client.HasAnySupportedUsages(format)); + bool has_any_supported_formats = false; + for (auto format : client.reported_formats) { + int res = client.GetNumSupportedUsages(format); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } + EXPECT_TRUE(has_any_supported_formats); } TEST_F(BufferCheckerClientTest, CanUseAnyReportedBufferModifiersLegacy) { @@ -484,35 +491,36 @@ ASSERT_TRUE(client.Init(params)); EXPECT_TRUE(!client.reported_format_modifier_map.empty()); + bool has_any_supported_formats = false; for (const auto& [format, modifiers] : client.reported_format_modifier_map) { std::vector<uint64_t> valid_modifiers; for (uint64_t modifier : modifiers) { if (modifier != DRM_FORMAT_MOD_INVALID) valid_modifiers.push_back(modifier); } - if (valid_modifiers.empty()) - valid_modifiers.push_back(DRM_FORMAT_MOD_INVALID); - EXPECT_TRUE(client.FormatAndModifierSupported(format, valid_modifiers)); - } -} -TEST_F(BufferCheckerClientTest, CanUseAllReportedBufferModifiersLegacy) { - exo::wayland::test::BufferCheckerTestClient client; - auto params = base_params_; - // Initialize no buffers when we start, wait until we've gotten the list - params.num_buffers = 0; - params.linux_dmabuf_version = ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION; - ASSERT_TRUE(client.Init(params)); - EXPECT_TRUE(!client.reported_format_modifier_map.empty()); + if (!valid_modifiers.empty()) { + int res = + client.GetNumSupportedFormatsAndModifier(format, valid_modifiers); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } - for (const auto& [format, modifiers] : client.reported_format_modifier_map) { - for (auto modifier : modifiers) { - EXPECT_TRUE(client.FormatAndModifierSupported(format, {modifier})); + if (base::Contains(modifiers, DRM_FORMAT_MOD_INVALID)) { + int res = client.GetNumSupportedFormatsAndModifier( + format, std::vector<uint64_t>({DRM_FORMAT_MOD_INVALID})); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } } } + EXPECT_TRUE(has_any_supported_formats); } -TEST_F(BufferCheckerClientTest, CanUseAllReportedBufferFormatsDefaultFeedback) { +TEST_F(BufferCheckerClientTest, CanUseAnyReportedBufferFormatsDefaultFeedback) { exo::wayland::test::BufferCheckerTestClient client; auto params = base_params_; // Initialize no buffers when we start, wait until we've gotten the list @@ -526,8 +534,15 @@ EXPECT_TRUE(!client.reported_format_modifier_map.empty()); PrintReportedFormats(client.reported_formats); - for (auto format : client.reported_formats) - EXPECT_TRUE(client.HasAnySupportedUsages(format)); + bool has_any_supported_formats = false; + for (auto format : client.reported_formats) { + int res = client.GetNumSupportedUsages(format); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } + EXPECT_TRUE(has_any_supported_formats); } TEST_F(BufferCheckerClientTest, @@ -544,40 +559,36 @@ client.GetDefaultFeedback(); EXPECT_TRUE(!client.reported_format_modifier_map.empty()); + bool has_any_supported_formats = false; for (const auto& [format, modifiers] : client.reported_format_modifier_map) { std::vector<uint64_t> valid_modifiers; for (uint64_t modifier : modifiers) { if (modifier != DRM_FORMAT_MOD_INVALID) valid_modifiers.push_back(modifier); } - if (valid_modifiers.empty()) - valid_modifiers.push_back(DRM_FORMAT_MOD_INVALID); - EXPECT_TRUE(client.FormatAndModifierSupported(format, valid_modifiers)); - } -} -TEST_F(BufferCheckerClientTest, - CanUseAllReportedBufferModifiersDefaultFeedback) { - exo::wayland::test::BufferCheckerTestClient client; - auto params = base_params_; - // Initialize no buffers when we start, wait until we've gotten the list - params.num_buffers = 0; - params.linux_dmabuf_version = - ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION; - ASSERT_TRUE(client.Init(params)); + if (!valid_modifiers.empty()) { + int res = + client.GetNumSupportedFormatsAndModifier(format, valid_modifiers); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } - EXPECT_TRUE(client.reported_format_modifier_map.empty()); - client.GetDefaultFeedback(); - EXPECT_TRUE(!client.reported_format_modifier_map.empty()); - - for (const auto& [format, modifiers] : client.reported_format_modifier_map) { - for (auto modifier : modifiers) { - EXPECT_TRUE(client.FormatAndModifierSupported(format, {modifier})); + if (base::Contains(modifiers, DRM_FORMAT_MOD_INVALID)) { + int res = client.GetNumSupportedFormatsAndModifier( + format, std::vector<uint64_t>({DRM_FORMAT_MOD_INVALID})); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } } } + EXPECT_TRUE(has_any_supported_formats); } -TEST_F(BufferCheckerClientTest, CanUseAllReportedBufferFormatsSurfaceFeedback) { +TEST_F(BufferCheckerClientTest, CanUseAnyReportedBufferFormatsSurfaceFeedback) { exo::wayland::test::BufferCheckerTestClient client; auto params = base_params_; // Initialize no buffers when we start, wait until we've gotten the list @@ -591,8 +602,15 @@ EXPECT_TRUE(!client.reported_format_modifier_map.empty()); PrintReportedFormats(client.reported_formats); - for (auto format : client.reported_formats) - EXPECT_TRUE(client.HasAnySupportedUsages(format)); + bool has_any_supported_formats = false; + for (auto format : client.reported_formats) { + int res = client.GetNumSupportedUsages(format); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } + EXPECT_TRUE(has_any_supported_formats); } TEST_F(BufferCheckerClientTest, @@ -609,35 +627,31 @@ client.GetSurfaceFeedback(); EXPECT_TRUE(!client.reported_format_modifier_map.empty()); + bool has_any_supported_formats = false; for (const auto& [format, modifiers] : client.reported_format_modifier_map) { std::vector<uint64_t> valid_modifiers; for (uint64_t modifier : modifiers) { if (modifier != DRM_FORMAT_MOD_INVALID) valid_modifiers.push_back(modifier); } - if (valid_modifiers.empty()) - valid_modifiers.push_back(DRM_FORMAT_MOD_INVALID); - EXPECT_TRUE(client.FormatAndModifierSupported(format, valid_modifiers)); - } -} -TEST_F(BufferCheckerClientTest, - CanUseAllReportedBufferModifiersSurfaceFeedback) { - exo::wayland::test::BufferCheckerTestClient client; - auto params = base_params_; - // Initialize no buffers when we start, wait until we've gotten the list - params.num_buffers = 0; - params.linux_dmabuf_version = - ZWP_LINUX_DMABUF_V1_GET_SURFACE_FEEDBACK_SINCE_VERSION; - ASSERT_TRUE(client.Init(params)); + if (!valid_modifiers.empty()) { + int res = + client.GetNumSupportedFormatsAndModifier(format, valid_modifiers); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } + } - EXPECT_TRUE(client.reported_format_modifier_map.empty()); - client.GetSurfaceFeedback(); - EXPECT_TRUE(!client.reported_format_modifier_map.empty()); - - for (const auto& [format, modifiers] : client.reported_format_modifier_map) { - for (auto modifier : modifiers) { - EXPECT_TRUE(client.FormatAndModifierSupported(format, {modifier})); + if (base::Contains(modifiers, DRM_FORMAT_MOD_INVALID)) { + int res = client.GetNumSupportedFormatsAndModifier( + format, std::vector<uint64_t>({DRM_FORMAT_MOD_INVALID})); + EXPECT_TRUE(res != -1); + if (res > 0) { + has_any_supported_formats = true; + } } } + EXPECT_TRUE(has_any_supported_formats); }
diff --git a/components/exo/wayland/wayland_aura_shell_server_test.cc b/components/exo/wayland/wayland_aura_shell_server_test.cc new file mode 100644 index 0000000..fe2fc74 --- /dev/null +++ b/components/exo/wayland/wayland_aura_shell_server_test.cc
@@ -0,0 +1,189 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include <wayland-server-protocol-core.h> +#include "components/exo/display.h" +#include "components/exo/wayland/test/client_util.h" +#include "components/exo/wayland/test/server_util.h" +#include "components/exo/wayland/test/wayland_server_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace exo::wayland { +namespace { + +class ClientData : public test::TestClient::CustomData { + public: + std::unique_ptr<wl_surface> surface; + std::unique_ptr<wl_surface> surface2; +}; + +class WaylandAuraShellServerTest : public test::WaylandServerTest { + public: + WaylandAuraShellServerTest() = default; + + WaylandAuraShellServerTest(const WaylandAuraShellServerTest&) = delete; + WaylandAuraShellServerTest& operator=(const WaylandAuraShellServerTest&) = + delete; + + ~WaylandAuraShellServerTest() override = default; + + // test::WaylandServerTest: + void SetUp() override { + WaylandServerTest::SetUp(); + display_ = server_->GetDisplay(); + } + + void TearDown() override { WaylandServerTest::TearDown(); } + + void OnAuraShellActivated(zaura_shell*, + wl_surface* gained_active, + wl_surface* lost_active) { + gained_active_ = gained_active; + lost_active_ = lost_active; + activated_call_count_++; + } + + void SetupClientSurface() { + PostToClientAndWait([&](test::TestClient* client) { + zaura_shell_add_listener(client->aura_shell(), &kAuraShellListener, this); + auto data = std::make_unique<ClientData>(); + data->surface.reset(wl_compositor_create_surface(client->compositor())); + + surface_key_ = test::client_util::GetResourceKey(data->surface.get()); + client->set_data(std::move(data)); + }); + } + + void SetupMultipleClientSurfaces() { + PostToClientAndWait([&](test::TestClient* client) { + zaura_shell_add_listener(client->aura_shell(), &kAuraShellListener, this); + auto data = std::make_unique<ClientData>(); + data->surface.reset(wl_compositor_create_surface(client->compositor())); + data->surface2.reset(wl_compositor_create_surface(client->compositor())); + + surface_key_ = test::client_util::GetResourceKey(data->surface.get()); + surface_key2_ = test::client_util::GetResourceKey(data->surface2.get()); + client->set_data(std::move(data)); + }); + } + + Surface* GetClientSurface(test::ResourceKey surface_key) { + return test::server_util::GetUserDataForResource<Surface>(server_.get(), + surface_key); + } + + const zaura_shell_listener kAuraShellListener = { + [](void* data, struct zaura_shell* zaura_shell, uint32_t layout_mode) {}, + [](void* data, struct zaura_shell* zaura_shell, uint32_t id) {}, + [](void* data, + struct zaura_shell* zaura_shell, + struct wl_array* desk_names) {}, + [](void* data, + struct zaura_shell* zaura_shell, + int32_t active_desk_index) {}, + [](void* data, + struct zaura_shell* zaura_shell, + struct wl_surface* gained_active, + struct wl_surface* lost_active) { + static_cast<WaylandAuraShellServerTest*>(data)->OnAuraShellActivated( + zaura_shell, gained_active, lost_active); + }}; + + Display* display_; + wl_surface* gained_active_ = nullptr; + wl_surface* lost_active_ = nullptr; + int32_t activated_call_count_ = 0; + + test::ResourceKey surface_key_; + test::ResourceKey surface_key2_; +}; + +// Home screen -> any window +TEST_F(WaylandAuraShellServerTest, HasFocusedClientChangedSendActivated) { + SetupClientSurface(); + Surface* surface = GetClientSurface(surface_key_); + ASSERT_TRUE(surface); + + display_->seat()->OnWindowFocused(surface->window(), nullptr); + // Wait until all wayland events are sent. + PostToClientAndWait([]() {}); + EXPECT_TRUE(gained_active_ != nullptr); + EXPECT_TRUE(lost_active_ == nullptr); + EXPECT_EQ(1, activated_call_count_); +} + +// Exo client window -> Same exo client another window +TEST_F(WaylandAuraShellServerTest, FocusedClientChangedSendActivated) { + SetupMultipleClientSurfaces(); + Surface* surface = GetClientSurface(surface_key_); + ASSERT_TRUE(surface); + + display_->seat()->OnWindowFocused(surface->window(), nullptr); + // Reset previous gained and lost active info. + gained_active_ = nullptr; + lost_active_ = nullptr; + + Surface* surface2 = GetClientSurface(surface_key2_); + ASSERT_TRUE(surface2); + display_->seat()->OnWindowFocused(surface2->window(), surface->window()); + // Wait until all wayland events are sent. + PostToClientAndWait([]() {}); + + EXPECT_TRUE(gained_active_ != nullptr); + EXPECT_TRUE(lost_active_ != nullptr); + EXPECT_EQ(2, activated_call_count_); +} + +// Exo client window -> Chrome window +TEST_F(WaylandAuraShellServerTest, FocusedClientChangedToNonExoSendActivated) { + SetupMultipleClientSurfaces(); + Surface* surface = GetClientSurface(surface_key_); + ASSERT_TRUE(surface); + display_->seat()->OnWindowFocused(surface->window(), nullptr); + + // Reset previous gained and lost active info. + gained_active_ = nullptr; + lost_active_ = nullptr; + + Surface* surface2 = GetClientSurface(surface_key2_); + ASSERT_TRUE(surface2); + // Chrome surface doesn't have wayland resource. + SetSurfaceResource(surface2, nullptr); + display_->seat()->OnWindowFocused(surface2->window(), surface->window()); + // Wait until all wayland events are sent. + PostToClientAndWait([]() {}); + + EXPECT_TRUE(gained_active_ == nullptr); + EXPECT_TRUE(lost_active_ != nullptr); + EXPECT_EQ(2, activated_call_count_); +} + +// Chrome window -> Chrome window +TEST_F(WaylandAuraShellServerTest, + NonExoFocusedClientChangedNotSendingActivated) { + SetupMultipleClientSurfaces(); + Surface* surface = GetClientSurface(surface_key_); + ASSERT_TRUE(surface); + // Chrome surface doesn't have wayland resource. + SetSurfaceResource(surface, nullptr); + display_->seat()->OnWindowFocused(surface->window(), nullptr); + + // Reset previous gained and lost active info. + gained_active_ = nullptr; + lost_active_ = nullptr; + + Surface* surface2 = GetClientSurface(surface_key2_); + ASSERT_TRUE(surface2); + // Chrome surface doesn't have wayland resource. + SetSurfaceResource(surface2, nullptr); + display_->seat()->OnWindowFocused(surface2->window(), surface->window()); + // Wait until all wayland events are sent. + PostToClientAndWait([]() {}); + + EXPECT_EQ(nullptr, gained_active_); + EXPECT_EQ(nullptr, lost_active_); + EXPECT_EQ(1, activated_call_count_); +} + +} // namespace +} // namespace exo::wayland
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc index b4a9db38..ec5716c 100644 --- a/components/exo/wayland/zaura_shell.cc +++ b/components/exo/wayland/zaura_shell.cc
@@ -1205,10 +1205,6 @@ if (wl_resource_get_version(aura_shell_resource_) < ZAURA_SHELL_ACTIVATED_SINCE_VERSION) return; - if (gained_active_surface == lost_active_surface && - last_has_focused_client_ == has_focused_client) - return; - last_has_focused_client_ = has_focused_client; wl_resource* gained_active_surface_resource = gained_active_surface ? GetSurfaceResource(gained_active_surface) @@ -1232,6 +1228,12 @@ lost_active_surface_resource = nullptr; } + if (gained_active_surface_resource == lost_active_surface_resource && + last_has_focused_client_ == has_focused_client) { + return; + } + last_has_focused_client_ = has_focused_client; + zaura_shell_send_activated(aura_shell_resource_, gained_active_surface_resource, lost_active_surface_resource);
diff --git a/components/external_intents/android/external_intents_features.cc b/components/external_intents/android/external_intents_features.cc index 8f695d6..a2e5fe28 100644 --- a/components/external_intents/android/external_intents_features.cc +++ b/components/external_intents/android/external_intents_features.cc
@@ -19,7 +19,7 @@ // Array of features exposed through the Java ExternalIntentsFeatures API. const base::Feature* kFeaturesExposedToJava[] = { &kBlockExternalFormSubmitWithoutGesture, &kExternalNavigationDebugLogs, - &kExternalNavigationSubframeRedirects}; + &kExternalNavigationSubframeRedirects, &kBlockSubframeIntentToSelf}; } // namespace @@ -39,6 +39,10 @@ "ExternalNavigationSubframeRedirects", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kBlockSubframeIntentToSelf, + "BlockSubframeIntentToSelf", + base::FEATURE_ENABLED_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 bab62ff..1308e555 100644 --- a/components/external_intents/android/external_intents_features.h +++ b/components/external_intents/android/external_intents_features.h
@@ -13,7 +13,7 @@ BASE_DECLARE_FEATURE(kBlockExternalFormSubmitWithoutGesture); BASE_DECLARE_FEATURE(kExternalNavigationDebugLogs); BASE_DECLARE_FEATURE(kExternalNavigationSubframeRedirects); - +BASE_DECLARE_FEATURE(kBlockSubframeIntentToSelf); } // namespace external_intents #endif // COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURES_H_
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 fddd0dd0..b52ed57 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
@@ -22,6 +22,7 @@ public static final String EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME = "ExternalNavigationDebugLogs"; public static final String EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME = "ExternalNavigationSubframeRedirects"; + public static final String BLOCK_SUBFRAME_INTENT_TO_SELF_NAME = "BlockSubframeIntentToSelf"; public static final ExternalIntentsFeatures BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE = new ExternalIntentsFeatures(0, BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE_NAME); @@ -32,6 +33,9 @@ public static final ExternalIntentsFeatures EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS = new ExternalIntentsFeatures(2, EXTERNAL_NAVIGATION_SUBFRAME_REDIRECTS_NAME); + public static final ExternalIntentsFeatures BLOCK_SUBFRAME_INTENT_TO_SELF = + new ExternalIntentsFeatures(3, BLOCK_SUBFRAME_INTENT_TO_SELF_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 3bb3073..c100cea 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
@@ -8,8 +8,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.Intent.ShortcutIconResource; import android.content.IntentFilter; @@ -76,7 +74,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -272,8 +269,6 @@ } } - private final ExternalNavigationDelegate mDelegate; - /** * Result types for checking if we should override URL loading. * NOTE: this enum is used in UMA, do not reorder values. Changes should be append only. @@ -433,6 +428,9 @@ } } + private final ExternalNavigationDelegate mDelegate; + private AlertDialog mIncognitoAlertDialog; + /** * Constructs a new instance of {@link ExternalNavigationHandler}, using the injected * {@link ExternalNavigationDelegate}. @@ -1108,6 +1106,28 @@ return OverrideUrlLoadingResult.forNoOverride(); } + private boolean isSubframeNavigationToSelf(ExternalNavigationParams params, + QueryIntentActivitiesSupplier resolvingInfos, ResolveActivitySupplier resolveActivity) { + if (!ExternalIntentsFeatures.BLOCK_SUBFRAME_INTENT_TO_SELF.isEnabled()) return false; + if (params.isMainFrame()) return false; + if (!resolveInfoContainsSelf(resolvingInfos.get())) return false; + if (resolveActivity.get() == null) return false; + + ActivityInfo info = resolveActivity.get().activityInfo; + if (info != null && mDelegate.getContext().getPackageName().equals(info.packageName)) { + if (debug()) Log.i(TAG, "Subframe navigation to self."); + return true; + } + + // We don't want the user seeing the chooser and choosing the browser, but resolving to + // another app is fine. + if (resolvesToChooser(resolveActivity.get(), resolvingInfos)) { + if (debug()) Log.i(TAG, "Subframe navigation to chooser including self."); + return true; + } + return false; + } + /** * Returns true if the intent is an insecure intent targeting browsers or browser-like apps * (excluding the embedding app). @@ -1277,8 +1297,8 @@ } try { - AlertDialog dialog = showLeavingIncognitoAlert(context, params, intent, fallbackUrl); - return dialog != null; + mIncognitoAlertDialog = showLeavingIncognitoAlert(context, params, intent, fallbackUrl); + return mIncognitoAlertDialog != null; } catch (BadTokenException e) { return false; } @@ -1301,28 +1321,20 @@ .setTitle(R.string.external_app_leave_incognito_warning_title) .setMessage(R.string.external_app_leave_incognito_warning) .setPositiveButton(R.string.external_app_leave_incognito_leave, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - onUserDecidedWhetherToLaunchIncognitoIntent( - /*shouldLaunch=*/true, params, intent, fallbackUrl); - } + (DialogInterface dialog, int which) -> { + onUserDecidedWhetherToLaunchIncognitoIntent( + /*shouldLaunch=*/true, params, intent, fallbackUrl); }) .setNegativeButton(R.string.external_app_leave_incognito_stay, - new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - onUserDecidedWhetherToLaunchIncognitoIntent( - /*shouldLaunch=*/false, params, intent, fallbackUrl); - } + (DialogInterface dialog, int which) -> { + onUserDecidedWhetherToLaunchIncognitoIntent( + /*shouldLaunch=*/false, params, intent, fallbackUrl); }) - .setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - onUserDecidedWhetherToLaunchIncognitoIntent( - /*shouldLaunch=*/false, params, intent, fallbackUrl); - } + .setOnCancelListener((DialogInterface dialog) -> { + onUserDecidedWhetherToLaunchIncognitoIntent( + /*shouldLaunch=*/false, params, intent, fallbackUrl); }) + .setOnDismissListener((DialogInterface dialog) -> { mIncognitoAlertDialog = null; }) .show(); } @@ -1440,6 +1452,11 @@ recordIntentSelectorMetrics(params.getUrl(), targetIntent); sanitizeQueryIntentActivitiesIntent(targetIntent); + // Any subsequent navigations should cancel the existing AlertDialog. + if (mIncognitoAlertDialog != null && mIncognitoAlertDialog.isShowing()) { + mIncognitoAlertDialog.cancel(); + } + // Don't allow external fallback URLs by default. canLaunchExternalFallbackResult.set(false); @@ -1533,6 +1550,11 @@ return OverrideUrlLoadingResult.forNoOverride(); } + ResolveActivitySupplier resolveActivity = new ResolveActivitySupplier(targetIntent); + if (isSubframeNavigationToSelf(params, resolvingInfos, resolveActivity)) { + return OverrideUrlLoadingResult.forNavigateTab(intentDataUrl, params); + } + boolean hasSpecializedHandler = countSpecializedHandlers(resolvingInfos.get()) > 0; if (!isExternalProtocol && !hasSpecializedHandler && !intentMatchesNonDefaultWebApk) { return fallBackToHandlingInApp(); @@ -1564,7 +1586,6 @@ return OverrideUrlLoadingResult.forExternalIntent(); } - ResolveActivitySupplier resolveActivity = new ResolveActivitySupplier(targetIntent); boolean requiresIntentChooser = false; if (!mDelegate.maybeSetTargetPackage(targetIntent, resolvingInfos)) { requiresIntentChooser = isInsecureIntentToOtherBrowser(targetIntent, resolvingInfos, @@ -1612,13 +1633,7 @@ if (resolveActivity == null) return true; - List<ResolveInfo> possibleHandlingActivities = resolvingInfosSupplier.get(); - - // If resolveActivity is contained in possibleHandlingActivities, that means the Intent - // would launch a specialized Activity. If not, that means the Intent will launch the - // Android disambiguation prompt. - boolean result = !resolversSubsetOf( - Collections.singletonList(resolveActivity), possibleHandlingActivities); + boolean result = resolvesToChooser(resolveActivity, resolvingInfosSupplier); if (debug() && result) Log.i(TAG, "Avoiding disambiguation dialog."); return result; } @@ -1977,6 +1992,13 @@ return OverrideUrlLoadingResult.forExternalIntent(); } + // If the |resolvingInfos| from queryIntentActivities don't contain the result of + // resolveActivity, it means the intent is resolving to the ResolverActivity. + private boolean resolvesToChooser( + @NonNull ResolveInfo resolveActivity, QueryIntentActivitiesSupplier resolvingInfos) { + return !resolversSubsetOf(Arrays.asList(resolveActivity), resolvingInfos.get()); + } + // looking up resources from other apps requires the use of getIdentifier() @SuppressWarnings({"UseCompatLoadingForDrawables", "DiscouragedApi"}) private OverrideUrlLoadingResult startActivityWithChooser(final Intent intent, @@ -1988,12 +2010,11 @@ // non-default filters, so just drop it. if (intentResolveInfo == null) return OverrideUrlLoadingResult.forNoOverride(); - // If the |resolvingInfos| from queryIntentActivities don't contain the result of - // resolveActivity, it means the intent is resolving to the ResolverActivity, so the user - // will already get the option to choose the target app (as there will be multiple options) - // and we don't need to do anything. Otherwise we have to make a fake option in the chooser - // dialog that loads the URL in the embedding app. - if (!resolversSubsetOf(Arrays.asList(intentResolveInfo), resolvingInfos.get())) { + // If we resolve to the Chooser Activity, the user will already get the option to choose the + // target app (as there will be multiple options) and we don't need to do anything. + // Otherwise we have to make a fake option in the chooser dialog that loads the URL in the + // embedding app. + if (resolvesToChooser(intentResolveInfo, resolvingInfos)) { return doStartActivity(intent, context); } @@ -2107,7 +2128,7 @@ // when the external navigation was otherwise blocked. In this case, we should just continue // to block the navigation, and sites hoping to prompt the user when navigation fails should // make sure to correctly target their app. - if (!resolversSubsetOf(Arrays.asList(intentResolveInfo), resolvingInfos.get())) { + if (resolvesToChooser(intentResolveInfo, resolvingInfos)) { if (debug()) Log.i(TAG, "Message resolves to multiple apps."); return OverrideUrlLoadingResult.forNoOverride(); }
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java index caceda69..051b6cf 100644 --- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java +++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -36,6 +36,7 @@ import org.junit.rules.TestRule; 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.mockito.quality.Strictness; @@ -72,12 +73,11 @@ * Instrumentation tests for {@link ExternalNavigationHandler}. */ @RunWith(BaseJUnit4ClassRunner.class) -// clang-format off @Batch(Batch.UNIT_TESTS) @Features.DisableFeatures(ExternalIntentsFeatures.EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME) -@Features.EnableFeatures(ExternalIntentsFeatures.BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE_NAME) +@Features.EnableFeatures({ExternalIntentsFeatures.BLOCK_EXTERNAL_FORM_SUBMIT_WITHOUT_GESTURE_NAME, + ExternalIntentsFeatures.BLOCK_SUBFRAME_INTENT_TO_SELF_NAME}) public class ExternalNavigationHandlerTest { - // clang-format on // Expectations private static final int IGNORE = 0x0; private static final int START_INCOGNITO = 0x1; @@ -1222,7 +1222,7 @@ // Inform the handler that the user decided not to launch the intent and verify that // the appropriate URL is navigated to in the browser. - mDelegate.incognitoDialogUserDecisionCallback.onResult(new Boolean(false)); + mDelegate.incognitoDialogUserDecisionCallback.onResult(Boolean.valueOf(false)); Assert.assertEquals(playUrl, mUrlHandler.mNewUrlAfterClobbering); mUrlHandler.mNewUrlAfterClobbering = null; mDelegate.incognitoDialogUserDecisionCallback = null; @@ -1240,7 +1240,7 @@ // Inform the handler that the user decided to launch the intent and verify that // the intent was launched. - mDelegate.incognitoDialogUserDecisionCallback.onResult(new Boolean(true)); + mDelegate.incognitoDialogUserDecisionCallback.onResult(Boolean.valueOf(true)); Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering); Assert.assertEquals(1, monitor.getHits()); Assert.assertEquals("market://details?id=com.imdb.mobile&referrer=mypage", @@ -1284,7 +1284,7 @@ // Inform the handler that the user decided not to launch the intent and verify that // the appropriate URL is navigated to in the browser. - mDelegate.incognitoDialogUserDecisionCallback.onResult(new Boolean(false)); + mDelegate.incognitoDialogUserDecisionCallback.onResult(Boolean.valueOf(false)); Assert.assertEquals("https://example.com/", mUrlHandler.mNewUrlAfterClobbering); mUrlHandler.mNewUrlAfterClobbering = null; @@ -1304,7 +1304,7 @@ // Inform the handler that the user decided not to launch the intent and verify that // the appropriate URL is navigated to in the browser. - mDelegate.incognitoDialogUserDecisionCallback.onResult(new Boolean(false)); + mDelegate.incognitoDialogUserDecisionCallback.onResult(Boolean.valueOf(false)); Assert.assertEquals("http://google.com/", mUrlHandler.mNewUrlAfterClobbering); }); } finally { @@ -1313,6 +1313,35 @@ } @Test + @MediumTest + public void testIncognitoAlertDialogDismissedOnNavigation() { + // IMDB app is installed. + mDelegate.add(new IntentActivity("imdb:", INTENT_APP_PACKAGE_NAME)); + + mUrlHandler.mCanShowIncognitoDialog = true; + RedirectHandler redirectHandler = RedirectHandler.create(); + redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false, true); + checkUrl(INTENT_URL_WITH_FALLBACK_URL) + .withHasUserGesture(true) + .withIsIncognito(true) + .withRedirectHandler(redirectHandler) + .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION, + OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO); + Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled); + + // Callback won't have been run with the mocked AlertDialog. + mUrlHandler.mAsyncActionCallback.onResult(AsyncActionTakenParams.forNoAction()); + + Mockito.doReturn(true).when(mAlertDialog).isShowing(); + redirectHandler.updateNewUrlLoading(PageTransition.LINK, false, false, 0, 0, false, true); + checkUrl(YOUTUBE_URL) + .withIsIncognito(true) + .withRedirectHandler(redirectHandler) + .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE); + Mockito.verify(mAlertDialog).cancel(); + } + + @Test @SmallTest public void testFallbackUrl_SubframeFallbackToMarketApp() { mDelegate.setCanResolveActivityForExternalSchemes(false); @@ -2561,6 +2590,40 @@ 2, redirectHandler.getLastCommittedEntryIndexBeforeStartingNavigation()); } + private void doTestSubframeIntentTargetsSelf(boolean targetsPackage) { + mUrlHandler.mResolveInfoContainsSelf = true; + if (!targetsPackage) { + mDelegate.setWillResolveToDisambiguationDialog(true); + } + String url = "intent://www.example.com/#Intent;scheme=https;" + + "action=android.intent.action.VIEW;package=" + SELF_PACKAGE_NAME + + ";S.browser_fallback_url=https://bad.com;end"; + + RedirectHandler redirectHandler = RedirectHandler.create(); + redirectHandler.updateNewUrlLoading( + PageTransition.AUTO_SUBFRAME, false, true, 0, 0, false, true); + + checkUrl(url) + .withIsMainFrame(false) + .withHasUserGesture(true) + .withRedirectHandler(redirectHandler) + .withPageTransition(PageTransition.AUTO_SUBFRAME) + .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_NAVIGATE_TAB, IGNORE); + Assert.assertEquals("https://www.example.com/", mUrlHandler.mNewUrlAfterClobbering); + } + + @Test + @SmallTest + public void testSubframeIntentTargetsSelf_Package() { + doTestSubframeIntentTargetsSelf(true); + } + + @Test + @SmallTest + public void testSubframeIntentTargetsSelf_Chooser() { + doTestSubframeIntentTargetsSelf(false); + } + private static List<ResolveInfo> makeResolveInfos(ResolveInfo... infos) { return Arrays.asList(infos); } @@ -2718,6 +2781,7 @@ public void reset() { mStartActivityIntent = null; + mStartIncognitoIntentCalled = false; } @Override @@ -2741,7 +2805,7 @@ String dataString = intent.getDataString(); if (intent.getScheme() != null) { if (dataString.startsWith("http://") || dataString.startsWith("https://")) { - list.add(newResolveInfo("chrome")); + list.add(newResolveInfo(SELF_PACKAGE_NAME)); } for (IntentActivity intentActivity : mIntentActivities) { if (dataString.startsWith(intentActivity.urlPrefix())) {
diff --git a/components/feature_engagement/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc index 82fab36..bf5cda90 100644 --- a/components/feature_engagement/public/event_constants.cc +++ b/components/feature_engagement/public/event_constants.cc
@@ -71,11 +71,17 @@ "overflow_menu_no_horizontal_scroll_or_action"; const char kPriceNotificationsUsed[] = "price_notifications_used"; const char kDefaultBrowserPromoShown[] = "default_browser_promo_shown"; + +// Default browser blue dot promo. const char kBlueDotPromoCriterionMet[] = "blue_dot_promo_criterion_met"; const char kBlueDotPromoEligibilityMet[] = "blue_dot_promo_eligibility_met"; const char kBlueDotPromoOverflowMenuShown[] = "blue_dot_promo_overflow_menu_shown"; +const char kBlueDotPromoOverflowMenuShownNewSession[] = + "blue_dot_promo_overflow_menu_shown_new_session"; const char kBlueDotPromoSettingsShown[] = "blue_dot_promo_settings_shown"; +const char kBlueDotPromoSettingsShownNewSession[] = + "blue_dot_promo_settings_shown_new_session"; const char kBlueDotPromoOverflowMenuDismissed[] = "blue_dot_promo_overflow_menu_dismissed"; const char kBlueDotPromoSettingsDismissed[] =
diff --git a/components/feature_engagement/public/event_constants.h b/components/feature_engagement/public/event_constants.h index 41a5b78..8f91b8e1 100644 --- a/components/feature_engagement/public/event_constants.h +++ b/components/feature_engagement/public/event_constants.h
@@ -141,10 +141,18 @@ // carousel. extern const char kBlueDotPromoOverflowMenuShown[]; +// The user has been shown the blue dot default browser promo on the overflow +// carousel, for a new user session. (i.e. after 6 hours from last shown). +extern const char kBlueDotPromoOverflowMenuShownNewSession[]; + // The user has been shown the blue dot default browser promo on the settings // row. extern const char kBlueDotPromoSettingsShown[]; +// The user has been shown the blue dot default browser promo on the settings +// row, after a new user session (i.e. after 6 hours from last shown). +extern const char kBlueDotPromoSettingsShownNewSession[]; + // The user has dismissed the blue dot default browser promo on the overflow // carousel. extern const char kBlueDotPromoOverflowMenuDismissed[];
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc index e80b95a..f6525c1 100644 --- a/components/feature_engagement/public/feature_configurations.cc +++ b/components/feature_engagement/public/feature_configurations.cc
@@ -1104,7 +1104,9 @@ // (kIPHiOSDefaultBrowserOverflowMenuBadgeFeature and // kIPHiOSDefaultBrowserSettingsBadgeFeature) which will enable a blue // notification badge to be shown to users at two different locations to - // help bring their attention to the default browser settings page. + // help bring their attention to the default browser settings page. This FET + // feature is non-blocking because it is a passive promo that appears + // alongside the rest of the UI, and does not interrupt the user's flow. absl::optional<FeatureConfig> config = FeatureConfig(); config->valid = true; @@ -1116,6 +1118,8 @@ Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360); config->event_configs.insert(EventConfig("default_browser_promo_shown", Comparator(EQUAL, 0), 30, 360)); + config->blocked_by.type = BlockedBy::Type::NONE; + config->blocking.type = Blocking::Type::NONE; return config; } @@ -1123,7 +1127,9 @@ // A config to allow a user to be shown the blue dot promo on the carousel. // It depends on kIPHiOSDefaultBrowserBadgeEligibilityFeature to have deemed // users eligible, and adds more constraints to decide when to stop showing - // the promo to the user. + // the promo to the user. This FET feature is non-blocking because it is a + // passive promo that appears alongside the rest of the UI, and does not + // interrupt the user's flow. absl::optional<FeatureConfig> config = FeatureConfig(); config->valid = true; @@ -1132,12 +1138,17 @@ config->used = EventConfig("blue_dot_promo_overflow_menu_dismissed", Comparator(EQUAL, 0), 30, 360); config->trigger = EventConfig("blue_dot_promo_overflow_menu_shown", - Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360); + Comparator(ANY, 0), 360, 360); + config->event_configs.insert( + EventConfig("blue_dot_promo_overflow_menu_shown_new_session", + Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360)); config->event_configs.insert( EventConfig("blue_dot_promo_eligibility_met", Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360)); config->event_configs.insert(EventConfig("default_browser_promo_shown", Comparator(EQUAL, 0), 30, 360)); + config->blocked_by.type = BlockedBy::Type::NONE; + config->blocking.type = Blocking::Type::NONE; return config; } @@ -1146,7 +1157,9 @@ // browser settings row item. It depends on // kIPHiOSDefaultBrowserBadgeEligibilityFeature to have deemed users // eligible, and adds more constraints to decide when to stop showing the - // promo. + // promo. This FET feature is non-blocking because it is a passive promo + // that appears alongside the rest of the UI, and does not interrupt the + // user's flow. absl::optional<FeatureConfig> config = FeatureConfig(); config->valid = true; @@ -1155,12 +1168,17 @@ config->used = EventConfig("blue_dot_promo_settings_dismissed", Comparator(EQUAL, 0), 30, 360); config->trigger = EventConfig("blue_dot_promo_settings_shown", - Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360); + Comparator(ANY, 0), 360, 360); + config->event_configs.insert( + EventConfig("blue_dot_promo_settings_shown_new_session", + Comparator(LESS_THAN_OR_EQUAL, 2), 360, 360)); config->event_configs.insert( EventConfig("blue_dot_promo_eligibility_met", Comparator(GREATER_THAN_OR_EQUAL, 1), 30, 360)); config->event_configs.insert(EventConfig("default_browser_promo_shown", Comparator(EQUAL, 0), 30, 360)); + config->blocked_by.type = BlockedBy::Type::NONE; + config->blocking.type = Blocking::Type::NONE; return config; } #endif // BUILDFLAG(IS_IOS)
diff --git a/components/file_access/scoped_file_access_delegate.cc b/components/file_access/scoped_file_access_delegate.cc index 5b4a603..b9a3ea4 100644 --- a/components/file_access/scoped_file_access_delegate.cc +++ b/components/file_access/scoped_file_access_delegate.cc
@@ -23,6 +23,28 @@ } } +// static +void ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + const std::vector<base::FilePath>& files, + base::OnceCallback<void(ScopedFileAccess)> callback) { + if (request_files_access_for_system_io_callback_) { + request_files_access_for_system_io_callback_->Run(files, + std::move(callback)); + } else { + std::move(callback).Run(ScopedFileAccess::Allowed()); + } +} + +// static +ScopedFileAccessDelegate::RequestFilesAccessForSystemIOCallback* +ScopedFileAccessDelegate::SetRequestFilesAccessForSystemIOCallbackForTesting( + RequestFilesAccessForSystemIOCallback callback) { + auto* old_ptr = request_files_access_for_system_io_callback_; + request_files_access_for_system_io_callback_ = + new RequestFilesAccessForSystemIOCallback(std::move(callback)); + return old_ptr; +} + ScopedFileAccessDelegate::ScopedFileAccessDelegate() { if (scoped_file_access_delegate_) { delete scoped_file_access_delegate_; @@ -40,4 +62,9 @@ ScopedFileAccessDelegate* ScopedFileAccessDelegate::scoped_file_access_delegate_ = nullptr; +// static +ScopedFileAccessDelegate::RequestFilesAccessForSystemIOCallback* + ScopedFileAccessDelegate::request_files_access_for_system_io_callback_ = + nullptr; + } // namespace file_access \ No newline at end of file
diff --git a/components/file_access/scoped_file_access_delegate.h b/components/file_access/scoped_file_access_delegate.h index 0c0aa1d..2b1fc09 100644 --- a/components/file_access/scoped_file_access_delegate.h +++ b/components/file_access/scoped_file_access_delegate.h
@@ -22,9 +22,17 @@ // appropriate proxy. It is used for managed ChromeOs only in the implementation // DlpScopedfileAccessDelegate. Only one instance of a class which extends // this class can exist at a time. The class itself also manages this one -// instance. When it is replaced the old instance is destructed. +// instance. When it is replaced the old instance is destructed. This instance +// is constructed and destructed on the UI thread. So all methods should only be +// called from the UI thread. The exception is RequestFilesAccessForSystemIO, +// which takes care of hopping correctly between the threads and providing this +// to packages without direct access to the UI thread. class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate { public: + using RequestFilesAccessForSystemIOCallback = + base::RepeatingCallback<void(const std::vector<base::FilePath>&, + base::OnceCallback<void(ScopedFileAccess)>)>; + ScopedFileAccessDelegate(const ScopedFileAccessDelegate&) = delete; ScopedFileAccessDelegate& operator=(const ScopedFileAccessDelegate&) = delete; @@ -54,6 +62,13 @@ const std::vector<base::FilePath>& files, base::OnceCallback<void(file_access::ScopedFileAccess)> callback) = 0; + // Called from the IO thread. Switches to the UI thread and calls + // RequestFilesAccessForSystem there. The `callback` is run on the IO thread + // again. + static void RequestFilesAccessForSystemIO( + const std::vector<base::FilePath>& files, + base::OnceCallback<void(ScopedFileAccess)> callback); + // Calls base::ThreadPool::PostTaskAndReplyWithResult but `task` is run with // file access to `path`. The file access is hold until the call to `reply` // returns. @@ -81,6 +96,13 @@ path, from_here, traits, std::move(task), std::move(reply))); } + // Sets the callback forwarding the RequestFilesAccessForSystem call from IO + // to UI thread. Returns the previous callback transferring the ownership to + // the caller. + static RequestFilesAccessForSystemIOCallback* + SetRequestFilesAccessForSystemIOCallbackForTesting( + RequestFilesAccessForSystemIOCallback callback); + protected: ScopedFileAccessDelegate(); @@ -89,6 +111,12 @@ // A single instance of ScopedFileAccessDelegate. Equals nullptr when there's // not any data transfer restrictions required. static ScopedFileAccessDelegate* scoped_file_access_delegate_; + + // A single instance for a callback living on the IO thread which switches to + // the UI thread to call RequestFilesAccessForSystem from there and switch + // back to IO thread handing the ScopedFileAccess to another (given) callback. + static RequestFilesAccessForSystemIOCallback* + request_files_access_for_system_io_callback_; }; } // namespace file_access
diff --git a/components/history/core/browser/browsing_history_service.h b/components/history/core/browser/browsing_history_service.h index 07f63be..6768ee81 100644 --- a/components/history/core/browser/browsing_history_service.h +++ b/components/history/core/browser/browsing_history_service.h
@@ -254,7 +254,7 @@ // Deleting the request will cancel it. std::unique_ptr<WebHistoryService::Request> web_history_request_; - // True if there is a pending delete requests to the history service. + // True if there is a pending delete requests to the web service. bool has_pending_delete_request_ = false; // Tracker for delete requests to the history service.
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index f2f86d50c..3d57040d 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1071,7 +1071,6 @@ // Compute the file names. history_dir_ = history_database_params.history_dir; - channel_ = history_database_params.channel; #if DCHECK_IS_ON() DCHECK(!HistoryPathsTracker::GetInstance()->HasPath(history_dir_)) @@ -2199,6 +2198,13 @@ db_->UpdateClusterTriggerability(clusters); } +void HistoryBackend::HideVisits(const std::vector<VisitID>& visit_ids) { + TRACE_EVENT0("browser", "HistoryBackend::HideVisits"); + if (!db_) + return; + db_->HideVisits(visit_ids); +} + std::vector<Cluster> HistoryBackend::GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time,
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 1d05b1d7..de898c55 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -38,7 +38,6 @@ #include "components/history/core/browser/sync/history_backend_for_sync.h" #include "components/history/core/browser/visit_tracker.h" #include "components/sync/driver/sync_service.h" -#include "components/version_info/channel.h" #include "sql/init_status.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" @@ -531,6 +530,8 @@ void UpdateClusterTriggerability(const std::vector<Cluster>& clusters); + void HideVisits(const std::vector<VisitID>& visit_ids); + std::vector<Cluster> GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time, @@ -974,9 +975,6 @@ // Directory where database files will be stored, empty until Init is called. base::FilePath history_dir_; - // Used to control error reporting. - version_info::Channel channel_ = version_info::Channel::UNKNOWN; - // The history/favicon databases. Either may be null if the database could // not be opened, all users must first check for null and return immediately // if it is. The favicon DB may be null when the history one isn't, but not
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 7aa3c33b..760d532 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -337,6 +337,18 @@ std::move(callback)); } +base::CancelableTaskTracker::TaskId HistoryService::HideVisits( + const std::vector<VisitID>& visit_ids, + base::OnceClosure callback, + base::CancelableTaskTracker* tracker) { + DCHECK(backend_task_runner_) << "History service being called after cleanup"; + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return tracker->PostTaskAndReply( + backend_task_runner_.get(), FROM_HERE, + base::BindOnce(&HistoryBackend::HideVisits, history_backend_, visit_ids), + std::move(callback)); +} + base::CancelableTaskTracker::TaskId HistoryService::GetMostRecentClusters( base::Time inclusive_min_time, base::Time exclusive_max_time,
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h index 2167255..c3c886e 100644 --- a/components/history/core/browser/history_service.h +++ b/components/history/core/browser/history_service.h
@@ -611,6 +611,12 @@ base::OnceClosure callback, base::CancelableTaskTracker* tracker); + // Sets scores of cluster visits to 0 to hide them from the webUI. + base::CancelableTaskTracker::TaskId HideVisits( + const std::vector<VisitID>& visit_ids, + base::OnceClosure callback, + base::CancelableTaskTracker* tracker); + // Get the most recent `Cluster`s within the constraints. The most recent // visit of a cluster represents the cluster's time. `max_clusters` is a hard // cap. `max_visits_soft_cap` is a soft cap; `GetMostRecentClusters()` will
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index ed8919d..7479a283 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -894,6 +894,9 @@ // any UI. It is still included in the cluster so that it can be queried over, // as well as deleted when the whole cluster is deleted. This is computed in // the UI code, and should not be persisted. + // TODO(manukh): Now always false. Clean up usages. Also clean up + // `PromoteMatchingVisitsAboveNonMatchingVisits()` and anywhere else that + // intentionally sets the score low enough to be hidden below. bool hidden = false; // The URL of the representative image, which may be empty.
diff --git a/components/history/core/browser/visit_annotations_database.cc b/components/history/core/browser/visit_annotations_database.cc index 800d502c..1ac58e9 100644 --- a/components/history/core/browser/visit_annotations_database.cc +++ b/components/history/core/browser/visit_annotations_database.cc
@@ -971,6 +971,26 @@ return keyword_data; } +void VisitAnnotationsDatabase::HideVisits( + const std::vector<VisitID>& visit_ids) { + if (visit_ids.empty()) + return; + + sql::Statement statement( + GetDB().GetCachedStatement(SQL_FROM_HERE, + "UPDATE clusters_and_visits " + "SET score=0 WHERE visit_id=?")); + + for (auto visit_id : visit_ids) { + statement.Reset(true); + statement.BindInt64(0, visit_id); + if (!statement.Run()) { + DVLOG(0) << "Failed to execute visit hide statement: " + << "visit_id = " << visit_id; + } + } +} + void VisitAnnotationsDatabase::DeleteClusters( const std::vector<int64_t>& cluster_ids) { if (cluster_ids.empty())
diff --git a/components/history/core/browser/visit_annotations_database.h b/components/history/core/browser/visit_annotations_database.h index 747182e..99cdeac 100644 --- a/components/history/core/browser/visit_annotations_database.h +++ b/components/history/core/browser/visit_annotations_database.h
@@ -133,6 +133,9 @@ base::flat_map<std::u16string, ClusterKeywordData> GetClusterKeywords( int64_t cluster_id); + // Sets scores of cluster visits to 0 to hide them from the webUI. + void HideVisits(const std::vector<VisitID>& visit_ids); + // Delete `Cluster`s from the table. void DeleteClusters(const std::vector<int64_t>& cluster_ids);
diff --git a/components/history/core/test/visit_annotations_test_utils.cc b/components/history/core/test/visit_annotations_test_utils.cc index dd4245a..a2a1d0a5 100644 --- a/components/history/core/test/visit_annotations_test_utils.cc +++ b/components/history/core/test/visit_annotations_test_utils.cc
@@ -52,6 +52,7 @@ [](const auto& visit_id) { ClusterVisit visit; visit.annotated_visit.visit_row.visit_id = visit_id; + visit.score = 1; return visit; }); return cluster;
diff --git a/components/history_clusters/core/cluster_metrics_utils.cc b/components/history_clusters/core/cluster_metrics_utils.cc index 8f13aee6..b4c3cad7 100644 --- a/components/history_clusters/core/cluster_metrics_utils.cc +++ b/components/history_clusters/core/cluster_metrics_utils.cc
@@ -27,10 +27,12 @@ std::string VisitActionToString(VisitAction action) { switch (action) { - case VisitAction::kDeleted: - return "Deleted"; case VisitAction::kClicked: return "Clicked"; + case VisitAction::kHidden: + return "Hidden"; + case VisitAction::kDeleted: + return "Deleted"; } NOTREACHED(); return std::string();
diff --git a/components/history_clusters/core/cluster_metrics_utils.h b/components/history_clusters/core/cluster_metrics_utils.h index 33a6273..3668e37 100644 --- a/components/history_clusters/core/cluster_metrics_utils.h +++ b/components/history_clusters/core/cluster_metrics_utils.h
@@ -58,7 +58,8 @@ // Actions that can be performed on visits. enum class VisitAction { kClicked = 0, - kDeleted = 1, + kHidden = 1, + kDeleted = 2, }; // Types of visits that can be shown and acted on.
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc index b8339a05..d5572bf 100644 --- a/components/history_clusters/core/config.cc +++ b/components/history_clusters/core/config.cc
@@ -62,9 +62,6 @@ internal::kJourneys, "JourneysNumVisitsToAlwaysShowAboveTheFold", num_visits_to_always_show_above_the_fold); - drop_hidden_visits = base::GetFieldTrialParamByFeatureAsBool( - internal::kJourneys, "drop_hidden_visits", drop_hidden_visits); - rescore_visits_within_clusters_for_query = base::GetFieldTrialParamByFeatureAsBool( internal::kJourneys, "JourneysRescoreVisitsWithinClustersForQuery", @@ -287,12 +284,6 @@ content_clustering_enabled = base::FeatureList::IsEnabled( features::kOnDeviceClusteringContentClustering); - content_clustering_entity_similarity_weight = - GetFieldTrialParamByFeatureAsDouble( - features::kOnDeviceClusteringContentClustering, - "content_clustering_entity_similarity_weight", - content_clustering_entity_similarity_weight); - content_clustering_similarity_threshold = GetFieldTrialParamByFeatureAsDouble( features::kOnDeviceClusteringContentClustering, @@ -302,22 +293,6 @@ DCHECK_GE(content_clustering_similarity_threshold, 0.0f); DCHECK_LE(content_clustering_similarity_threshold, 1.0f); - content_cluster_on_intersection_similarity = - GetFieldTrialParamByFeatureAsBool( - features::kOnDeviceClusteringContentClustering, - "use_content_clustering_intersection_similarity", - content_cluster_on_intersection_similarity); - - cluster_interaction_threshold = GetFieldTrialParamByFeatureAsInt( - features::kOnDeviceClusteringContentClustering, - "content_clustering_intersection_threshold", - cluster_interaction_threshold); - - content_cluster_using_cosine_similarity = GetFieldTrialParamByFeatureAsBool( - features::kOnDeviceClusteringContentClustering, - "use_content_clustering_cosine_similarity", - content_cluster_using_cosine_similarity); - exclude_entities_that_have_no_collections_from_content_clustering = GetFieldTrialParamByFeatureAsBool( features::kOnDeviceClusteringContentClustering, @@ -326,6 +301,14 @@ collections_to_block_from_content_clustering = JourneysCollectionContentClusteringBlocklist(); + + use_pairwise_merge = GetFieldTrialParamByFeatureAsBool( + features::kOnDeviceClusteringContentClustering, "use_pairwise_merge", + use_pairwise_merge); + + max_pairwise_merge_iterations = GetFieldTrialParamByFeatureAsInt( + features::kOnDeviceClusteringContentClustering, + "max_pairwise_merge_iterations", max_pairwise_merge_iterations); } // The `kHistoryClustersVisitDeduping` feature and child params. @@ -378,6 +361,14 @@ cluster_triggerability_cutoff_duration.InMinutes())); } + // WebUI features and params. + { + hide_visits = base::FeatureList::IsEnabled(internal::kHideVisits); + + hide_visits_icon = GetFieldTrialParamByFeatureAsBool( + internal::kHideVisits, "hide_visits_icon", hide_visits_icon); + } + // Lonely features without child params. { non_user_visible_debug =
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h index 0a09524..f6579bc 100644 --- a/components/history_clusters/core/config.h +++ b/components/history_clusters/core/config.h
@@ -58,10 +58,6 @@ // one "top visit" and three subordinate looking visits will be always shown. size_t num_visits_to_always_show_above_the_fold = 4; - // If enabled, hidden visits are dropped entirely, instead of being gated - // behind a "Show More" UI control. - bool drop_hidden_visits = true; - // If enabled, when there is a Journeys search query, the backend re-scores // visits within a cluster to account for whether or not that visit matches. bool rescore_visits_within_clusters_for_query = true; @@ -260,6 +256,10 @@ // visit. int entity_relevance_threshold = 60; + // Returns the threshold for which we should mark a cluster as being able to + // show on prominent UI surfaces. + float content_visibility_threshold = 0.7; + // Returns the threshold used to determine if a cluster, and its visits, has // too high site engagement to be likely useful. float noisy_cluster_visits_engagement_threshold = 15.0; @@ -269,45 +269,6 @@ // on the zero state UI). size_t number_interesting_visits_filter_threshold = 1; - // The `kOnDeviceClusteringContentClustering` feature and child params. - - // Returns whether content clustering is enabled and - // should be performed by the clustering backend. - bool content_clustering_enabled = false; - - // Returns the weight that should be placed on entity similarity for - // determining if two clusters are similar enough to be combined into one. - float content_clustering_entity_similarity_weight = 1.0; - - // Returns the similarity threshold, between 0 and 1, used to determine if - // two clusters are similar enough to be combined into - // a single cluster. - float content_clustering_similarity_threshold = 0.2; - - // Returns the threshold for which we should mark a cluster as being able to - // show on prominent UI surfaces. - float content_visibility_threshold = 0.7; - - // Returns true if content clustering should use the intersection similarity - // score. - bool content_cluster_on_intersection_similarity = false; - - // Returns the threshold, in terms of the number of overlapping keywords, to - // use when clustering based on intersection score. - int cluster_interaction_threshold = 2; - - // Returns true if content clustering should use the cosine similarity - // algorithm. - bool content_cluster_using_cosine_similarity = false; - - // Returns whether we should exclude entities that do not have associated - // collections from content clustering. - bool exclude_entities_that_have_no_collections_from_content_clustering = - false; - - // The set of collections to block from being content clustered. - base::flat_set<std::string> collections_to_block_from_content_clustering; - // The `kUseEngagementScoreCache` feature and child params. // The max number of hosts that should be stored in the engagement score @@ -317,6 +278,32 @@ // The max time a host should be stored in the engagement score cache. base::TimeDelta engagement_score_cache_refresh_duration = base::Minutes(120); + // The `kOnDeviceClusteringContentClustering` feature and child params. + + // Returns whether content clustering is enabled and + // should be performed by the clustering backend. + bool content_clustering_enabled = false; + + // Returns the similarity threshold, between 0 and 1, used to determine if + // two clusters are similar enough to be combined into + // a single cluster. + float content_clustering_similarity_threshold = 0.2; + + // Returns whether we should exclude entities that do not have associated + // collections from content clustering. + bool exclude_entities_that_have_no_collections_from_content_clustering = true; + + // The set of collections to block from being content clustered. + base::flat_set<std::string> collections_to_block_from_content_clustering = { + "/collection/it_glosssary", "/collection/software"}; + + // Whether to merge similar clusters using pairwise merge. + bool use_pairwise_merge = false; + + // The maximum number of iterations to run for the convergence of pairwise + // merging of similar clusters. + int max_pairwise_merge_iterations = 40; + // The `kHistoryClustersVisitDeduping` feature and child params. // Use host instead of heavily-stripped URL as URL for deduping. @@ -353,6 +340,15 @@ // considered to be fully frozen and triggerability can be finalized. base::TimeDelta cluster_triggerability_cutoff_duration = base::Minutes(120); + // WebUI features and params. + + // Whether show either the hide visits thumbs-down or menu item on individual + // visits of persisted clusters. Which is shown depends on `hide_visits_icon`. + bool hide_visits = false; + + // Whether to the icon or menu item. + bool hide_visits_icon = false; + // Lonely features without child params. // Enables debug info in non-user-visible surfaces, like Chrome Inspector.
diff --git a/components/history_clusters/core/content_annotations_cluster_processor.cc b/components/history_clusters/core/content_annotations_cluster_processor.cc index d0d86123..1bfbeec 100644 --- a/components/history_clusters/core/content_annotations_cluster_processor.cc +++ b/components/history_clusters/core/content_annotations_cluster_processor.cc
@@ -8,6 +8,7 @@ #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/metrics/histogram_functions.h" #include "components/history_clusters/core/config.h" #include "components/history_clusters/core/on_device_clustering_util.h" #include "components/optimization_guide/core/entity_metadata.h" @@ -52,61 +53,161 @@ return dot_product / (mag_cluster1 * mag_cluster2); } -// Return the Jaccard Similarity between two sets of -// strings. -float CalculateJaccardSimilarity( - const base::flat_map<std::string, float>& cluster1, - const base::flat_map<std::string, float>& cluster2) { - // If either cluster is empty, just say that they are different. - if (cluster1.empty() || cluster2.empty()) - return 0.0; - - base::flat_set<std::string> cluster_union; - int intersection_size = 0; - for (const auto& token : cluster1) { - if (cluster2.find(token.first) != cluster2.end()) { - intersection_size++; - } - cluster_union.insert(token.first); - } - for (const auto& token : cluster2) { - cluster_union.insert(token.first); - } - - return cluster_union.empty() - ? 0.0 - : intersection_size / (1.0 * cluster_union.size()); -} - -// Calculates the similarity of two clusters using an intersection similarity. -// Returns 1 if the clusters share more than a threshold number of tokens in -// common and 0 otherwise. -float CalculateIntersectionSimilarity( - const base::flat_map<std::string, float>& cluster1, - const base::flat_map<std::string, float>& cluster2) { - // If either clusters is empty, just say that they're different. - if (cluster1.empty() || cluster2.empty()) - return 0.0; - - int intersection_size = 0; - for (const auto& token : cluster1) { - if (cluster2.find(token.first) != cluster2.end()) { - intersection_size++; - } - } - return intersection_size >= GetConfig().cluster_interaction_threshold ? 1.0 - : 0.0; -} - // Returns the similarity score based on the configured similarity metric. float CalculateSimilarityScore( const base::flat_map<std::string, float>& cluster1, const base::flat_map<std::string, float>& cluster2) { - if (GetConfig().content_cluster_on_intersection_similarity) - return CalculateIntersectionSimilarity(cluster1, cluster2); - if (GetConfig().content_cluster_using_cosine_similarity) - return CalculateCosineSimiliarity(cluster1, cluster2); - return CalculateJaccardSimilarity(cluster1, cluster2); + // TODO(b/244505276): Add more similarity metrics here if we can find one that + // makes more sense than cosine similarity. + return CalculateCosineSimiliarity(cluster1, cluster2); +} + +// Merges based on the following algorithm: +// For each cluster in clusters: +// For each other cluster in clusters: +// If similar, merge into first cluster. +void MergeIntoPreviousClusters( + std::vector<history::Cluster>* clusters, + std::vector<base::flat_map<std::string, float>>& occurrence_maps) { + for (size_t i = 0; i < clusters->size(); i++) { + if (clusters->at(i).visits.empty()) { + continue; + } + // Greedily combine clusters by checking if this cluster is similar to any + // other unmerged clusters. + for (size_t j = i + 1; j < clusters->size(); j++) { + if (clusters->at(j).visits.empty()) { + continue; + } + float entity_similarity = + CalculateSimilarityScore(occurrence_maps[i], occurrence_maps[j]); + if (entity_similarity >= + GetConfig().content_clustering_similarity_threshold) { + // Add the visits to the aggregated cluster. + AppendClusterVisits(clusters->at(i), clusters->at(j)); + } + } + } +} + +// Performs a pairwise merge of similar clusters in `clusters` based on +// `occurrence_maps`. In each iteration of the calculation, it will find the +// closest match for each cluster based on the similarity of the occurrence maps +// for each non-empty cluster in `clusters` and merge clusters that have a +// reciprocal match. It will run until the merge converges (an iteration has no +// matches) or the max number of iterations have been run. +void PairwiseMergeSimilarClusters( + std::vector<history::Cluster>* clusters, + std::vector<base::flat_map<std::string, float>>& occurrence_maps) { + int num_iterations = 0; + base::flat_set<size_t> no_matches; + bool found_match_in_iteration = false; + + do { + num_iterations++; + found_match_in_iteration = false; + + base::flat_map<size_t, size_t> best_matches; + base::flat_map<size_t, float> best_matches_scores; + + for (size_t i = 0; i < clusters->size(); i++) { + if (no_matches.contains(i)) { + // Skip if it did not have a match in a previous iteration. + continue; + } + if (clusters->at(i).visits.empty()) { + // Skip if cluster has already been merged. + continue; + } + + for (size_t j = i + 1; j < clusters->size(); j++) { + if (no_matches.contains(j)) { + // Skip if it did not have a match in a previous iteration. + continue; + } + if (clusters->at(j).visits.empty()) { + // Skip if cluster has already been merged. + continue; + } + + float entity_similarity = + CalculateSimilarityScore(occurrence_maps[i], occurrence_maps[j]); + if (entity_similarity >= + GetConfig().content_clustering_similarity_threshold) { + found_match_in_iteration = true; + + // Update best match for i, if applicable. + if (!best_matches_scores.contains(i) || + entity_similarity > best_matches_scores[i]) { + best_matches[i] = j; + best_matches_scores[i] = entity_similarity; + } + + // Update best match for j, if applicable. + if (!best_matches_scores.contains(j) || + entity_similarity > best_matches_scores[j]) { + best_matches[j] = i; + best_matches_scores[j] = entity_similarity; + } + } + } + + if (!best_matches.contains(i)) { + // Did not find a match for `i` during this iteration. Keep track of it + // so future processing of `i` is not performed. + no_matches.insert(i); + } + } + + // Process potential matches. + for (const auto& match : best_matches) { + DCHECK(clusters->size() > match.first && clusters->size() > match.second); + + if (clusters->at(match.first).visits.empty()) { + // Skip cluster match that has already been processed. + continue; + } + + // See if it is a reciprocal match. + if (best_matches.contains(match.second) && + best_matches[match.second] == match.first) { + // Merge cluster visits from second cluster into first. + AppendClusterVisits(clusters->at(match.first), + clusters->at(match.second)); + + // Merge occurrence mappings from second cluster into first. + for (const auto& entity_and_occurrence : + occurrence_maps[match.second]) { + occurrence_maps[match.first][entity_and_occurrence.first] += + entity_and_occurrence.second; + } + occurrence_maps[match.second].clear(); + } + } + } while (found_match_in_iteration && + num_iterations < GetConfig().max_pairwise_merge_iterations); + + base::UmaHistogramCounts100( + "History.Clusters.Backend.ContentClustering.PairwiseMergeNumIterations", + num_iterations); +} + +// Merges similar clusters in `clusters` based on the `occurrence_maps`. It is +// expected that `clusters` and `occurrence_maps` have the same number of +// entries and that the ith entry in `occurence_maps` is the occurrence map for +// the ith entry in `clusters`. +void MergeSimilarClusters( + std::vector<history::Cluster>* clusters, + std::vector<base::flat_map<std::string, float>>& occurrence_maps) { + DCHECK_EQ(clusters->size(), occurrence_maps.size()); + + if (GetConfig().use_pairwise_merge) { + PairwiseMergeSimilarClusters(clusters, occurrence_maps); + } else { + MergeIntoPreviousClusters(clusters, occurrence_maps); + } + + RemoveEmptyClusters(clusters); } } // namespace @@ -120,37 +221,27 @@ void ContentAnnotationsClusterProcessor::ProcessClusters( std::vector<history::Cluster>* clusters) { + DCHECK(clusters); + + if (clusters->empty()) { + return; + } + + base::UmaHistogramCounts1000( + "History.Clusters.Backend.ContentClustering.NumClustersBeforeMerge", + clusters->size()); + std::vector<base::flat_map<std::string, float>> occurrence_maps( clusters->size()); for (size_t i = 0; i < clusters->size(); i++) { occurrence_maps[i] = CreateOccurrenceMapForCluster(clusters->at(i)); } - // Now cluster on the entries in each BoW between clusters. - base::flat_set<int> merged_cluster_indices; - for (size_t i = 0; i < clusters->size(); i++) { - if (merged_cluster_indices.find(i) != merged_cluster_indices.end()) { - continue; - } - // Greedily combine clusters by checking if this cluster is similar to any - // other unmerged clusters. - for (size_t j = i + 1; j < clusters->size(); j++) { - if (merged_cluster_indices.find(j) != merged_cluster_indices.end()) { - continue; - } - float entity_similarity = - CalculateSimilarityScore(occurrence_maps[i], occurrence_maps[j]); - if (entity_similarity > - GetConfig().content_clustering_similarity_threshold) { - // Add the visits to the aggregated cluster. - merged_cluster_indices.insert(j); - AppendClusterVisits(clusters->at(i), clusters->at(j)); - } - } - } + MergeSimilarClusters(clusters, occurrence_maps); - // Remove empty clusters. - RemoveEmptyClusters(clusters); + base::UmaHistogramCounts1000( + "History.Clusters.Backend.ContentClustering.NumClustersAfterMerge", + clusters->size()); } base::flat_map<std::string, float>
diff --git a/components/history_clusters/core/content_annotations_cluster_processor_unittest.cc b/components/history_clusters/core/content_annotations_cluster_processor_unittest.cc index 31f4ffc2..8320578 100644 --- a/components/history_clusters/core/content_annotations_cluster_processor_unittest.cc +++ b/components/history_clusters/core/content_annotations_cluster_processor_unittest.cc
@@ -5,6 +5,7 @@ #include "components/history_clusters/core/content_annotations_cluster_processor.h" #include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "components/history_clusters/core/clustering_test_utils.h" #include "components/history_clusters/core/config.h" @@ -22,10 +23,10 @@ public: ContentAnnotationsClusterProcessorTest() { config_.content_clustering_enabled = true; - config_.content_cluster_on_intersection_similarity = false; config_.content_clustering_similarity_threshold = 0.5; config_.exclude_entities_that_have_no_collections_from_content_clustering = false; + config_.use_pairwise_merge = true; config_.collections_to_block_from_content_clustering = {}; SetConfigForTesting(config_); } @@ -67,6 +68,8 @@ }; TEST_F(ContentAnnotationsClusterProcessorTest, AboveThreshold) { + base::HistogramTester histogram_tester; + std::vector<history::Cluster> clusters; history::AnnotatedVisit visit = @@ -96,265 +99,87 @@ cluster2.visits = {testing::CreateClusterVisit(visit5)}; clusters.push_back(cluster2); - ProcessClusters(&clusters); - EXPECT_THAT( - testing::ToVisitResults(clusters), - ElementsAre(ElementsAre( - testing::VisitResult(1, 1.0), testing::VisitResult(2, 1.0), - testing::VisitResult(4, 1.0), testing::VisitResult(10, 1.0)))); - ASSERT_EQ(clusters.size(), 1u); -} - -TEST_F(ContentAnnotationsClusterProcessorTest, BelowThreshold) { - std::vector<history::Cluster> clusters; - - history::AnnotatedVisit visit = - testing::CreateDefaultAnnotatedVisit(1, GURL("https://github.com/")); - visit.content_annotations.model_annotations.entities = {{"github", 1}}; - visit.content_annotations.model_annotations.categories = {{"category", 1}}; - - history::AnnotatedVisit visit2 = - testing::CreateDefaultAnnotatedVisit(2, GURL("https://google.com/")); - visit2.visit_row.visit_duration = base::Seconds(20); - history::Cluster cluster1; - cluster1.visits = {testing::CreateClusterVisit(visit), - testing::CreateClusterVisit(visit2)}; - clusters.push_back(cluster1); - - // After the context clustering, visit4 will not be in the same cluster as - // visit and visit2 but should be clustered together since they have the same - // entities. - history::AnnotatedVisit visit4 = - testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")); - visit4.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster2; - cluster2.visits = {testing::CreateClusterVisit(visit4)}; - clusters.push_back(cluster2); - - // This visit has no entities and shouldn't be grouped with the others. - history::AnnotatedVisit visit6 = - testing::CreateDefaultAnnotatedVisit(11, GURL("https://othervisit.com/")); - history::Cluster cluster4; - cluster4.visits = {testing::CreateClusterVisit(visit6)}; - clusters.push_back(cluster4); - - // This visit has no content annotations and shouldn't be grouped with the - // others. - history::AnnotatedVisit visit7 = testing::CreateDefaultAnnotatedVisit( - 12, GURL("https://nocontentannotations.com/")); - history::Cluster cluster5; - cluster5.visits = {testing::CreateClusterVisit(visit7)}; - clusters.push_back(cluster5); - - ProcessClusters(&clusters); - EXPECT_THAT(testing::ToVisitResults(clusters), - ElementsAre(ElementsAre(testing::VisitResult(1, 1.0), - testing::VisitResult(2, 1.0), - testing::VisitResult(4, 1.0)), - ElementsAre(testing::VisitResult(11, 1.0)), - ElementsAre(testing::VisitResult(12, 1.0)))); -} - -class ContentAnnotationsClusterProcessorCosineSimilarityTest - : public ContentAnnotationsClusterProcessorTest { - public: - ContentAnnotationsClusterProcessorCosineSimilarityTest() { - config_.content_clustering_enabled = true; - config_.content_cluster_on_intersection_similarity = false; - config_.content_clustering_similarity_threshold = 0.5; - config_.exclude_entities_that_have_no_collections_from_content_clustering = - false; - config_.collections_to_block_from_content_clustering = {}; - config_.content_cluster_using_cosine_similarity = true; - SetConfigForTesting(config_); - } - - private: - Config config_; -}; - -TEST_F(ContentAnnotationsClusterProcessorCosineSimilarityTest, AboveThreshold) { - std::vector<history::Cluster> clusters; - - history::AnnotatedVisit visit = - testing::CreateDefaultAnnotatedVisit(1, GURL("https://github.com/")); - visit.content_annotations.model_annotations.entities = {{"github", 1}}; - visit.content_annotations.model_annotations.categories = {{"category", 1}}; - history::AnnotatedVisit visit2 = - testing::CreateDefaultAnnotatedVisit(2, GURL("https://google.com/")); - visit2.content_annotations.model_annotations.entities = {{"github", 1}}; - history::AnnotatedVisit visit4 = - testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")); - visit4.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster1; - cluster1.visits = {testing::CreateClusterVisit(visit), - testing::CreateClusterVisit(visit2), - testing::CreateClusterVisit(visit4)}; - clusters.push_back(cluster1); - // After the context clustering, visit5 will not be in the same cluster as // visit, visit2, and visit4 but all of the visits have the same entity // so they will be clustered in the content pass. - history::AnnotatedVisit visit5 = testing::CreateDefaultAnnotatedVisit( - 10, GURL("https://nonexistentreferrer.com/")); - visit5.content_annotations.model_annotations.entities = {{"github", 1}}; - visit5.content_annotations.model_annotations.categories = {{"category", 1}}; - history::Cluster cluster2; - cluster2.visits = {testing::CreateClusterVisit(visit5)}; - clusters.push_back(cluster2); - - ProcessClusters(&clusters); - EXPECT_THAT( - testing::ToVisitResults(clusters), - ElementsAre(ElementsAre( - testing::VisitResult(1, 1.0), testing::VisitResult(2, 1.0), - testing::VisitResult(4, 1.0), testing::VisitResult(10, 1.0)))); -} - -TEST_F(ContentAnnotationsClusterProcessorCosineSimilarityTest, BelowThreshold) { - std::vector<history::Cluster> clusters; - - history::AnnotatedVisit visit = - testing::CreateDefaultAnnotatedVisit(1, GURL("https://github.com/")); - visit.content_annotations.model_annotations.entities = {{"github", 1}}; - visit.content_annotations.model_annotations.categories = {{"category", 1}}; - - history::AnnotatedVisit visit2 = - testing::CreateDefaultAnnotatedVisit(2, GURL("https://google.com/")); - visit2.visit_row.visit_duration = base::Seconds(20); - history::Cluster cluster1; - cluster1.visits = {testing::CreateClusterVisit(visit), - testing::CreateClusterVisit(visit2)}; - clusters.push_back(cluster1); - - // After the context clustering, visit4 will not be in the same cluster as - // visit and visit2 but should be clustered together since they have the same - // entities. - history::AnnotatedVisit visit4 = - testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")); - visit4.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster2; - cluster2.visits = {testing::CreateClusterVisit(visit4)}; - clusters.push_back(cluster2); - - // This visit has no entities and shouldn't be grouped with the others. - history::AnnotatedVisit visit6 = - testing::CreateDefaultAnnotatedVisit(11, GURL("https://othervisit.com/")); - history::Cluster cluster4; - cluster4.visits = {testing::CreateClusterVisit(visit6)}; - clusters.push_back(cluster4); - - // This visit has no content annotations and shouldn't be grouped with the - // others. - history::AnnotatedVisit visit7 = testing::CreateDefaultAnnotatedVisit( - 12, GURL("https://nocontentannotations.com/")); - history::Cluster cluster5; - cluster5.visits = {testing::CreateClusterVisit(visit7)}; - clusters.push_back(cluster5); - - ProcessClusters(&clusters); - EXPECT_THAT(testing::ToVisitResults(clusters), - ElementsAre(ElementsAre(testing::VisitResult(1, 1.0), - testing::VisitResult(2, 1.0), - testing::VisitResult(4, 1.0)), - ElementsAre(testing::VisitResult(11, 1.0)), - ElementsAre(testing::VisitResult(12, 1.0)))); -} - -class ContentAnnotationsClusterProcessorIntersectionMetricTest - : public ContentAnnotationsClusterProcessorTest { - public: - ContentAnnotationsClusterProcessorIntersectionMetricTest() { - config_.content_clustering_enabled = true; - config_.content_cluster_on_intersection_similarity = true; - config_.exclude_entities_that_have_no_collections_from_content_clustering = - false; - config_.collections_to_block_from_content_clustering = {}; - config_.cluster_interaction_threshold = 2; - SetConfigForTesting(config_); - } - - private: - Config config_; -}; - -TEST_F(ContentAnnotationsClusterProcessorIntersectionMetricTest, - AboveThreshold) { - std::vector<history::Cluster> clusters; - - history::AnnotatedVisit visit = - testing::CreateDefaultAnnotatedVisit(1, GURL("https://github.com/")); - visit.content_annotations.model_annotations.entities = {{"github", 1}, - {"baz", 1}}; - history::AnnotatedVisit visit2 = - testing::CreateDefaultAnnotatedVisit(2, GURL("https://google.com/")); - visit2.content_annotations.model_annotations.entities = {{"github", 1}}; - history::AnnotatedVisit visit4 = - testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")); - visit4.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster1; - cluster1.visits = {testing::CreateClusterVisit(visit), - testing::CreateClusterVisit(visit2), - testing::CreateClusterVisit(visit4)}; - clusters.push_back(cluster1); - - // After the context clustering, visit5 will not be in the same cluster as - // visit, visit2, and visit4 but has the same two categories, which is - // above the default intersection threshold. - history::AnnotatedVisit visit5 = testing::CreateDefaultAnnotatedVisit( - 10, GURL("https://nonexistentreferrer.com/")); - visit5.content_annotations.model_annotations.entities = {{"github", 1}, - {"baz", 1}}; history::AnnotatedVisit visit6 = testing::CreateDefaultAnnotatedVisit( - 11, GURL("https://nonexistentreferrer.com/")); + 6, GURL("https://nonexistentreferrer.com/")); visit6.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster2; - cluster2.visits = {testing::CreateClusterVisit(visit5), - testing::CreateClusterVisit(visit6)}; - clusters.push_back(cluster2); + history::Cluster cluster3; + cluster3.visits = {testing::CreateClusterVisit(visit6)}; + clusters.push_back(cluster3); ProcessClusters(&clusters); EXPECT_THAT(testing::ToVisitResults(clusters), ElementsAre(ElementsAre( testing::VisitResult(1, 1.0), testing::VisitResult(2, 1.0), testing::VisitResult(4, 1.0), testing::VisitResult(10, 1.0), - testing::VisitResult(11, 1.0)))); + testing::VisitResult(6, 1.0)))); + ASSERT_EQ(clusters.size(), 1u); + + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.ContentClustering.NumClustersBeforeMerge", 3, + 1); + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.ContentClustering.NumClustersAfterMerge", 1, 1); } -TEST_F(ContentAnnotationsClusterProcessorIntersectionMetricTest, - BelowThreshold) { +TEST_F(ContentAnnotationsClusterProcessorTest, BelowThreshold) { + base::HistogramTester histogram_tester; + std::vector<history::Cluster> clusters; history::AnnotatedVisit visit = testing::CreateDefaultAnnotatedVisit(1, GURL("https://github.com/")); visit.content_annotations.model_annotations.entities = {{"github", 1}}; visit.content_annotations.model_annotations.categories = {{"category", 1}}; + history::AnnotatedVisit visit2 = testing::CreateDefaultAnnotatedVisit(2, GURL("https://google.com/")); - visit2.content_annotations.model_annotations.entities = {{"github", 1}}; - visit2.content_annotations.model_annotations.categories = {{"category2", 2}}; + visit2.visit_row.visit_duration = base::Seconds(20); + history::Cluster cluster1; + cluster1.visits = {testing::CreateClusterVisit(visit), + testing::CreateClusterVisit(visit2)}; + clusters.push_back(cluster1); + + // After the context clustering, visit4 will not be in the same cluster as + // visit and visit2 but should be clustered together since they have the same + // entities. history::AnnotatedVisit visit4 = testing::CreateDefaultAnnotatedVisit(4, GURL("https://github.com/")); visit4.content_annotations.model_annotations.entities = {{"github", 1}}; - history::Cluster cluster1; - cluster1.visits = {testing::CreateClusterVisit(visit), - testing::CreateClusterVisit(visit2), - testing::CreateClusterVisit(visit4)}; - clusters.push_back(cluster1); - - // After the context clustering, visit5 will not be in the same cluster as - // visit, visit2, and visit4 and it only intersects on one categories, which - // is below the default intersection threshold. - history::AnnotatedVisit visit5 = testing::CreateDefaultAnnotatedVisit( - 10, GURL("https://nonexistentreferrer.com/")); - visit5.content_annotations.model_annotations.entities = {{"github", 1}}; - visit5.content_annotations.model_annotations.categories = {{"category", 1}}; history::Cluster cluster2; - cluster2.visits = {testing::CreateClusterVisit(visit5)}; + cluster2.visits = {testing::CreateClusterVisit(visit4)}; clusters.push_back(cluster2); + // This visit has no entities and shouldn't be grouped with the others. + history::AnnotatedVisit visit6 = + testing::CreateDefaultAnnotatedVisit(11, GURL("https://othervisit.com/")); + history::Cluster cluster4; + cluster4.visits = {testing::CreateClusterVisit(visit6)}; + clusters.push_back(cluster4); + + // This visit has no content annotations and shouldn't be grouped with the + // others. + history::AnnotatedVisit visit7 = testing::CreateDefaultAnnotatedVisit( + 12, GURL("https://nocontentannotations.com/")); + history::Cluster cluster5; + cluster5.visits = {testing::CreateClusterVisit(visit7)}; + clusters.push_back(cluster5); + ProcessClusters(&clusters); - ASSERT_EQ(clusters.size(), 2u); + EXPECT_THAT(testing::ToVisitResults(clusters), + ElementsAre(ElementsAre(testing::VisitResult(1, 1.0), + testing::VisitResult(2, 1.0), + testing::VisitResult(4, 1.0)), + ElementsAre(testing::VisitResult(11, 1.0)), + ElementsAre(testing::VisitResult(12, 1.0)))); + + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.ContentClustering.NumClustersBeforeMerge", 4, + 1); + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.ContentClustering.NumClustersAfterMerge", 3, 1); } class ContentAnnotationsSimilarityVariousCollectionsFilteringTest
diff --git a/components/history_clusters/core/features.cc b/components/history_clusters/core/features.cc index 7ea9dd7..3357ed22 100644 --- a/components/history_clusters/core/features.cc +++ b/components/history_clusters/core/features.cc
@@ -85,26 +85,12 @@ "HistoryClustersNavigationContextClustering", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kHideVisits, + "HistoryClustersHideVisits", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace internal -BASE_FEATURE(kJourneysSurveyForHistoryEntrypoint, - "JourneysSurveyForHistoryEntrypoint", - base::FEATURE_DISABLED_BY_DEFAULT); - -const base::FeatureParam<base::TimeDelta> - kJourneysSurveyForHistoryEntrypointDelay{ - &kJourneysSurveyForHistoryEntrypoint, "survey-delay-duration", - base::Seconds(6)}; - -BASE_FEATURE(kJourneysSurveyForOmniboxEntrypoint, - "JourneysSurveyForOmniboxEntrypoint", - base::FEATURE_DISABLED_BY_DEFAULT); - -const base::FeatureParam<base::TimeDelta> - kJourneysSurveyForOmniboxEntrypointDelay{ - &kJourneysSurveyForOmniboxEntrypoint, "survey-delay-duration", - base::Seconds(6)}; - BASE_FEATURE(kSidePanelJourneys, "SidePanelJourneys", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/history_clusters/core/features.h b/components/history_clusters/core/features.h index 463213e7..e853e60 100644 --- a/components/history_clusters/core/features.h +++ b/components/history_clusters/core/features.h
@@ -7,8 +7,6 @@ #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" -#include "base/time/time.h" -#include "url/gurl.h" namespace history_clusters { @@ -71,6 +69,10 @@ // batches. BASE_DECLARE_FEATURE(kHistoryClustersNavigationContextClustering); +// Enables either the hide visits thumbs-down or menu item on individual visits +// of persisted clusters. +BASE_DECLARE_FEATURE(kHideVisits); + // Order consistently with config.h. } // namespace internal @@ -80,16 +82,6 @@ // referred to outside of Journeys code. Moreover, they are not used inside an // inner loop, so they don't need to be high performance. -// Enables the user survey when the user clicks over to Journeys from History. -BASE_DECLARE_FEATURE(kJourneysSurveyForHistoryEntrypoint); -extern const base::FeatureParam<base::TimeDelta> - kJourneysSurveyForHistoryEntrypointDelay; - -// Enables the user survey when the user uses the omnibox to access Journeys. -BASE_DECLARE_FEATURE(kJourneysSurveyForOmniboxEntrypoint); -extern const base::FeatureParam<base::TimeDelta> - kJourneysSurveyForOmniboxEntrypointDelay; - // Enables Side Panel Journeys. BASE_DECLARE_FEATURE(kSidePanelJourneys); extern const base::FeatureParam<bool> kSidePanelJourneysOpensFromOmnibox;
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc index e6fa3ac..17443eb 100644 --- a/components/history_clusters/core/history_clusters_service.cc +++ b/components/history_clusters/core/history_clusters_service.cc
@@ -12,10 +12,10 @@ #include "base/functional/bind.h" #include "base/i18n/case_conversion.h" #include "base/metrics/histogram_functions.h" +#include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" #include "base/time/time.h" -#include "base/time/time_to_iso8601.h" #include "base/timer/elapsed_timer.h" #include "base/timer/timer.h" #include "components/history/core/browser/history_backend.h" @@ -421,7 +421,10 @@ // sensitive clusters here. continue; } - if (cluster.visits.size() < 2) { + const size_t visible_visits = base::ranges::count_if( + cluster.visits, + [](const auto& cluster_visit) { return cluster_visit.score > 0; }); + if (visible_visits < 2) { // Only accept keywords from clusters with at least two visits. This is a // simple first-pass technique to avoid overtriggering the omnibox action. continue;
diff --git a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc index 0213067..afc4986 100644 --- a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc +++ b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.cc
@@ -12,6 +12,7 @@ #include "components/history/core/browser/history_service.h" #include "components/history_clusters/core/clustering_backend.h" #include "components/history_clusters/core/config.h" +#include "components/history_clusters/core/history_clusters_db_tasks.h" #include "components/history_clusters/core/history_clusters_debug_jsons.h" #include "components/history_clusters/core/history_clusters_service.h" @@ -32,7 +33,7 @@ DCHECK(history_service_); DCHECK(backend_); - continuation_time_ = task_created_time_; + continuation_params_.continuation_time = task_created_time_; Start(); } @@ -40,14 +41,134 @@ ~HistoryClustersServiceTaskUpdateClusterTriggerability() = default; void HistoryClustersServiceTaskUpdateClusterTriggerability::Start() { - history_service_->GetMostRecentClusters( - base::Time::Min(), continuation_time_, - GetConfig().max_persisted_clusters_to_fetch, - GetConfig().max_persisted_cluster_visits_to_fetch_soft_cap, + if (weak_history_clusters_service_ && + weak_history_clusters_service_->ShouldNotifyDebugMessage()) { + weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( + "UPDATE CLUSTER TRIGGERABILITY TASK - START. " + "exhausted_unclustered_visits = %d. " + "continuation_time = %s.", + continuation_params_.exhausted_unclustered_visits, + GetDebugTime(continuation_params_.continuation_time).c_str())); + } + + if (continuation_params_.exhausted_unclustered_visits) { + history_service_->GetMostRecentClusters( + base::Time::Min(), continuation_params_.continuation_time, + GetConfig().max_persisted_clusters_to_fetch, + GetConfig().max_persisted_cluster_visits_to_fetch_soft_cap, + base::BindOnce(&HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnGotPersistedClusters, + weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), + /*include_keywords_and_duplicates=*/false, &task_tracker_); + } else { + history_service_->ScheduleDBTask( + FROM_HERE, + std::make_unique<GetAnnotatedVisitsToCluster>( + std::map<int64_t, IncompleteVisitContextAnnotations>(), + /*begin_time=*/base::Time::Min(), continuation_params_, + /*recent_first=*/true, + /*days_of_clustered_visits=*/0, /*recluster=*/false, + base::BindOnce( + &HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnGotAnnotatedVisitsToCluster, + weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now())), + &task_tracker_); + } +} + +void HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnGotAnnotatedVisitsToCluster( + base::TimeTicks start_time, + std::vector<int64_t> old_clusters_unused, + std::vector<history::AnnotatedVisit> annotated_visits, + QueryClustersContinuationParams continuation_params) { + if (!weak_history_clusters_service_) { + return; + } + + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusterTriggerability." + "GetAnnotatedVisitsToClusterLatency", + base::TimeTicks::Now() - start_time); + + // Records whether there were unclustered visits to cluster. This will inform + // whether the call to get annotated visits to cluster can be removed once + // this code path has launched. + if (!continuation_params_.is_continuation) { + base::UmaHistogramBoolean( + "History.Clusters.Backend.UpdateClusterTriggerability." + "HadUnclusteredVisitsToCluster", + annotated_visits.empty()); + } + + if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { + weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( + "UPDATE CLUSTER TRIGGERABILITY TASK - UNCLUSTERED VISITS %zu:", + annotated_visits.size())); + weak_history_clusters_service_->NotifyDebugMessage( + GetDebugJSONForVisits(annotated_visits)); + } + + continuation_params_ = continuation_params; + + if (annotated_visits.empty()) { + // Reset the continuation time so that the newly created clusters have their + // triggerability metadata calculated. + continuation_params_.continuation_time = task_created_time_; + Start(); + return; + } + + // Using `kKeywordCacheGeneration` as that determines the task priority. + backend_->GetClusters( + ClusteringRequestSource::kKeywordCacheGeneration, base::BindOnce(&HistoryClustersServiceTaskUpdateClusterTriggerability:: - OnGotPersistedClusters, + OnGotModelContextClusters, weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), - /*include_keywords_and_duplicates=*/false, &task_tracker_); + annotated_visits, /*requires_ui_and_triggerability=*/false); +} + +void HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnGotModelContextClusters(base::TimeTicks start_time, + std::vector<history::Cluster> clusters) { + // Persist the context clusters. + if (!weak_history_clusters_service_) { + return; + } + + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusterTriggerability." + "ComputeContextClustersLatency", + base::TimeTicks::Now() - start_time); + + if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { + weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( + "UPDATE CLUSTER TRIGGERABILITY TASK - MODEL CONTEXT CLUSTERS %zu:", + clusters.size())); + weak_history_clusters_service_->NotifyDebugMessage( + GetDebugJSONForClusters(clusters)); + } + + history_service_->ReplaceClusters( + /*ids_to_delete=*/{}, clusters, + base::BindOnce(&HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnPersistedContextClusters, + weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), + &task_tracker_); +} + +void HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnPersistedContextClusters(base::TimeTicks start_time) { + if (!weak_history_clusters_service_) { + return; + } + + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusterTriggerability." + "PersistContextClustersLatency", + base::TimeTicks::Now() - start_time); + + Start(); } void HistoryClustersServiceTaskUpdateClusterTriggerability:: @@ -64,7 +185,7 @@ if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( - "UPDATE CLUSTER TRIGGERABILITY TASK - PERSISTED CLUSTERS %zu:", + "UPDATE CLUSTER TRIGGERABILITY TASK - PERSISTED CONTEXT CLUSTERS %zu:", clusters.size())); weak_history_clusters_service_->NotifyDebugMessage( GetDebugJSONForClusters(clusters)); @@ -78,7 +199,7 @@ std::move(callback_).Run(); return; } - continuation_time_ = + continuation_params_.continuation_time = clusters.back().GetMostRecentVisit().annotated_visit.visit_row.visit_time; std::vector<history::Cluster> filtered_clusters; @@ -96,14 +217,15 @@ backend_->GetClusterTriggerability( base::BindOnce(&HistoryClustersServiceTaskUpdateClusterTriggerability:: - OnGotModelClusters, + OnGotModelClustersWithTriggerability, weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()), std::move(filtered_clusters)); } -void HistoryClustersServiceTaskUpdateClusterTriggerability::OnGotModelClusters( - base::TimeTicks start_time, - std::vector<history::Cluster> clusters) { +void HistoryClustersServiceTaskUpdateClusterTriggerability:: + OnGotModelClustersWithTriggerability( + base::TimeTicks start_time, + std::vector<history::Cluster> clusters) { if (!weak_history_clusters_service_) { return; } @@ -114,9 +236,10 @@ base::TimeTicks::Now() - start_time); if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { - weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( - "UPDATE CLUSTER TRIGGERABILITY TASK - MODEL CLUSTERS %zu:", - clusters.size())); + weak_history_clusters_service_->NotifyDebugMessage( + base::StringPrintf("UPDATE CLUSTER TRIGGERABILITY TASK - MODEL " + "CLUSTERS WITH TRIGGERABILITY %zu:", + clusters.size())); weak_history_clusters_service_->NotifyDebugMessage( GetDebugJSONForClusters(clusters)); }
diff --git a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h index 545a68cb..4f77498 100644 --- a/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h +++ b/components/history_clusters/core/history_clusters_service_task_update_cluster_triggerability.h
@@ -38,11 +38,20 @@ ~HistoryClustersServiceTaskUpdateClusterTriggerability() override; private: + // When there remain unclustered visits, calculate the context clusters and + // persist them. After unclustered visits have been exhausted, the below flows + // will be run to calculate triggerability on the remaining clusters. + // Start() -> + // OnGotAnnotatedVisitsToCluster() -> + // OnGotModelContextClusters() -> + // OnPersistedContextClusters() -> + // Start() + // When there remain clusters without their triggerability calculated, // calculate them and persist the new values: // Start() -> // OnGotPersistedClusters() -> - // OnGotModelClusters() -> + // OnGotModelClustersWithTriggerability() -> // OnPersistedClusterTriggerability() -> // Start() @@ -57,20 +66,41 @@ // persisted clusters. void Start(); - // Invoked after `Start()` asyncly fetches clusters. May syncly invoke - // `callback_` if no clusters were returned. If clusters are returned, this - // will filter for clusters that do not have their triggerability calculated - // yet so that triggerability metadata can be calculated. Otherwise, it - // invokes `Start()` to fetch more clusters. + // Invoked after `Start()` asyncly fetches visits. If visits are returned, + // this will cluster them into the basic context clusters and persist those. + // After all unclustered visits have been exhausted, the flow to update its + // triggerability metadata will be run. + void OnGotAnnotatedVisitsToCluster( + base::TimeTicks start_time, + std::vector<int64_t> old_clusters_unused, + std::vector<history::AnnotatedVisit> annotated_visits, + QueryClustersContinuationParams continuation_params); + + // Invoked after `OnGotAnnotatedVisitsToCluster()` asyncly calculates context + // clusters from unclustered visits. + void OnGotModelContextClusters(base::TimeTicks start_time, + std::vector<history::Cluster> clusters); + + // Invoked after `OnGotModelContextClusters()` asyncly persists the context + // clusters. + void OnPersistedContextClusters(base::TimeTicks start_time); + + // Invoked after `Start()` asyncly fetches clusters when all unclustered + // visits have been exhausted. May syncly invoke `callback_` if no clusters + // were returned. If clusters are returned, this will filter for clusters that + // do not have their triggerability calculated yet so that triggerability + // metadata can be calculated. Otherwise, it invokes `Start()` to fetch more + // clusters. void OnGotPersistedClusters(base::TimeTicks start_time, std::vector<history::Cluster> clusters); // Invoked after `OnGotPersistedClusters()` asyncly obtains clusters. - void OnGotModelClusters(base::TimeTicks start_time, - std::vector<history::Cluster> clusters); + void OnGotModelClustersWithTriggerability( + base::TimeTicks start_time, + std::vector<history::Cluster> clusters); - // Invoked after `OnGotModelClusters()` asyncly persists clusters. Will syncly - // invoke `Start()` to initiate the next iteration. + // Invoked after `OnGotModelClustersWithTriggerability()` asyncly persists + // clusters. Will syncly invoke `Start()` to initiate the next iteration. void OnPersistedClusterTriggerability(base::TimeTicks start_time); // Never nullptr. @@ -81,7 +111,7 @@ const raw_ptr<history::HistoryService> history_service_; // Used to make requests to `HistoryService`. - base::Time continuation_time_; + QueryClustersContinuationParams continuation_params_; base::CancelableTaskTracker task_tracker_; // Invoked after `OnGotPersistedClusters()` when all clusters have been
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc index 6470f97..7d8ab029 100644 --- a/components/history_clusters/core/history_clusters_service_unittest.cc +++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -1334,10 +1334,12 @@ ComputeURLKeywordForLookup(GURL("https://second-1-day-old-visit.com/")))); std::vector<history::Cluster> clusters; + // This cluster should contribute to keywords. clusters.push_back(history::Cluster( 0, { GetHardcodedClusterVisit(5), + GetHardcodedClusterVisit(5), GetHardcodedClusterVisit( /*visit_id=*/2, /*score=*/0.0, /*engagement_score=*/20.0), }, @@ -1346,6 +1348,8 @@ {u"z", history::ClusterKeywordData()}, {u"apples bananas", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); + // This cluster should NOT contribute to keywords because + // `should_show_on_prominent_ui_surfaces` is false. clusters.push_back( history::Cluster(0, { @@ -1354,10 +1358,13 @@ }, {{u"sensitive", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/false)); + // This cluster should NOT contribute to keywords because it only has 1 + // visible visit. clusters.push_back( history::Cluster(0, { GetHardcodedClusterVisit(2), + GetHardcodedClusterVisit(2, /*score=*/0), }, {{u"singlevisit", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); @@ -1403,10 +1410,12 @@ ComputeURLKeywordForLookup(GURL("https://second-1-day-old-visit.com/")))); std::vector<history::Cluster> clusters; + // This cluster should contribute to keywords. clusters.push_back(history::Cluster( 0, { GetHardcodedClusterVisit(5), + GetHardcodedClusterVisit(5), GetHardcodedClusterVisit( /*visit_id=*/2, /*score=*/0.0, /*engagement_score=*/20.0), }, @@ -1415,6 +1424,8 @@ {u"z", history::ClusterKeywordData()}, {u"apples bananas", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); + // This cluster should NOT contribute to keywords because + // `should_show_on_prominent_ui_surfaces` is false. clusters.push_back( history::Cluster(0, { @@ -1423,10 +1434,13 @@ }, {{u"sensitive", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/false)); + // This cluster should NOT contribute to keywords because it only has 1 + // visible visit. clusters.push_back( history::Cluster(0, { GetHardcodedClusterVisit(2), + GetHardcodedClusterVisit(2, /*score=*/0), }, {{u"singlevisit", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); @@ -1515,13 +1529,13 @@ AddIncompleteVisit(7, 7, yesterday); // Create 4 clusters: - std::vector<history::AnnotatedVisit> visits = - test_clustering_backend_->LastClusteredVisits(); + history::ClusterVisit cluster_visit; + cluster_visit.score = .5; std::vector<history::Cluster> clusters; // 1) A cluster with 4 phrases and 6 words. The next cluster's keywords should // also be cached since we have less than 5 phrases. clusters.push_back( - history::Cluster(0, {{}, {}}, + history::Cluster(0, {cluster_visit, cluster_visit}, {{u"one", history::ClusterKeywordData()}, {u"two", history::ClusterKeywordData()}, {u"three", history::ClusterKeywordData()}, @@ -1530,19 +1544,21 @@ // 2) The 2nd cluster has only 1 visit. Since it's keywords won't be cached, // they should not affect the max. clusters.push_back(history::Cluster( - 0, {{}}, + 0, {cluster_visit}, {{u"ignored not cached", history::ClusterKeywordData()}, {u"elephant penguin kangaroo", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); // 3) With this 3rd cluster, we'll have 5 phrases and 7 words. Now that we've // reached 5 phrases, the next cluster's keywords should not be cached. clusters.push_back( - history::Cluster(0, {{}, {}}, {{u"seven", history::ClusterKeywordData()}}, + history::Cluster(0, {cluster_visit, cluster_visit}, + {{u"seven", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); // 4) The 4th cluster's keywords should not be cached since we've reached 5 // phrases. clusters.push_back( - history::Cluster(0, {{}, {}}, {{u"eight", history::ClusterKeywordData()}}, + history::Cluster(0, {cluster_visit, cluster_visit}, + {{u"eight", history::ClusterKeywordData()}}, /*should_show_on_prominent_ui_surfaces=*/true)); // Kick off cluster request.
diff --git a/components/history_clusters/core/history_clusters_util.cc b/components/history_clusters/core/history_clusters_util.cc index f817eeba..992c9cec 100644 --- a/components/history_clusters/core/history_clusters_util.cc +++ b/components/history_clusters/core/history_clusters_util.cc
@@ -55,6 +55,12 @@ } for (auto& visit : cluster->visits) { + // 0-scored visits should not be considered; they should not be shown even + // if the cluster matches the query; nor should they surface the cluster + // even if the visit matches the query. + if (visit.score == 0) + continue; + bool match_found = false; // Search through the visible elements and highlight match positions. @@ -89,7 +95,7 @@ if (match_found) { visit.matches_search_query = true; - DCHECK_GE(visit.score, 0); + DCHECK_GT(visit.score, 0); total_matching_visit_score += visit.score; } } @@ -276,26 +282,22 @@ } } -void HideAndCullLowScoringVisits(std::vector<history::Cluster>& clusters) { - for (auto& cluster : clusters) { - for (size_t i = 0; i < cluster.visits.size(); ++i) { - auto& visit = cluster.visits[i]; - // Even a 0.0 visit shouldn't be hidden if this is the first visit we - // encounter. The assumption is that the visits are always ranked by score - // in a descending order. - // TODO(crbug.com/1313631): Simplify this after removing "Show More" UI. - if ((visit.score == 0.0 && i != 0) || - (visit.score < GetConfig().min_score_to_always_show_above_the_fold && - i >= GetConfig().num_visits_to_always_show_above_the_fold)) { - visit.hidden = true; - } - } - - if (GetConfig().drop_hidden_visits) { - base::EraseIf(cluster.visits, - [](const auto& visit) { return visit.hidden; }); - } - } +void HideAndCullLowScoringVisits(std::vector<history::Cluster>& clusters, + size_t min_visits) { + DCHECK_GT(min_visits, 0u); + base::EraseIf(clusters, [&](auto& cluster) { + int index = -1; + base::EraseIf(cluster.visits, [&](auto& visit) { + index++; + return visit.score == 0.0 || + (visit.score < + GetConfig().min_score_to_always_show_above_the_fold && + index >= + static_cast<int>( + GetConfig().num_visits_to_always_show_above_the_fold)); + }); + return cluster.visits.size() < min_visits; + }); } void CoalesceRelatedSearches(std::vector<history::Cluster>& clusters) {
diff --git a/components/history_clusters/core/history_clusters_util.h b/components/history_clusters/core/history_clusters_util.h index 976af8c..0954ab7 100644 --- a/components/history_clusters/core/history_clusters_util.h +++ b/components/history_clusters/core/history_clusters_util.h
@@ -57,8 +57,10 @@ std::vector<history::Cluster>& clusters, std::set<GURL>* seen_single_visit_cluster_urls); -// Marks low scoring visits as hidden, and drops them if necessary. -void HideAndCullLowScoringVisits(std::vector<history::Cluster>& clusters); +// Removes low scoring visits and clusters with less than`min_visits` visits +// remaining. +void HideAndCullLowScoringVisits(std::vector<history::Cluster>& clusters, + size_t min_visits); // Coalesces the related searches off of individual visits and places them at // the cluster level with numerical limits defined by flags.
diff --git a/components/history_clusters/core/history_clusters_util_unittest.cc b/components/history_clusters/core/history_clusters_util_unittest.cc index 1609c630..b6a698c 100644 --- a/components/history_clusters/core/history_clusters_util_unittest.cc +++ b/components/history_clusters/core/history_clusters_util_unittest.cc
@@ -4,6 +4,7 @@ #include "components/history_clusters/core/history_clusters_util.h" +#include "base/ranges/algorithm.h" #include "base/strings/stringprintf.h" #include "components/history_clusters/core/config.h" #include "components/history_clusters/core/history_clusters_service_test_api.h" @@ -285,92 +286,53 @@ TEST(HistoryClustersUtilTest, HideAndCullLowScoringVisits) { std::vector<history::Cluster> all_clusters; + auto add_cluster = [&](int64_t cluster_id, std::vector<float> visit_scores) { + history::Cluster cluster; + cluster.cluster_id = cluster_id; + base::ranges::transform(visit_scores, std::back_inserter(cluster.visits), + [&](const auto& visit_score) { + return GetHardcodedClusterVisit(1, visit_score); + }); + cluster.keyword_to_data_map = {{u"keyword", history::ClusterKeywordData()}}; + all_clusters.push_back(cluster); + }; + // High scoring visits should always be above the fold. - history::Cluster cluster1; - cluster1.cluster_id = 4; - cluster1.visits.push_back(GetHardcodedClusterVisit(1, 1)); - cluster1.visits.push_back(GetHardcodedClusterVisit(1, .8)); - cluster1.visits.push_back(GetHardcodedClusterVisit(1, .5)); - cluster1.visits.push_back(GetHardcodedClusterVisit(1, .5)); - cluster1.visits.push_back(GetHardcodedClusterVisit(1, .5)); - cluster1.keyword_to_data_map = {{u"keyword", history::ClusterKeywordData()}}; + add_cluster(4, {1, .8, .5, .5, .5}); // Low scoring visits should be above the fold only if they're one of top 4. - history::Cluster cluster2; - cluster2.cluster_id = 6; - cluster2.visits.push_back(GetHardcodedClusterVisit(1, .4)); - cluster2.visits.push_back(GetHardcodedClusterVisit(1, .4)); - cluster2.visits.push_back(GetHardcodedClusterVisit(1, .4)); - cluster2.visits.push_back(GetHardcodedClusterVisit(1, .4)); - cluster2.visits.push_back(GetHardcodedClusterVisit(1, .4)); - cluster2.keyword_to_data_map = {{u"keyword", history::ClusterKeywordData()}}; + add_cluster(6, {.4, .4, .4, .4, .4}); - // 0 scoring visits should be above the fold only if they're 1st. - history::Cluster cluster3; - cluster3.cluster_id = 8; - cluster3.visits.push_back(GetHardcodedClusterVisit(1, 0.0)); - cluster3.visits.push_back(GetHardcodedClusterVisit(1, 0.0)); - cluster3.keyword_to_data_map = {{u"keyword", history::ClusterKeywordData()}}; + // 0 scoring visits should never be above the fold. + add_cluster(8, {0, 0, .8, .8}); - all_clusters.push_back(cluster1); - all_clusters.push_back(cluster2); - all_clusters.push_back(cluster3); + // Clusters with 1 visit after filtering should be removed. + add_cluster(10, {.8, 0}); - { - Config config; - config.drop_hidden_visits = true; - SetConfigForTesting(config); + // Clusters with 0 visits after filtering should be removed. + add_cluster(12, {0, 0}); - auto clusters = all_clusters; - HideAndCullLowScoringVisits(clusters); + auto clusters = all_clusters; + // Try with `min_visits` = 2. This is how query-less state behaves. + HideAndCullLowScoringVisits(clusters, 2); + ASSERT_EQ(clusters.size(), 3u); - EXPECT_EQ(clusters[0].cluster_id, 4); - auto& visits = clusters[0].visits; - ASSERT_EQ(visits.size(), 5u); - EXPECT_EQ(visits[0].hidden, false); - EXPECT_EQ(visits[1].hidden, false); - EXPECT_EQ(visits[2].hidden, false); - EXPECT_EQ(visits[3].hidden, false); - EXPECT_EQ(visits[4].hidden, false); + EXPECT_EQ(clusters[0].cluster_id, 4); + EXPECT_EQ(clusters[0].visits.size(), 5u); - EXPECT_EQ(clusters[1].cluster_id, 6); - visits = clusters[1].visits; - ASSERT_EQ(visits.size(), 4u); - EXPECT_EQ(visits[0].hidden, false); - EXPECT_EQ(visits[1].hidden, false); - EXPECT_EQ(visits[2].hidden, false); - EXPECT_EQ(visits[3].hidden, false); + EXPECT_EQ(clusters[1].cluster_id, 6); + EXPECT_EQ(clusters[1].visits.size(), 4u); - EXPECT_EQ(clusters[2].cluster_id, 8); - ASSERT_EQ(clusters[2].visits.size(), 1u); - EXPECT_EQ(clusters[2].visits[0].hidden, false); - } + EXPECT_EQ(clusters[2].cluster_id, 8); + EXPECT_EQ(clusters[2].visits.size(), 2u); - { - Config config; - config.drop_hidden_visits = false; - SetConfigForTesting(config); - - auto clusters = all_clusters; - HideAndCullLowScoringVisits(clusters); - - EXPECT_EQ(clusters[0].cluster_id, 4); - EXPECT_EQ(clusters[0].visits.size(), 5u); - - EXPECT_EQ(clusters[1].cluster_id, 6); - const auto& visits = clusters[1].visits; - ASSERT_EQ(visits.size(), 5u); - EXPECT_EQ(visits[0].hidden, false); - EXPECT_EQ(visits[1].hidden, false); - EXPECT_EQ(visits[2].hidden, false); - EXPECT_EQ(visits[3].hidden, false); - EXPECT_EQ(visits[4].hidden, true); - - EXPECT_EQ(clusters[2].cluster_id, 8); - ASSERT_EQ(clusters[2].visits.size(), 2u); - EXPECT_EQ(clusters[2].visits[0].hidden, false); - EXPECT_EQ(clusters[2].visits[1].hidden, true); - } + // Try with `min_visits` = 1. This is how query state behaves. + clusters = all_clusters; + HideAndCullLowScoringVisits(clusters, 1); + // Cluster 10, with 1 visit after filtering should no longer be removed. + ASSERT_EQ(clusters.size(), 4u); + EXPECT_EQ(clusters[3].cluster_id, 10); + EXPECT_EQ(clusters[3].visits.size(), 1u); } TEST(HistoryClustersUtilTest, CoalesceRelatedSearches) {
diff --git a/components/history_clusters/ui/query_clusters_state.cc b/components/history_clusters/ui/query_clusters_state.cc index 2c6c3f0..a2fadeb 100644 --- a/components/history_clusters/ui/query_clusters_state.cc +++ b/components/history_clusters/ui/query_clusters_state.cc
@@ -46,8 +46,8 @@ // We have to do this AFTER applying the search query, because applying the // search query re-scores matching visits to promote them above non-matching - // visits. - HideAndCullLowScoringVisits(clusters); + // visits. Show 1-visit clusters only in query mode. + HideAndCullLowScoringVisits(clusters, query_.empty() ? 2 : 1); // Do this AFTER we cull the low scoring visits, so those visits don't get // their related searches coalesced onto the cluster level. CoalesceRelatedSearches(clusters);
diff --git a/components/history_clusters_strings.grdp b/components/history_clusters_strings.grdp index f788784d..e8b447f 100644 --- a/components/history_clusters_strings.grdp +++ b/components/history_clusters_strings.grdp
@@ -33,6 +33,9 @@ <message name="IDS_HISTORY_CLUSTERS_CLUSTER_LABEL_MULTIPLE_HOSTNAMES" desc="The header used for Journeys that are anchored by multiple host names."> <ph name="HOST_NAME">$1<ex>google.com</ex> and more</ph> </message> + <message name="IDS_HISTORY_CLUSTERS_HIDE_PAGE" desc="Label of the item in drop-down menu that allows the user to hide a history item."> + Hide item + </message> <message name="IDS_HISTORY_CLUSTERS_LOAD_MORE_BUTTON_LABEL" desc="A label for the button that loads more history clusters at the bottom of the history clusters list."> Load more </message> @@ -61,7 +64,7 @@ <message name="IDS_HISTORY_CLUSTERS_REMOVE_ALL_ITEMS" desc="Label of the item in drop-down menu that allows the user to remove a group of history items."> Remove all from history </message> - <message name="IDS_HISTORY_CLUSTERS_REMOVE_PAGE" desc="Label of the item in drop-down menu that allows the user to remove a history item"> + <message name="IDS_HISTORY_CLUSTERS_REMOVE_PAGE" desc="Label of the item in drop-down menu that allows the user to remove a history item."> Remove from history </message> <message name="IDS_HISTORY_CLUSTERS_REMOVE_ITEM_TOAST" desc="Confirmation message shown after user successfully removes one history item from the item's drop-down menu.">
diff --git a/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HIDE_PAGE.png.sha1 b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HIDE_PAGE.png.sha1 new file mode 100644 index 0000000..c34a0c7 --- /dev/null +++ b/components/history_clusters_strings_grdp/IDS_HISTORY_CLUSTERS_HIDE_PAGE.png.sha1
@@ -0,0 +1 @@ +309ba82c08fde04abb43a11844b15c8c97039f6a \ No newline at end of file
diff --git a/components/live_caption/BUILD.gn b/components/live_caption/BUILD.gn index 0b4c8e1..e28ceb69 100644 --- a/components/live_caption/BUILD.gn +++ b/components/live_caption/BUILD.gn
@@ -12,8 +12,6 @@ "caption_bubble_context_remote.h", "caption_bubble_controller.h", "caption_bubble_session_observer.h", - "live_caption_controller.cc", - "live_caption_controller.h", ] deps = [ @@ -60,6 +58,13 @@ "live_caption_ui_remote_driver.h", ] } # is_chromeos_ash + + if (!is_chromeos_lacros) { + sources += [ + "live_caption_controller.cc", + "live_caption_controller.h", + ] + } } static_library("live_translate") {
diff --git a/components/metrics/cloned_install_detector.cc b/components/metrics/cloned_install_detector.cc index 4a4cf83..6f36a0f 100644 --- a/components/metrics/cloned_install_detector.cc +++ b/components/metrics/cloned_install_detector.cc
@@ -8,6 +8,7 @@ #include <string> +#include "base/callback_list.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" @@ -78,9 +79,11 @@ MachineIdState id_state = ID_NO_STORED_VALUE; if (local_state->HasPrefPath(prefs::kMetricsMachineId)) { if (local_state->GetInteger(prefs::kMetricsMachineId) != hashed_id) { + DCHECK(!detected_this_session_); id_state = ID_CHANGED; detected_this_session_ = true; local_state->SetBoolean(prefs::kMetricsResetIds, true); + callback_list_.Notify(); } else { id_state = ID_UNCHANGED; } @@ -109,6 +112,23 @@ return detected_this_session_; } +base::CallbackListSubscription +ClonedInstallDetector::AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) { + if (detected_this_session_) { + // If this install has already been detected as cloned, run the callback + // immediately. + std::move(callback).Run(); + return base::CallbackListSubscription(); + } + return callback_list_.Add(std::move(callback)); +} + +void ClonedInstallDetector::SaveMachineIdForTesting(PrefService* local_state, + const std::string& raw_id) { + SaveMachineId(local_state, raw_id); +} + // static void ClonedInstallDetector::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref(prefs::kMetricsResetIds, false);
diff --git a/components/metrics/cloned_install_detector.h b/components/metrics/cloned_install_detector.h index dc9b1ad..0560b7797 100644 --- a/components/metrics/cloned_install_detector.h +++ b/components/metrics/cloned_install_detector.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_METRICS_CLONED_INSTALL_DETECTOR_H_ #define COMPONENTS_METRICS_CLONED_INSTALL_DETECTOR_H_ +#include "base/callback_list.h" +#include "base/functional/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" @@ -59,13 +61,28 @@ // session. bool ClonedInstallDetectedInCurrentSession() const; + // Adds a callback that is run if this install is detected as cloned during + // this session. If this is called after the detection had already occurred, + // the callback is run immediately. + base::CallbackListSubscription AddOnClonedInstallDetectedCallback( + base::OnceClosure callback); + + // Wrapper around SaveMachineId(). Used for testing in UKM (the tests cannot + // be declared as friends since they live in a different namespace). + void SaveMachineIdForTesting(PrefService* local_state, + const std::string& raw_id); + private: FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, SaveId); FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, DetectClone); FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, ShouldResetClientIds); FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, ClonedInstallDetectedInCurrentSession); + FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, + ClonedInstallDetectedCallback); FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, CheckProviderResetIds); + FRIEND_TEST_ALL_PREFIXES(MetricsServiceTestWithFeatures, + PurgeLogsOnClonedInstallDetected); // Converts raw_id into a 24-bit hash and stores the hash in |local_state|. // |raw_id| is not a const ref because it's passed from a cross-thread post @@ -79,6 +96,8 @@ // client id and should reset client ids as a result. bool should_reset_client_ids_ = false; + base::OnceClosureList callback_list_; + base::WeakPtrFactory<ClonedInstallDetector> weak_ptr_factory_{this}; };
diff --git a/components/metrics/cloned_install_detector_unittest.cc b/components/metrics/cloned_install_detector_unittest.cc index f9a66766..3914ce8 100644 --- a/components/metrics/cloned_install_detector_unittest.cc +++ b/components/metrics/cloned_install_detector_unittest.cc
@@ -4,6 +4,8 @@ #include "components/metrics/cloned_install_detector.h" +#include "base/callback_list.h" +#include "base/test/bind.h" #include "components/metrics/machine_id_provider.h" #include "components/metrics/metrics_pref_names.h" #include "components/prefs/testing_pref_service.h" @@ -82,4 +84,38 @@ EXPECT_TRUE(detector.ClonedInstallDetectedInCurrentSession()); } +TEST(ClonedInstallDetectorTest, ClonedInstallDetectedCallback) { + TestingPrefServiceSimple prefs; + ClonedInstallDetector::RegisterPrefs(prefs.registry()); + + ClonedInstallDetector detector; + + // Set up a callback that will set |callback_called| to true when a cloned + // install is detected. + bool callback_called = false; + base::CallbackListSubscription subscription = + detector.AddOnClonedInstallDetectedCallback(base::BindLambdaForTesting( + [&callback_called] { callback_called = true; })); + + // Save a machine id that will not cause a clone to be detected. + prefs.SetInteger(prefs::kMetricsMachineId, kTestHashedId); + detector.SaveMachineId(&prefs, kTestRawId); + EXPECT_FALSE(detector.ClonedInstallDetectedInCurrentSession()); + EXPECT_FALSE(callback_called); + + // Save a machine id that will cause a clone to be detected. + prefs.SetInteger(prefs::kMetricsMachineId, kTestHashedId + 1); + detector.SaveMachineId(&prefs, kTestRawId); + EXPECT_TRUE(detector.ClonedInstallDetectedInCurrentSession()); + EXPECT_TRUE(callback_called); + + // Verify that if a callback is added after the cloned install has been + // detected, it is called immediately. + bool callback_called2 = false; + base::CallbackListSubscription subscription2 = + detector.AddOnClonedInstallDetectedCallback(base::BindLambdaForTesting( + [&callback_called2] { callback_called2 = true; })); + EXPECT_TRUE(callback_called2); +} + } // namespace metrics
diff --git a/components/metrics/metrics_log_store.cc b/components/metrics/metrics_log_store.cc index e496888..5ec791f 100644 --- a/components/metrics/metrics_log_store.cc +++ b/components/metrics/metrics_log_store.cc
@@ -88,6 +88,14 @@ uncompressed_log_size); } +void MetricsLogStore::Purge() { + initial_log_queue_.Purge(); + ongoing_log_queue_.Purge(); + if (has_alternate_ongoing_log_store()) { + alternate_ongoing_log_queue_->Purge(); + } +} + const std::string& MetricsLogStore::GetSigningKeyForLogType( MetricsLog::LogType log_type) { return GetLogStoreForLogType(log_type)->signing_key();
diff --git a/components/metrics/metrics_log_store.h b/components/metrics/metrics_log_store.h index 76a0316..237e8541 100644 --- a/components/metrics/metrics_log_store.h +++ b/components/metrics/metrics_log_store.h
@@ -96,6 +96,9 @@ size_t uncompressed_log_size, MetricsLog::LogType log_type); + // Deletes all logs, in memory and on disk. + void Purge(); + // Returns the signing key that should be used to create a signature for a // log of the given |log_type|. We don't "simply" return the signing key that // was passed during the construction of this object, because although
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index 83ea8ef..ff57004 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -291,6 +291,11 @@ logs_event_manager_.AddObserver(logs_event_observer_.get()); } + cloned_install_subscription_ = + state_manager->AddOnClonedInstallDetectedCallback( + base::BindOnce(&MetricsService::OnClonedInstallDetected, + self_ptr_factory_.GetWeakPtr())); + RegisterMetricsProvider( std::make_unique<StabilityMetricsProvider>(local_state_)); @@ -1355,6 +1360,14 @@ : state_ < SENDING_LOGS; } +void MetricsService::OnClonedInstallDetected() { + // Purge all logs, as they may come from a previous install. Unfortunately, + // since the cloned install detector works asynchronously, it is possible that + // this is called after logs were already sent. However, practically speaking, + // this should not happen, since logs are only sent late into the session. + reporting_service_.metrics_log_store()->Purge(); +} + // static MetricsService::FinalizedLog MetricsService::SnapshotDeltasAndFinalizeLog( std::unique_ptr<MetricsLogHistogramWriter> log_histogram_writer,
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h index 78917ef..8802316 100644 --- a/components/metrics/metrics_service.h +++ b/components/metrics/metrics_service.h
@@ -532,6 +532,9 @@ // Returns whether it is too early to close a log. bool IsTooEarlyToCloseLog(); + // Called if this install is detected as cloned. + void OnClonedInstallDetected(); + // Snapshots histogram deltas using the passed |log_histogram_writer| and then // finalizes |log| by calling FinalizeLog(). |log|, |current_app_version| and // |signing_key| are used to finalize the log (see FinalizeLog()). @@ -638,6 +641,10 @@ // A set of observers that keeps track of the metrics reporting state. base::RepeatingCallbackList<void(bool)> enablement_observers_; + // Subscription for a callback that runs if this install is detected as + // cloned. + base::CallbackListSubscription cloned_install_subscription_; + #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) // Indicates whether OnAppEnterForeground() (true) or OnAppEnterBackground // (false) was called.
diff --git a/components/metrics/metrics_service_client.cc b/components/metrics/metrics_service_client.cc index 0cde959..a1458a7 100644 --- a/components/metrics/metrics_service_client.cc +++ b/components/metrics/metrics_service_client.cc
@@ -150,6 +150,12 @@ return false; } +base::CallbackListSubscription +MetricsServiceClient::AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) { + return base::CallbackListSubscription(); +} + MetricsLogStore::StorageLimits MetricsServiceClient::GetStorageLimits() const { return { /*min_initial_log_queue_count=*/kMinInitialLogQueueCount,
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h index 39e3b91..217e3c13 100644 --- a/components/metrics/metrics_service_client.h +++ b/components/metrics/metrics_service_client.h
@@ -9,6 +9,7 @@ #include <memory> #include <string> +#include "base/callback_list.h" #include "base/functional/callback.h" #include "base/time/time.h" #include "components/metrics/metrics_log_store.h" @@ -133,11 +134,6 @@ // Called when loading state changed, e.g. start/stop loading. virtual void LoadingStateChanged(bool is_loading) {} - // Called on renderer crashes in some embedders (e.g., those that do not use - // //content and thus do not have //content's notification system available - // as a mechanism for observing renderer crashes). - virtual void OnRendererProcessCrash() {} - // Returns whether metrics reporting is managed by policy. virtual bool IsReportingPolicyManaged(); @@ -173,6 +169,9 @@ // Checks if the cloned install detector says that client ids should be reset. virtual bool ShouldResetClientIdsOnClonedInstall(); + virtual base::CallbackListSubscription AddOnClonedInstallDetectedCallback( + base::OnceClosure callback); + // Specifies local log storage requirements and restrictions. virtual MetricsLogStore::StorageLimits GetStorageLimits() const;
diff --git a/components/metrics/metrics_service_unittest.cc b/components/metrics/metrics_service_unittest.cc index 1e5f6115..5c32d40 100644 --- a/components/metrics/metrics_service_unittest.cc +++ b/components/metrics/metrics_service_unittest.cc
@@ -31,6 +31,7 @@ #include "build/build_config.h" #include "components/metrics/clean_exit_beacon.h" #include "components/metrics/client_info.h" +#include "components/metrics/cloned_install_detector.h" #include "components/metrics/environment_recorder.h" #include "components/metrics/log_decoder.h" #include "components/metrics/metrics_features.h" @@ -1290,6 +1291,51 @@ EXPECT_FALSE(enabled.value()); } +// Verifies that when a cloned install is detected, logs are purged. +TEST_P(MetricsServiceTestWithFeatures, PurgeLogsOnClonedInstallDetected) { + EnableMetricsReporting(); + TestMetricsServiceClient client; + TestMetricsService service(GetMetricsStateManager(), &client, + GetLocalState()); + service.InitializeMetricsRecordingState(); + + // Store various logs. + MetricsLogStore* test_log_store = service.LogStoreForTest(); + test_log_store->StoreLog("dummy log data", MetricsLog::ONGOING_LOG, + LogMetadata()); + test_log_store->StageNextLog(); + test_log_store->StoreLog("more dummy log data", MetricsLog::ONGOING_LOG, + LogMetadata()); + test_log_store->StoreLog("dummy stability log", + MetricsLog::INITIAL_STABILITY_LOG, LogMetadata()); + test_log_store->SetAlternateOngoingLogStore(InitializeTestLogStoreAndGet()); + test_log_store->StoreLog("dummy log for alternate ongoing log store", + MetricsLog::ONGOING_LOG, LogMetadata()); + EXPECT_TRUE(test_log_store->has_staged_log()); + EXPECT_TRUE(test_log_store->has_unsent_logs()); + + ClonedInstallDetector* cloned_install_detector = + GetMetricsStateManager()->cloned_install_detector_for_testing(); + + static constexpr char kTestRawId[] = "test"; + // Hashed machine id for |kTestRawId|. + static constexpr int kTestHashedId = 2216819; + + // Save a machine id that will not cause a clone to be detected. + GetLocalState()->SetInteger(prefs::kMetricsMachineId, kTestHashedId); + cloned_install_detector->SaveMachineId(GetLocalState(), kTestRawId); + // Verify that the logs are still present. + EXPECT_TRUE(test_log_store->has_staged_log()); + EXPECT_TRUE(test_log_store->has_unsent_logs()); + + // Save a machine id that will cause a clone to be detected. + GetLocalState()->SetInteger(prefs::kMetricsMachineId, kTestHashedId + 1); + cloned_install_detector->SaveMachineId(GetLocalState(), kTestRawId); + // Verify that the logs were purged. + EXPECT_FALSE(test_log_store->has_staged_log()); + EXPECT_FALSE(test_log_store->has_unsent_logs()); +} + #if BUILDFLAG(IS_CHROMEOS_LACROS) // ResetClientId is only enabled on certain targets. TEST_P(MetricsServiceTestWithFeatures, SetClientIdToExternalId) {
diff --git a/components/metrics/metrics_state_manager.cc b/components/metrics/metrics_state_manager.cc index 0f8c32d..7fdd69f 100644 --- a/components/metrics/metrics_state_manager.cc +++ b/components/metrics/metrics_state_manager.cc
@@ -533,6 +533,13 @@ return cloned_install_detector_.ShouldResetClientIds(local_state_); } +base::CallbackListSubscription +MetricsStateManager::AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) { + return cloned_install_detector_.AddOnClonedInstallDetectedCallback( + std::move(callback)); +} + std::unique_ptr<const variations::EntropyProviders> MetricsStateManager::CreateEntropyProviders() { return std::make_unique<variations::EntropyProviders>(
diff --git a/components/metrics/metrics_state_manager.h b/components/metrics/metrics_state_manager.h index 4db65e8..c6aa6f0 100644 --- a/components/metrics/metrics_state_manager.h +++ b/components/metrics/metrics_state_manager.h
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include "base/callback_list.h" #include "base/files/file_path.h" #include "base/functional/callback.h" #include "base/gtest_prod_util.h" @@ -172,6 +173,10 @@ // Checks if the cloned install detector says that client ids should be reset. bool ShouldResetClientIdsOnClonedInstall(); + // Wrapper around ClonedInstallDetector::AddOnClonedInstallDetectedCallback(). + base::CallbackListSubscription AddOnClonedInstallDetectedCallback( + base::OnceClosure callback); + // Creates entropy providers for trial randomization. // // If this StateManager supports high entropy randomization, and there is @@ -181,6 +186,10 @@ // only returns an entropy provider that is based on a low entropy source. std::unique_ptr<const variations::EntropyProviders> CreateEntropyProviders(); + ClonedInstallDetector* cloned_install_detector_for_testing() { + return &cloned_install_detector_; + } + // Creates the MetricsStateManager, enforcing that only a single instance // of the class exists at a time. Returns nullptr if an instance exists // already.
diff --git a/components/mirroring/mojom/session_parameters.mojom b/components/mirroring/mojom/session_parameters.mojom index 6979123..d9ef4b4 100644 --- a/components/mirroring/mojom/session_parameters.mojom +++ b/components/mirroring/mojom/session_parameters.mojom
@@ -51,13 +51,6 @@ // querying the receiver device for its capabilities. bool is_remote_playback; - // The interval elapsed before the service requests a refresh frame from the - // video capture source. Refresh frames help the video encoder converge to a - // quality image when the video source is static content. Omission of this - // parameter uses the default value defined in mirror_settings.cc. A value of - // zero disables refresh frame requests. - mojo_base.mojom.TimeDelta? refresh_interval; - // If true, all video frames sent will be letterboxed/pillarboxed to fit the // aspect ratio of the negotiated resolution. This is to allow letterboxing // to be selectively applied to receivers that have outstanding bugs with
diff --git a/components/mirroring/service/mirror_settings.cc b/components/mirroring/service/mirror_settings.cc index 076b687..5e56128 100644 --- a/components/mirroring/service/mirror_settings.cc +++ b/components/mirroring/service/mirror_settings.cc
@@ -28,15 +28,6 @@ // TODO(openscreen/44): Re-enable in port to Open Screen. constexpr base::TimeDelta kDefaultPlayoutDelay = base::Milliseconds(400); -// The default "slow" interval since the last video frame was received from the -// video source, before requesting a refresh frame. -// TODO(crbug.com/1394392): Remove after launching CastFastRefreshFrames. -constexpr base::TimeDelta kDefaultSlowRefreshInterval = base::Milliseconds(250); - -// The default "fast" interval since the last video frame was received from the -// video source, before requesting a refresh frame. -constexpr base::TimeDelta kDefaultFastRefreshInterval = base::Milliseconds(50); - constexpr int kAudioTimebase = 48000; constexpr int kVidoTimebase = 90000; constexpr int kAudioChannels = 2; @@ -89,12 +80,7 @@ : min_width_(kMinWidth), min_height_(kMinHeight), max_width_(kMaxWidth), - max_height_(kMaxHeight) { - refresh_interval_ = - base::FeatureList::IsEnabled(features::kCastFastRefreshFrames) - ? kDefaultFastRefreshInterval - : kDefaultSlowRefreshInterval; -} + max_height_(kMaxHeight) {} MirrorSettings::~MirrorSettings() {}
diff --git a/components/mirroring/service/mirror_settings.h b/components/mirroring/service/mirror_settings.h index b5c457eb..4684e3f 100644 --- a/components/mirroring/service/mirror_settings.h +++ b/components/mirroring/service/mirror_settings.h
@@ -16,6 +16,10 @@ namespace mirroring { +// The interval since the last video frame was received from the video source, +// before requesting a refresh frame. +constexpr base::TimeDelta kFrameRefreshInterval = base::Milliseconds(50); + // Holds the default settings for a mirroring session. This class provides the // audio/video configs that this sender supports. And also provides the // audio/video constraints used for capturing. @@ -62,7 +66,7 @@ int max_width_; int max_height_; bool enable_sender_side_letterboxing_ = true; - base::TimeDelta refresh_interval_; + base::TimeDelta refresh_interval_{kFrameRefreshInterval}; }; } // namespace mirroring
diff --git a/components/mirroring/service/mirroring_features.cc b/components/mirroring/service/mirroring_features.cc index 5f88b8b..834ef91e 100644 --- a/components/mirroring/service/mirroring_features.cc +++ b/components/mirroring/service/mirroring_features.cc
@@ -23,14 +23,5 @@ "CastDisableModelNameCheck", base::FEATURE_ENABLED_BY_DEFAULT); -// This changes the default interval for refresh frame requests when the capture -// source is showing static content from the slower default to a faster one. -// -// This feature is overridden by the Chrome command line flag -// --mirroring-refresh-interval-ms=<num>. -BASE_FEATURE(kCastFastRefreshFrames, - "CastFastRefreshFrames", - base::FEATURE_ENABLED_BY_DEFAULT); - } // namespace features } // namespace mirroring
diff --git a/components/mirroring/service/openscreen_session_host.cc b/components/mirroring/service/openscreen_session_host.cc index 353f441..ddf4a36 100644 --- a/components/mirroring/service/openscreen_session_host.cc +++ b/components/mirroring/service/openscreen_session_host.cc
@@ -267,11 +267,6 @@ mirror_settings_.SetResolutionConstraints(max_resolution.width(), max_resolution.height()); - - if (session_params_.refresh_interval) { - mirror_settings_.set_refresh_interval(*(session_params_.refresh_interval)); - } - resource_provider_->GetNetworkContext( network_context_.BindNewPipeAndPassReceiver());
diff --git a/components/mirroring/service/session.cc b/components/mirroring/service/session.cc index 1f4e3c44f..ccc8655 100644 --- a/components/mirroring/service/session.cc +++ b/components/mirroring/service/session.cc
@@ -380,10 +380,6 @@ mirror_settings_.SetResolutionConstraints(max_resolution.width(), max_resolution.height()); - if (session_params_.refresh_interval) { - mirror_settings_.set_refresh_interval(*(session_params_.refresh_interval)); - } - resource_provider_->GetNetworkContext( network_context_.BindNewPipeAndPassReceiver()); @@ -784,9 +780,15 @@ weak_factory_.GetWeakPtr()), base::BindRepeating(&Session::ProcessFeedback, weak_factory_.GetWeakPtr())); + video_stream_ = std::make_unique<VideoRtpStream>( std::move(video_sender), weak_factory_.GetWeakPtr(), mirror_settings_.refresh_interval()); + LogInfoMessage(base::StringPrintf( + "Created video stream with refresh interval of %d ms", + static_cast<int>( + mirror_settings_.refresh_interval().InMilliseconds()))); + if (!video_capture_client_) { mojo::PendingRemote<media::mojom::VideoCaptureHost> video_host; resource_provider_->GetVideoCaptureHost(
diff --git a/components/mirroring/service/video_capture_client.cc b/components/mirroring/service/video_capture_client.cc index 19b420d..3427009 100644 --- a/components/mirroring/service/video_capture_client.cc +++ b/components/mirroring/service/video_capture_client.cc
@@ -23,7 +23,7 @@ // TODO(https://crbug.com/1406986): Investigate whether there's a better way // to accomplish this (without using UnguessableToken::Deserialize). static const base::UnguessableToken device_id( - base::UnguessableToken::Deserialize2(1, 1).value()); + base::UnguessableToken::Deserialize(1, 1).value()); return device_id; } @@ -32,7 +32,7 @@ // TODO(https://crbug.com/1406986): Investigate whether there's a better way // to accomplish this (without using UnguessableToken::Deserialize). static const base::UnguessableToken session_id( - base::UnguessableToken::Deserialize2(1, 1).value()); + base::UnguessableToken::Deserialize(1, 1).value()); return session_id; }
diff --git a/components/network_hints/browser/simple_network_hints_handler_impl.cc b/components/network_hints/browser/simple_network_hints_handler_impl.cc index ea185924e..9478dad 100644 --- a/components/network_hints/browser/simple_network_hints_handler_impl.cc +++ b/components/network_hints/browser/simple_network_hints_handler_impl.cc
@@ -46,7 +46,9 @@ // has completed or mojo connection error has happened. class DnsLookupRequest : public network::ResolveHostClientBase { public: - DnsLookupRequest(int render_process_id, int render_frame_id, const GURL& url) + DnsLookupRequest(int render_process_id, + int render_frame_id, + const url::SchemeHostPort& url) : render_process_id_(render_process_id), render_frame_id_(render_frame_id), url_(url) {} @@ -72,7 +74,6 @@ } DCHECK(!receiver_.is_bound()); - url::SchemeHostPort scheme_host_port(url_); network::mojom::ResolveHostParametersPtr resolve_host_parameters = network::mojom::ResolveHostParameters::New(); // Lets the host resolver know it can be de-prioritized. @@ -87,8 +88,7 @@ render_frame_host->GetProcess() ->GetStoragePartition() ->GetNetworkContext() - ->ResolveHost(network::mojom::HostResolverHost::NewSchemeHostPort( - std::move(scheme_host_port)), + ->ResolveHost(network::mojom::HostResolverHost::NewSchemeHostPort(url_), GetPendingNetworkAnonymizationKey(render_frame_host), std::move(resolve_host_parameters), receiver_.BindNewPipeAndPassRemote()); @@ -106,7 +106,7 @@ const absl::optional<net::AddressList>& resolved_addresses, const absl::optional<net::HostResolverEndpointResults>& endpoint_results_with_metadata) override { - VLOG(2) << __FUNCTION__ << ": " << url_.spec() + VLOG(2) << __FUNCTION__ << ": " << url_.Serialize() << ", result=" << resolve_error_info.error; request_.reset(); } @@ -114,7 +114,7 @@ mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this}; const int render_process_id_; const int render_frame_id_; - const GURL url_; + const url::SchemeHostPort url_; std::unique_ptr<DnsLookupRequest> request_; }; @@ -140,8 +140,9 @@ std::move(receiver)); } -void SimpleNetworkHintsHandlerImpl::PrefetchDNS(const std::vector<GURL>& urls) { - for (const GURL& url : urls) { +void SimpleNetworkHintsHandlerImpl::PrefetchDNS( + const std::vector<url::SchemeHostPort>& urls) { + for (const url::SchemeHostPort& url : urls) { std::unique_ptr<DnsLookupRequest> request = std::make_unique<DnsLookupRequest>(render_process_id_, render_frame_id_, url); @@ -150,10 +151,9 @@ } } -void SimpleNetworkHintsHandlerImpl::Preconnect(const GURL& url, +void SimpleNetworkHintsHandlerImpl::Preconnect(const url::SchemeHostPort& url, bool allow_credentials) { - if (!url.is_valid() || !url.has_host() || !url.has_scheme() || - !url.SchemeIsHTTPOrHTTPS()) { + if (url.scheme() != url::kHttpScheme && url.scheme() != url::kHttpsScheme) { return; } @@ -168,7 +168,7 @@ render_frame_host->GetStoragePartition() ->GetNetworkContext() - ->PreconnectSockets(/*num_streams=*/1, url, allow_credentials, + ->PreconnectSockets(/*num_streams=*/1, url.GetURL(), allow_credentials, network_anonymization_key); }
diff --git a/components/network_hints/browser/simple_network_hints_handler_impl.h b/components/network_hints/browser/simple_network_hints_handler_impl.h index 3a65ae5..0fff5b1 100644 --- a/components/network_hints/browser/simple_network_hints_handler_impl.h +++ b/components/network_hints/browser/simple_network_hints_handler_impl.h
@@ -30,8 +30,9 @@ mojo::PendingReceiver<mojom::NetworkHintsHandler> receiver); // mojom::NetworkHintsHandler methods: - void PrefetchDNS(const std::vector<GURL>& urls) override; - void Preconnect(const GURL& url, bool allow_credentials) override; + void PrefetchDNS(const std::vector<url::SchemeHostPort>& urls) override; + void Preconnect(const url::SchemeHostPort& url, + bool allow_credentials) override; private: const int render_process_id_;
diff --git a/components/network_hints/common/BUILD.gn b/components/network_hints/common/BUILD.gn index 6f810a9..ddc0c41 100644 --- a/components/network_hints/common/BUILD.gn +++ b/components/network_hints/common/BUILD.gn
@@ -8,5 +8,5 @@ generate_java = false sources = [ "network_hints.mojom" ] - public_deps = [ "//url/mojom:url_mojom_gurl" ] + public_deps = [ "//url/mojom:url_mojom_scheme_host_port" ] }
diff --git a/components/network_hints/common/network_hints.mojom b/components/network_hints/common/network_hints.mojom index 6f03c475..8818448 100644 --- a/components/network_hints/common/network_hints.mojom +++ b/components/network_hints/common/network_hints.mojom
@@ -4,15 +4,15 @@ module network_hints.mojom; -import "url/mojom/url.mojom"; +import "url/mojom/scheme_host_port.mojom"; // This interface is used by the renderer to provide hints to the browser. interface NetworkHintsHandler { // This method is called periodically with a hint to perform DNS lookups for // a batch set of urls. - PrefetchDNS(array<url.mojom.Url> url_list); + PrefetchDNS(array<url.mojom.SchemeHostPort> url_list); // This method is called periodically with a hint to preconnect to the origin // of the specified url. - Preconnect(url.mojom.Url url, bool allow_credentials); + Preconnect(url.mojom.SchemeHostPort url, bool allow_credentials); };
diff --git a/components/network_hints/renderer/web_prescient_networking_impl.cc b/components/network_hints/renderer/web_prescient_networking_impl.cc index ada53ee..5f745b9 100644 --- a/components/network_hints/renderer/web_prescient_networking_impl.cc +++ b/components/network_hints/renderer/web_prescient_networking_impl.cc
@@ -14,9 +14,9 @@ void ForwardToHandler(mojo::Remote<mojom::NetworkHintsHandler>* handler, const std::vector<std::string>& names) { - std::vector<GURL> urls; + std::vector<url::SchemeHostPort> urls; for (const auto& name : names) { - urls.emplace_back("http://" + name); + urls.emplace_back(url::kHttpScheme, name, 80); } handler->get()->PrefetchDNS(urls); } @@ -39,17 +39,18 @@ if (!gurl.is_valid() || !gurl.has_host()) { return; } + url::SchemeHostPort scheme_host_pair(gurl); if (base::FeatureList::IsEnabled(network::features::kPrefetchDNSWithURL)) { - std::vector<GURL> urls; - urls.push_back(std::move(gurl)); + std::vector<url::SchemeHostPort> urls; + urls.push_back(std::move(scheme_host_pair)); handler_->PrefetchDNS(urls); // TODO(jam): If this launches remove DnsQueue and RendererDnsPrefetch // which are no longer needed. They were from a feature which existed // at launch but not anymore that prefetched DNS for every link on a page. } else { - auto host_piece = gurl.host_piece(); - dns_prefetch_.Resolve(host_piece.data(), host_piece.length()); + const auto& host = scheme_host_pair.host(); + dns_prefetch_.Resolve(host.data(), host.length()); } } @@ -60,7 +61,9 @@ if (!url.IsValid()) return; - handler_->Preconnect(url, allow_credentials); + GURL gurl(url); + url::SchemeHostPort scheme_host_pair(gurl); + handler_->Preconnect(scheme_host_pair, allow_credentials); } } // namespace network_hints
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResultUnitTest.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResultUnitTest.java index fe05db4..bc66795 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResultUnitTest.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteResultUnitTest.java
@@ -4,10 +4,9 @@ package org.chromium.components.omnibox; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_COLLAPSED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_EXPANDED_NO_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_EXPANDED_WITH_HEADER; -import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_EXPANDED_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_1_NO_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_2_WITH_HEADER; +import static org.chromium.components.omnibox.GroupConfigTestSupport.SECTION_3_WITH_HEADER; import org.junit.Assert; import org.junit.Test; @@ -56,25 +55,20 @@ list2.get(2).getSubtypes().add(4); var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .putGroupConfigs(30, SECTION_3_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) + .putGroupConfigs(30, SECTION_3_WITH_HEADER) .build(); - var groupsDetails2 = GroupsInfo.newBuilder() - .putGroupConfigs(10, - GroupConfig.newBuilder() - .mergeFrom(SECTION_1_EXPANDED_NO_HEADER) - .build()) - .putGroupConfigs(20, - GroupConfig.newBuilder() - .mergeFrom(SECTION_2_EXPANDED_WITH_HEADER) - .build()) - .putGroupConfigs(30, - GroupConfig.newBuilder() - .mergeFrom(SECTION_3_EXPANDED_WITH_HEADER) - .build()) - .build(); + var groupsDetails2 = + GroupsInfo.newBuilder() + .putGroupConfigs( + 10, GroupConfig.newBuilder().mergeFrom(SECTION_1_NO_HEADER).build()) + .putGroupConfigs(20, + GroupConfig.newBuilder().mergeFrom(SECTION_2_WITH_HEADER).build()) + .putGroupConfigs(30, + GroupConfig.newBuilder().mergeFrom(SECTION_3_WITH_HEADER).build()) + .build(); AutocompleteResult res1 = AutocompleteResult.fromCache(list1, groupsDetails1); AutocompleteResult res2 = AutocompleteResult.fromCache(list2, groupsDetails2); @@ -91,12 +85,12 @@ buildSuggestionForIndex(2), buildSuggestionForIndex(1), buildSuggestionForIndex(3)); var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) .build(); var groupsDetails2 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) .build(); var res1 = AutocompleteResult.fromCache(list1, groupsDetails1); @@ -114,34 +108,11 @@ buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) .build(); var groupsDetails2 = - GroupsInfo.newBuilder().putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER).build(); - - var res1 = AutocompleteResult.fromCache(list1, groupsDetails1); - var res2 = AutocompleteResult.fromCache(list2, groupsDetails2); - - Assert.assertNotEquals(res1, res2); - Assert.assertNotEquals(res1.hashCode(), res2.hashCode()); - } - - @Test - public void autocompleteResult_groupsWithDifferentDefaultExpandedStateAreNotEqual() { - var list1 = Arrays.asList( - buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); - var list2 = Arrays.asList( - buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); - - var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .build(); - var groupsDetails2 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_COLLAPSED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .build(); + GroupsInfo.newBuilder().putGroupConfigs(10, SECTION_1_NO_HEADER).build(); var res1 = AutocompleteResult.fromCache(list1, groupsDetails1); var res2 = AutocompleteResult.fromCache(list2, groupsDetails2); @@ -158,13 +129,13 @@ buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) .build(); var groupsDetails2 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) - .putGroupConfigs(30, SECTION_3_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) + .putGroupConfigs(30, SECTION_3_WITH_HEADER) .build(); var res1 = AutocompleteResult.fromCache(list1, groupsDetails1); @@ -194,18 +165,18 @@ buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); var groupsDetails1 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(20, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(20, SECTION_2_WITH_HEADER) .build(); var groupsDetails2 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) - .putGroupConfigs(15, SECTION_2_EXPANDED_WITH_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) + .putGroupConfigs(15, SECTION_2_WITH_HEADER) .build(); var groupsDetails3 = GroupsInfo.newBuilder() - .putGroupConfigs(10, SECTION_1_EXPANDED_NO_HEADER) + .putGroupConfigs(10, SECTION_1_NO_HEADER) .putGroupConfigs(20, GroupConfig.newBuilder() - .mergeFrom(SECTION_2_EXPANDED_WITH_HEADER) + .mergeFrom(SECTION_2_WITH_HEADER) .setHeaderText("Woooo") .build()) .build();
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/GroupConfigTestSupport.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/GroupConfigTestSupport.java index 884e026..d6d03302 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/GroupConfigTestSupport.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/GroupConfigTestSupport.java
@@ -34,29 +34,18 @@ .setRenderType(GroupConfig.RenderType.HORIZONTAL) .build(); - /** Suggestions with no headers, expanded, section 1. */ - public static GroupConfig SECTION_1_EXPANDED_NO_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_1, "", true); + /** Suggestions with no headers, section 1. */ + public static GroupConfig SECTION_1_NO_HEADER = + buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_1, ""); - /** Suggestions with no headers, collapsed, section 1. */ - public static GroupConfig SECTION_1_COLLAPSED_NO_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_1, "", false); + /** Suggestions with headers, section 2. */ + public static GroupConfig SECTION_2_WITH_HEADER = + buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_2, "Section #2"); - /** Suggestions with headers, expanded, section 2. */ - public static GroupConfig SECTION_2_EXPANDED_WITH_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_2, "Section #2", true); + /** Suggestions with headers, section 3. */ + public static GroupConfig SECTION_3_WITH_HEADER = + buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_3, "Section #3"); - /** Suggestions with headers, collapsed, section 2. */ - public static GroupConfig SECTION_2_COLLAPSED_WITH_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_2, "Section #2", false); - - /** Suggestions with headers, expanded, section 3. */ - public static GroupConfig SECTION_3_EXPANDED_WITH_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_3, "Section #3", true); - - /** Suggestions with headers, collapsed, section 3. */ - public static GroupConfig SECTION_3_COLLAPSED_WITH_HEADER = - buildGroupConfig(GroupSection.SECTION_REMOTE_ZPS_3, "Section #3", false); /** * Create a simple GroupConfig instance with supplied text and visibility. * @@ -66,12 +55,7 @@ * @return Newly constructed GroupConfig. */ public static GroupConfig buildGroupConfig( - @NonNull GroupSection section, @NonNull String headerText, boolean isVisible) { - return GroupConfig.newBuilder() - .setSection(section) - .setHeaderText(headerText) - .setVisibility(isVisible ? GroupConfig.Visibility.DEFAULT_VISIBLE - : GroupConfig.Visibility.HIDDEN) - .build(); + @NonNull GroupSection section, @NonNull String headerText) { + return GroupConfig.newBuilder().setSection(section).setHeaderText(headerText).build(); } }
diff --git a/components/omnibox/browser/autocomplete_grouper_groups.cc b/components/omnibox/browser/autocomplete_grouper_groups.cc index 3a3bd19..ccfc2c47 100644 --- a/components/omnibox/browser/autocomplete_grouper_groups.cc +++ b/components/omnibox/browser/autocomplete_grouper_groups.cc
@@ -26,17 +26,32 @@ return false; } const auto& limit_and_count = group_id_limits_and_counts_.at(group_id); - // Check this `Group`s total limit and the limit the particular `group_id`. - return matches_.size() < limit_ && - limit_and_count.count < limit_and_count.limit; + // Check this `Group`'s total limit and the limit for the `group_id`. + return count_ < limit_ && limit_and_count.count < limit_and_count.limit; } void Group::Add(const AutocompleteMatch& match) { DCHECK(CanAdd(match)); matches_.push_back(match); + Count(match); +} + +void Group::Count(const AutocompleteMatch& match) { + count_++; group_id_limits_and_counts_[match.suggestion_group_id.value()].count++; } +void Group::AdjustLimitsAndResetCounts(size_t max_limit) { + DCHECK(matches_.empty()) << "Must be called once before adding the matches."; + limit_ = std::min({limit_, max_limit, count_}); + count_ = 0; + for (auto& [group_id, limit_and_count] : group_id_limits_and_counts_) { + limit_and_count.limit = + std::min({limit_and_count.limit, limit_, limit_and_count.count}); + limit_and_count.count = 0; + } +} + DefaultGroup::DefaultGroup() : Group(1, GroupIdLimitsAndCounts{{omnibox::GROUP_STARTER_PACK, {1}},
diff --git a/components/omnibox/browser/autocomplete_grouper_groups.h b/components/omnibox/browser/autocomplete_grouper_groups.h index 815e14f1..e6ba1cdd 100644 --- a/components/omnibox/browser/autocomplete_grouper_groups.h +++ b/components/omnibox/browser/autocomplete_grouper_groups.h
@@ -30,10 +30,23 @@ Group(size_t limit, omnibox::GroupId group_id); virtual ~Group(); - // Returns if `match` can be added to this `Group`. + // Returns if `match` can be added to this `Group`. Checks if the `GroupId` of + // the match is permitted in this `Group`, this `Group`'s total limit, and the + // limit for the `GroupId` of the match. virtual bool CanAdd(const AutocompleteMatch& match) const; - // Adds `match` to this `Group`. `CanAdd()` should be verified by the caller. + // Adds `match` to this `Group` and increments this `Group`'s total count and + // the count for the `GroupId` of the match. + // `CanAdd()` should be verified by the caller. void Add(const AutocompleteMatch& match); + // Increments this `Group`'s total count and the count for the `GroupId` of + // the match but does not add `match` to this `Group`. + void Count(const AutocompleteMatch& match); + // Adjusts the `Group`'s total limit and the limits for the `GroupId`s in the + // `Group` based on the number of matches counted and the given max limit. + // Ensures that the limits are less than or equal to their original values. + // Resets the `Group`'s total count and the counts for the `GroupId`s in the + // `Group` so that matches can actually be added to the `Group`. + void AdjustLimitsAndResetCounts(size_t max_limit); size_t limit() { return limit_; } void set_limit(size_t limit) { limit_ = limit; } @@ -42,6 +55,8 @@ private: // Max number of matches this `Group` can contain. size_t limit_{0}; + // The number of matches this `Group` contains. + size_t count_{0}; // The limit and count per `GroupId`. GroupIdLimitsAndCounts group_id_limits_and_counts_; // The matches this `Group` contains.
diff --git a/components/omnibox/browser/autocomplete_grouper_sections.cc b/components/omnibox/browser/autocomplete_grouper_sections.cc index 4ded7bcc4..099fb76 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections.cc +++ b/components/omnibox/browser/autocomplete_grouper_sections.cc
@@ -20,6 +20,10 @@ // static ACMatches Section::GroupMatches(PSections sections, ACMatches matches) { + for (auto& section : sections) { + section->InitFromMatches(matches); + } + for (const auto& match : matches) { DCHECK(match.suggestion_group_id.has_value()); for (const auto& section : sections) { @@ -39,9 +43,7 @@ return grouped_matches; } -Group* Section::CanAdd(const AutocompleteMatch& match) { - if (size_ >= limit_) - return nullptr; +Group* Section::FindGroup(const AutocompleteMatch& match) { auto iter = base::ranges::find_if( groups_, [&](const auto& group) { return group->CanAdd(match); }); if (iter == groups_.end()) @@ -50,35 +52,79 @@ } bool Section::Add(const AutocompleteMatch& match) { - Group* group = CanAdd(match); + if (count_ >= limit_) { + return false; + } + Group* group = FindGroup(match); if (group) { group->Add(match); - size_++; + count_++; } return group; } -MobileZeroInputSection::MobileZeroInputSection() : Section(20) { - groups_.push_back(std::make_unique<Group>( - 10, Group::GroupIdLimitsAndCounts{ - {omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX, {1}}, - {omnibox::GROUP_MOBILE_CLIPBOARD, {1}}, - {omnibox::GROUP_MOBILE_MOST_VISITED, {8}}, - {omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, {10}}})); - groups_.push_back(std::make_unique<Group>(5, omnibox::GROUP_TRENDS)); +ZpsSection::ZpsSection(size_t limit) : Section(limit) {} + +void ZpsSection::InitFromMatches(const ACMatches& matches) { + // Iterate over the matches to see if they can be added to any `Group` in this + // `Section`. If so, increment the total count for this `Section` and for the + // respective group. + for (const auto& match : matches) { + Group* group = FindGroup(match); + if (group) { + count_++; + group->Count(match); + } + } + + // Adjust the `Section`'s total limit based on the number of matches in the + // `Section`. Ensure the limit is less than or equal to the original value. + // Reset the count so that matches can actually be added to this `Section`. + limit_ = std::min(limit_, count_); + count_ = 0; + + size_t remaining = limit_; + for (const auto& group : groups_) { + group->AdjustLimitsAndResetCounts(remaining); + remaining -= group->limit(); + } + DCHECK_EQ(remaining, 0U); } -DesktopNonZpsSection::DesktopNonZpsSection(const ACMatches& matches) - : Section(10) { - // Create the 4 groups with reasonable placeholder limits. Some of the limits - // will be adjusted below. - auto default_group = std::make_unique<DefaultGroup>(); - auto starter_pack_group = - std::make_unique<Group>(9, omnibox::GROUP_STARTER_PACK); - auto search_group = std::make_unique<Group>( +AndroidZpsSection::AndroidZpsSection() : ZpsSection(15) { + groups_.push_back( + std::make_unique<Group>(1, omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX)); + groups_.push_back( + std::make_unique<Group>(1, omnibox::GROUP_MOBILE_CLIPBOARD)); + groups_.push_back( + std::make_unique<Group>(1, omnibox::GROUP_MOBILE_MOST_VISITED)); + groups_.push_back( + std::make_unique<Group>(15, omnibox::GROUP_PREVIOUS_SEARCH_RELATED)); + groups_.push_back( + std::make_unique<Group>(15, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST)); +} + +DesktopZpsSection::DesktopZpsSection() : ZpsSection(8) { + groups_.push_back( + std::make_unique<Group>(8, omnibox::GROUP_PREVIOUS_SEARCH_RELATED)); + groups_.push_back( + std::make_unique<Group>(8, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST)); + groups_.push_back(std::make_unique<Group>(8, omnibox::GROUP_TRENDS)); +} + +DesktopNonZpsSection::DesktopNonZpsSection() : Section(10) { + groups_.push_back(std::make_unique<DefaultGroup>()); + groups_.push_back(std::make_unique<Group>(9, omnibox::GROUP_STARTER_PACK)); + groups_.push_back(std::make_unique<Group>( 9, Group::GroupIdLimitsAndCounts{{omnibox::GROUP_SEARCH, {9}}, - {omnibox::GROUP_HISTORY_CLUSTER, {1}}}); - auto nav_group = std::make_unique<Group>(7, omnibox::GROUP_OTHER_NAVS); + {omnibox::GROUP_HISTORY_CLUSTER, {1}}})); + groups_.push_back(std::make_unique<Group>(7, omnibox::GROUP_OTHER_NAVS)); +} + +void DesktopNonZpsSection::InitFromMatches(const ACMatches& matches) { + auto* default_group = groups_[0].get(); + auto* search_group = groups_[2].get(); + auto* nav_group = groups_[3].get(); // Determine if `matches` contains any searches. bool has_search = base::ranges::any_of( @@ -101,11 +147,8 @@ limit_ = std::clamp<size_t>(first_nav_index, 8, 10); // Show at least 1 search, either in the default group or the search group. - if (has_search && !default_is_search) + if (has_search && !default_is_search) { + DCHECK_GE(limit_, 2U); nav_group->set_limit(limit_ - 2); - - groups_.push_back(std::move(default_group)); - groups_.push_back(std::move(starter_pack_group)); - groups_.push_back(std::move(search_group)); - groups_.push_back(std::move(nav_group)); + } }
diff --git a/components/omnibox/browser/autocomplete_grouper_sections.h b/components/omnibox/browser/autocomplete_grouper_sections.h index 9f5dca11..0fefeac 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections.h +++ b/components/omnibox/browser/autocomplete_grouper_sections.h
@@ -26,30 +26,57 @@ // Returns `matches` ranked and culled according to `sections`. All `matches` // should have `suggestion_group_id` set and be sorted by relevance. static ACMatches GroupMatches(PSections sections, ACMatches matches); + // Used to adjust this `Section`'s total limit and the total limits for the + // `Group`s in this `Section` based on the given matches. + virtual void InitFromMatches(const ACMatches& matches) {} protected: - // Return the `Group` `match` can be added to, or `nullptr` if it can't be - // added to any group in `groups_`. - virtual Group* CanAdd(const AutocompleteMatch& match); - // Tries to add `match` to the appropriate `groups_`. Returns if it was added - // to any group in `groups_`. + // Returns the first `Group` in this `Section` `match` can be added to or + // `nullptr` if none can be found. Does not take the total limit into account. + Group* FindGroup(const AutocompleteMatch& match); + // Returns whether `match` was added to a `Group` in this `Section`. Does not + // add a match beyond the total limit. bool Add(const AutocompleteMatch& match); // Max number of matches this `Section` can contain across `groups_`. - size_t limit_ = 0; + size_t limit_{0}; // The number of matches this `Section` contains across `groups_`. - size_t size_ = 0; - // The `groups_` this `Section` contains. - PGroups groups_ = {}; + size_t count_{0}; + // The `Group`s this `Section` contains. + PGroups groups_{}; }; -// Section containing up to 15 searches and 5 trending suggestions. -class MobileZeroInputSection : public Section { +// Base section for zps limits and grouping. +// Since zero-prefix matches are seen in descending order of relevance, the +// default implementation of `InitFromMatches()` ensures that matches with +// higher relevance scores do not fill up the section if others with lower +// scores are expected to be placed earlier based on their `Group`s position. +class ZpsSection : public Section { public: - MobileZeroInputSection(); + explicit ZpsSection(size_t limit); + // Section: + void InitFromMatches(const ACMatches& matches) override; }; -// Section expressing the desktop, non-zps limits and grouping. The rules are: +// Section expressing the Android zps limits and grouping. The rules are: +// - Contains up to 1 verbatim, 1 clipboard, 1 most visited, 8 related search +// suggestions, and 15 personalized suggestions. +// - Allow up to 15 suggestions total. +class AndroidZpsSection : public ZpsSection { + public: + AndroidZpsSection(); +}; + +// Section expressing the Desktop zps limits and grouping. The rules are: +// - Containing up to 8 related search suggestions, 8 personalized suggestions, +// and 8 trending search suggestions. +// - Allow up to 8 suggestions total. +class DesktopZpsSection : public ZpsSection { + public: + DesktopZpsSection(); +}; + +// Section expressing the Desktop, non-zps limits and grouping. The rules are: // - Contains up to 1 default, 10 starer packs, 10 search, 8 nav, and 1 history // cluster suggestions. // - Allow up to 10 suggestions total. @@ -60,7 +87,9 @@ // - Group defaults 1st, then searches and history clusters, then navs. class DesktopNonZpsSection : public Section { public: - explicit DesktopNonZpsSection(const ACMatches& matches); + DesktopNonZpsSection(); + // Section: + void InitFromMatches(const ACMatches& matches) override; }; #endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_GROUPER_SECTIONS_H_
diff --git a/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc b/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc index 2204c541..658807a 100644 --- a/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc +++ b/components/omnibox/browser/autocomplete_grouper_sections_unittest.cc
@@ -35,6 +35,7 @@ } // namespace +// Tests a section with no groups. TEST(AutocompleteGrouperSectionsTest, Section) { auto test = [](const ACMatches& matches, std::vector<int> expected_relevances) { @@ -51,42 +52,95 @@ test({CreateMatch(1, omnibox::GROUP_SEARCH)}, {}); } -TEST(AutocompleteGrouperSectionsTest, MobileZeroInputSection) { +// Tests a section with groups and limits, but no rules. +TEST(AutocompleteGrouperSectionsTest, SectionWithGroupsAndLimitsButNoRules) { auto test = [](const ACMatches& matches, std::vector<int> expected_relevances) { PSections sections; - sections.push_back(std::make_unique<MobileZeroInputSection>()); + sections.push_back(std::make_unique<DesktopZpsSection>()); auto out_matches = Section::GroupMatches(std::move(sections), matches); VerifyMatches(out_matches, expected_relevances); }; - // Given no matches, should return no matches. - test({}, {}); + { + SCOPED_TRACE("Given no matches, should return no matches."); + test({}, {}); + } - // Matches not qualifying for the section should not be added. - ACMatches matches; - matches.push_back(CreateMatch(100, omnibox::GROUP_DOCUMENT)); - // `GROUP_TRENDS` matches should be added up to their group limit (5). - for (size_t i = 0; i < 10; ++i) - matches.push_back(CreateMatch(90 - i, omnibox::GROUP_TRENDS)); - // `GROUP_MOBILE_MOST_VISITED` matches should be added up to their group limit - // (8). - for (size_t i = 0; i < 20; ++i) - matches.push_back(CreateMatch(60 - i, omnibox::GROUP_MOBILE_MOST_VISITED)); - // Matches should be ranked by group, not relevance or add order. - std::vector<int> expected_relevances; - for (size_t i = 60; i > 60 - 8; --i) - expected_relevances.push_back(i); - for (size_t i = 90; i > 90 - 5; --i) - expected_relevances.push_back(i); - test(matches, expected_relevances); + { + SCOPED_TRACE("Matches that qualify for no groups, should not be added."); + test( + { + CreateMatch(100, omnibox::GROUP_DOCUMENT), + CreateMatch(99, omnibox::GROUP_SEARCH), + CreateMatch(98, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST), + }, + {98}); + } + + { + SCOPED_TRACE( + "Matches should be ranked by group, not relevance or add order."); + ACMatches matches; + // `GROUP_TRENDS` matches come 3rd and should not be added. + for (size_t i = 0; i < 10; ++i) { + matches.push_back(CreateMatch(90 - i, omnibox::GROUP_TRENDS)); + } + // `GROUP_PERSONALIZED_ZERO_SUGGEST` matches come 2nd and should not be + // added. + for (size_t i = 0; i < 10; ++i) { + matches.push_back( + CreateMatch(80 - i, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST)); + } + // `GROUP_PREVIOUS_SEARCH_RELATED` matches come 1st and should be added. + for (size_t i = 0; i < 10; ++i) { + matches.push_back( + CreateMatch(70 - i, omnibox::GROUP_PREVIOUS_SEARCH_RELATED)); + } + std::vector<int> expected_relevances; + for (size_t i = 70; i > 70 - 8; --i) { + expected_relevances.push_back(i); + } + test(matches, expected_relevances); + } + + { + SCOPED_TRACE("Matches should be added up to their group limit."); + ACMatches matches; + for (size_t i = 0; i < 10; ++i) { + matches.push_back( + CreateMatch(80 - i, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST)); + } + std::vector<int> expected_relevances; + for (size_t i = 80; i > 80 - 8; --i) { + expected_relevances.push_back(i); + } + test(matches, expected_relevances); + } + + { + SCOPED_TRACE("Matches should be added up to the section limit."); + ACMatches matches; + // `GROUP_TRENDS` matches should be added up to the remaining section limit + // (3). + for (size_t i = 0; i < 10; ++i) { + matches.push_back(CreateMatch(90 - i, omnibox::GROUP_TRENDS)); + } + // `GROUP_PERSONALIZED_ZERO_SUGGEST` matches should all be added. + for (size_t i = 0; i < 5; ++i) { + matches.push_back( + CreateMatch(80 - i, omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST)); + } + test(matches, {80, 79, 78, 77, 76, 90, 89, 88}); + } } +// Tests the groups, limits, and rules for the Desktop non-ZPS section. TEST(AutocompleteGrouperSectionsTest, DesktopNonZpsSection) { auto test = [](const ACMatches& matches, std::vector<int> expected_relevances) { PSections sections; - sections.push_back(std::make_unique<DesktopNonZpsSection>(matches)); + sections.push_back(std::make_unique<DesktopNonZpsSection>()); auto out_matches = Section::GroupMatches(std::move(sections), matches); VerifyMatches(out_matches, expected_relevances); };
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index 62e0c30a..7e63313 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -363,7 +363,7 @@ // supported, delegate to the framework. const bool is_zero_suggest = input.IsZeroSuggest(); if (base::FeatureList::IsEnabled(omnibox::kGroupingFramework) && - !is_zero_suggest && !is_android && !is_ios) { + !is_android && !is_ios) { // Grouping requires all matches have a group ID. To keep providers 'dumb', // they only assign IDs when their ID isn't obvious from the match type. // Most matches will instead set IDs here to keep providers 'dumb' and the @@ -381,12 +381,13 @@ base::EraseIf(matches_, [&](const auto& match) { return match.relevance == 0; }); - // If there's only 1 match, then grouping is a no-op. - if (matches_.size() > 2) { - PSections sections; - sections.push_back(std::make_unique<DesktopNonZpsSection>(matches_)); - matches_ = Section::GroupMatches(std::move(sections), matches_); + PSections sections; + if (is_zero_suggest) { + sections.push_back(std::make_unique<DesktopZpsSection>()); + } else if (matches_.size() > 2) { // Grouping is a no-op for only 1 match. + sections.push_back(std::make_unique<DesktopNonZpsSection>()); } + matches_ = Section::GroupMatches(std::move(sections), std::move(matches_)); } else { // Limit history cluster suggestions to 1. This has to be done before
diff --git a/components/omnibox/browser/autocomplete_result_android.cc b/components/omnibox/browser/autocomplete_result_android.cc index 5fb2ff1..a798be7 100644 --- a/components/omnibox/browser/autocomplete_result_android.cc +++ b/components/omnibox/browser/autocomplete_result_android.cc
@@ -174,8 +174,6 @@ UMA_HISTOGRAM_ENUMERATION("Android.Omnibox.InvalidMatch", MatchVerificationResult::BAD_RESULT_SIZE, MatchVerificationResult::COUNT); - NOTREACHED() << "AutocompletResult objects are of different size: " - << j_matches.size() << " (Java) vs " << size() << " (Native)"; ReportInvalidMatchData(base::NumberToString(j_matches.size()) + "!=" + base::NumberToString(size()), verification_point); @@ -186,8 +184,6 @@ UMA_HISTOGRAM_ENUMERATION("Android.Omnibox.InvalidMatch", MatchVerificationResult::INVALID_MATCH_POSITION, MatchVerificationResult::COUNT); - NOTREACHED() << "Requested action index is not valid: " << match_index - << " outside of " << size() << " limit"; ReportInvalidMatchData( base::NumberToString(match_index) + ">=" + base::NumberToString(size()), verification_point); @@ -213,9 +209,6 @@ : u"<null>"); } #endif - NOTREACHED() - << "AutocompleteMatch mismatch with native-sourced suggestions at " - << index; ReportInvalidMatchData( base::NumberToString(index) + "/" + base::NumberToString(size()),
diff --git a/components/omnibox/browser/zero_suggest_cache_service.cc b/components/omnibox/browser/zero_suggest_cache_service.cc index 406ab86..74a4a9f 100644 --- a/components/omnibox/browser/zero_suggest_cache_service.cc +++ b/components/omnibox/browser/zero_suggest_cache_service.cc
@@ -38,7 +38,7 @@ for (auto it = prefs_dict.begin(); it != prefs_dict.end(); ++it) { const auto& page_url = it->first; const auto& response_json = (it->second).GetString(); - StoreZeroSuggestResponse(page_url, CacheEntry(response_json)); + StoreZeroSuggestResponse(page_url, response_json); } } } @@ -79,13 +79,15 @@ void ZeroSuggestCacheService::StoreZeroSuggestResponse( const std::string& page_url, - const CacheEntry& response) { + const std::string& response_json) { + auto entry = CacheEntry(response_json); + if (page_url.empty()) { // Write ZPS response for NTP to cache. - ntp_entry_ = response; + ntp_entry_ = entry; } else { // Write ZPS response for SRP/Web to cache. - cache_.Put(page_url, response); + cache_.Put(page_url, entry); } base::UmaHistogramCounts1M( @@ -94,7 +96,7 @@ base::trace_event::EstimateMemoryUsage(ntp_entry_)); for (auto& observer : observers_) { - observer.OnZeroSuggestResponseUpdated(page_url, response); + observer.OnZeroSuggestResponseUpdated(page_url, entry); } }
diff --git a/components/omnibox/browser/zero_suggest_cache_service.h b/components/omnibox/browser/zero_suggest_cache_service.h index 3016593..c5dbc04 100644 --- a/components/omnibox/browser/zero_suggest_cache_service.h +++ b/components/omnibox/browser/zero_suggest_cache_service.h
@@ -62,7 +62,7 @@ // Read/write zero suggest cache entries. CacheEntry ReadZeroSuggestResponse(const std::string& page_url) const; void StoreZeroSuggestResponse(const std::string& page_url, - const CacheEntry& response); + const std::string& response_json); // Remove all zero suggest cache entries. void ClearCache();
diff --git a/components/omnibox/browser/zero_suggest_cache_service_unittest.cc b/components/omnibox/browser/zero_suggest_cache_service_unittest.cc index 8eb25dc6..57d7db45 100644 --- a/components/omnibox/browser/zero_suggest_cache_service_unittest.cc +++ b/components/omnibox/browser/zero_suggest_cache_service_unittest.cc
@@ -76,8 +76,7 @@ TEST_F(ZeroSuggestCacheServiceTest, StoreResponsePopulatesCache) { ZeroSuggestCacheService cache_svc(GetPrefs(), 1); - cache_svc.StoreZeroSuggestResponse("https://www.google.com", - CacheEntry("foo")); + cache_svc.StoreZeroSuggestResponse("https://www.google.com", "foo"); EXPECT_FALSE(cache_svc.IsCacheEmpty()); } @@ -89,20 +88,20 @@ const std::string response = "foo"; const std::string histogram = "Omnibox.ZeroSuggestProvider.CacheMemoryUsage"; - cache_svc.StoreZeroSuggestResponse(page_url, CacheEntry(response)); + cache_svc.StoreZeroSuggestResponse(page_url, response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url).response_json, response); histogram_tester.ExpectTotalCount(histogram, 1); - cache_svc.StoreZeroSuggestResponse(page_url, CacheEntry("")); + cache_svc.StoreZeroSuggestResponse(page_url, ""); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url).response_json, ""); histogram_tester.ExpectTotalCount(histogram, 2); - cache_svc.StoreZeroSuggestResponse("", CacheEntry(response)); + cache_svc.StoreZeroSuggestResponse("", response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse("").response_json, response); histogram_tester.ExpectTotalCount(histogram, 3); - cache_svc.StoreZeroSuggestResponse("", CacheEntry("")); + cache_svc.StoreZeroSuggestResponse("", ""); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse("").response_json, ""); histogram_tester.ExpectTotalCount(histogram, 4); } @@ -114,11 +113,11 @@ const std::string old_response = "foo"; const std::string new_response = "bar"; - cache_svc.StoreZeroSuggestResponse(page_url, CacheEntry(old_response)); + cache_svc.StoreZeroSuggestResponse(page_url, old_response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url).response_json, old_response); - cache_svc.StoreZeroSuggestResponse(page_url, CacheEntry(new_response)); + cache_svc.StoreZeroSuggestResponse(page_url, new_response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url).response_json, new_response); } @@ -143,21 +142,21 @@ EXPECT_EQ(other_goog_observer.GetData().response_json, ""); EXPECT_EQ(fb_observer.GetData().response_json, ""); - cache_svc.StoreZeroSuggestResponse(goog_url, CacheEntry("foo")); + cache_svc.StoreZeroSuggestResponse(goog_url, "foo"); // Only the relevant observers should have been notified. EXPECT_EQ(goog_observer.GetData().response_json, "foo"); EXPECT_EQ(other_goog_observer.GetData().response_json, "foo"); EXPECT_EQ(fb_observer.GetData().response_json, ""); - cache_svc.StoreZeroSuggestResponse(fb_url, CacheEntry("bar")); + cache_svc.StoreZeroSuggestResponse(fb_url, "bar"); // Only the relevant observer should have been notified. EXPECT_EQ(goog_observer.GetData().response_json, "foo"); EXPECT_EQ(other_goog_observer.GetData().response_json, "foo"); EXPECT_EQ(fb_observer.GetData().response_json, "bar"); - cache_svc.StoreZeroSuggestResponse(goog_url, CacheEntry("eggs")); + cache_svc.StoreZeroSuggestResponse(goog_url, "eggs"); // The relevant observers should have received an updated value. EXPECT_EQ(goog_observer.GetData().response_json, "eggs"); @@ -165,7 +164,7 @@ EXPECT_EQ(fb_observer.GetData().response_json, "bar"); cache_svc.RemoveObserver(&fb_observer); - cache_svc.StoreZeroSuggestResponse(fb_url, CacheEntry("spam")); + cache_svc.StoreZeroSuggestResponse(fb_url, "spam"); // The relevant observer should NOT have been notified (since it was removed // prior to updating the cache). @@ -181,8 +180,8 @@ TestCacheEntry entry2 = {"https://www.google.com", "bar"}; TestCacheEntry entry3 = {"https://www.example.com", "eggs"}; - cache_svc.StoreZeroSuggestResponse(entry1.url, CacheEntry(entry1.response)); - cache_svc.StoreZeroSuggestResponse(entry2.url, CacheEntry(entry2.response)); + cache_svc.StoreZeroSuggestResponse(entry1.url, entry1.response); + cache_svc.StoreZeroSuggestResponse(entry2.url, entry2.response); // Fill up the zero suggest cache to max capacity. EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(entry1.url).response_json, @@ -190,7 +189,7 @@ EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(entry2.url).response_json, entry2.response); - cache_svc.StoreZeroSuggestResponse(entry3.url, CacheEntry(entry3.response)); + cache_svc.StoreZeroSuggestResponse(entry3.url, entry3.response); // "Least recently used" entry should now have been evicted from the cache. EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(entry1.url).response_json, ""); @@ -205,7 +204,7 @@ const std::string page_url = "https://www.google.com"; const std::string response = "foo"; - cache_svc.StoreZeroSuggestResponse(page_url, CacheEntry(response)); + cache_svc.StoreZeroSuggestResponse(page_url, response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url).response_json, response); @@ -219,15 +218,15 @@ TestCacheEntry entry3 = {"https://www.example.com", "eggs"}; // Fill up the zero suggest cache to max capacity. - cache_svc.StoreZeroSuggestResponse(entry1.url, CacheEntry(entry1.response)); - cache_svc.StoreZeroSuggestResponse(entry2.url, CacheEntry(entry2.response)); + cache_svc.StoreZeroSuggestResponse(entry1.url, entry1.response); + cache_svc.StoreZeroSuggestResponse(entry2.url, entry2.response); // Read the oldest entry in the cache, thereby marking the more recent entry // as "least recently used". EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(entry1.url).response_json, entry1.response); - cache_svc.StoreZeroSuggestResponse(entry3.url, CacheEntry(entry3.response)); + cache_svc.StoreZeroSuggestResponse(entry3.url, entry3.response); // Since the second request was the "least recently used", it should have been // evicted. @@ -245,12 +244,9 @@ ZeroSuggestCacheService cache_svc(GetPrefs(), 3); - cache_svc.StoreZeroSuggestResponse(ntp_entry.url, - CacheEntry(ntp_entry.response)); - cache_svc.StoreZeroSuggestResponse(srp_entry.url, - CacheEntry(srp_entry.response)); - cache_svc.StoreZeroSuggestResponse(web_entry.url, - CacheEntry(web_entry.response)); + cache_svc.StoreZeroSuggestResponse(ntp_entry.url, ntp_entry.response); + cache_svc.StoreZeroSuggestResponse(srp_entry.url, srp_entry.response); + cache_svc.StoreZeroSuggestResponse(web_entry.url, web_entry.response); EXPECT_FALSE( cache_svc.ReadZeroSuggestResponse(ntp_entry.url).response_json.empty()); @@ -301,12 +297,9 @@ PrefService* prefs = GetPrefs(); { ZeroSuggestCacheService cache_svc(prefs, 3); - cache_svc.StoreZeroSuggestResponse(ntp_entry.url, - CacheEntry(ntp_entry.response)); - cache_svc.StoreZeroSuggestResponse(srp_entry.url, - CacheEntry(srp_entry.response)); - cache_svc.StoreZeroSuggestResponse(web_entry.url, - CacheEntry(web_entry.response)); + cache_svc.StoreZeroSuggestResponse(ntp_entry.url, ntp_entry.response); + cache_svc.StoreZeroSuggestResponse(srp_entry.url, srp_entry.response); + cache_svc.StoreZeroSuggestResponse(web_entry.url, web_entry.response); } EXPECT_EQ(omnibox::GetUserPreferenceForZeroSuggestCachedResponse( @@ -325,8 +318,7 @@ PrefService* prefs = nullptr; ZeroSuggestCacheService cache_svc(prefs, 1); - cache_svc.StoreZeroSuggestResponse(ntp_entry.url, - CacheEntry(ntp_entry.response)); + cache_svc.StoreZeroSuggestResponse(ntp_entry.url, ntp_entry.response); EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(ntp_entry.url).response_json, ntp_entry.response);
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index 6c8ed55..a66a69c2 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -252,8 +252,8 @@ if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestInMemoryCaching)) { auto* zero_suggest_cache_service = client->GetZeroSuggestCacheService(); if (zero_suggest_cache_service != nullptr) { - ZeroSuggestCacheService::CacheEntry entry(response_json); - zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, entry); + zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, + response_json); LogEvent(Event::kRemoteResponseCached, result_type, is_prefetch); } } else {
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc index ec0beb18..f434b46 100644 --- a/components/omnibox/browser/zero_suggest_provider_unittest.cc +++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -1603,7 +1603,7 @@ R"([],[],{"google:suggestrelevance":[602, 601, 600],)" R"("google:verbatimrelevance":1300}])"); ZeroSuggestCacheService* cache_svc = client_->GetZeroSuggestCacheService(); - cache_svc->StoreZeroSuggestResponse("", CacheEntry(json_response)); + cache_svc->StoreZeroSuggestResponse("", json_response); AutocompleteInput input = OnFocusInputForNTP(); provider_->Start(input, false); @@ -1772,7 +1772,7 @@ AutocompleteInput input = OnClobberInputForSRP(); ZeroSuggestCacheService* cache_svc = client_->GetZeroSuggestCacheService(); cache_svc->StoreZeroSuggestResponse(input.current_url().spec(), - CacheEntry(json_response)); + json_response); provider_->Start(input, false); ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, @@ -1943,7 +1943,7 @@ AutocompleteInput input = OnClobberInputForWeb(); ZeroSuggestCacheService* cache_svc = client_->GetZeroSuggestCacheService(); cache_svc->StoreZeroSuggestResponse(input.current_url().spec(), - CacheEntry(json_response)); + json_response); provider_->Start(input, false); ASSERT_EQ(ZeroSuggestProvider::ResultType::kRemoteSendURL, @@ -2872,9 +2872,8 @@ R"({"du": "https://www.google.com/s3"}]}])"); ZeroSuggestCacheService* cache_svc = client_->GetZeroSuggestCacheService(); - cache_svc->StoreZeroSuggestResponse("", CacheEntry(json_response)); - cache_svc->StoreZeroSuggestResponse("https://www.google.com", - CacheEntry(json_response)); + cache_svc->StoreZeroSuggestResponse("", json_response); + cache_svc->StoreZeroSuggestResponse("https://www.google.com", json_response); AutocompleteInput input = OnFocusInputForNTP(); provider_->Start(input, false);
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.cc b/components/optimization_guide/content/browser/page_content_annotations_service.cc index 20b99f2..37f212162 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_service.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_service.cc
@@ -374,7 +374,25 @@ std::move(callback).Run(CreateEmptyBatchAnnotationResults(inputs)); return; } - annotator_->Annotate(std::move(callback), inputs, annotation_type); + + annotator_->Annotate( + base::BindOnce( + [](BatchAnnotationCallback original_callback, + OptimizationGuideLogger* optimization_guide_logger, + const std::vector<BatchAnnotationResult>& batch_result) { + if (optimization_guide_logger) { + for (const BatchAnnotationResult& result : batch_result) { + OPTIMIZATION_GUIDE_LOGGER( + optimization_guide_common::mojom::LogSource:: + PAGE_CONTENT_ANNOTATIONS, + optimization_guide_logger) + << "PageContentAnnotationJob Result: " << result.ToString(); + } + } + std::move(original_callback).Run(batch_result); + }, + std::move(callback), optimization_guide_logger_), + inputs, annotation_type); } absl::optional<ModelInfo> PageContentAnnotationsService::GetModelInfoForType(
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc index 2e8f6901..75e0023 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc
@@ -613,10 +613,8 @@ const std::string& page_url, const std::string& response_json) { DCHECK(zero_suggest_cache_service); - - ZeroSuggestCacheService::CacheEntry entry; - entry.response_json = response_json; - zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, entry); + zero_suggest_cache_service->StoreZeroSuggestResponse(page_url, + response_json); } // Performs synchronous call of `HistoryService::QueryHistory()`.
diff --git a/components/origin_trials/BUILD.gn b/components/origin_trials/BUILD.gn index 889627d..078056fc 100644 --- a/components/origin_trials/BUILD.gn +++ b/components/origin_trials/BUILD.gn
@@ -20,6 +20,7 @@ "//components/prefs", "//components/user_prefs", "//content/public/browser", + "//net", "//third_party/blink/public/common:headers", "//url:url", ]
diff --git a/components/origin_trials/browser/DEPS b/components/origin_trials/browser/DEPS index 586f928..f7e0680e9 100644 --- a/components/origin_trials/browser/DEPS +++ b/components/origin_trials/browser/DEPS
@@ -10,6 +10,8 @@ "+content/public/browser", "+content/public/common", + "+net/base/schemeful_site.h", + "+third_party/blink/public/common/origin_trials", ]
diff --git a/components/origin_trials/browser/leveldb_persistence_provider.cc b/components/origin_trials/browser/leveldb_persistence_provider.cc index 5da1706..9e1454a 100644 --- a/components/origin_trials/browser/leveldb_persistence_provider.cc +++ b/components/origin_trials/browser/leveldb_persistence_provider.cc
@@ -9,12 +9,15 @@ #include <vector> #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/ranges/algorithm.h" +#include "base/strings/string_util.h" #include "base/synchronization/lock.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" @@ -27,6 +30,7 @@ #include "components/origin_trials/proto/db_trial_token.pb.h" #include "components/origin_trials/proto/proto_util.h" #include "content/public/browser/browser_thread.h" +#include "net/base/schemeful_site.h" #include "third_party/blink/public/common/origin_trials/trial_token_validator.h" #include "url/origin.h" @@ -34,6 +38,20 @@ namespace { +// Check to see if |token_origin_host| has any of the strings in +// |partition_sites| as a suffix. +bool HasFirstPartyPartition( + const url::Origin token_origin_host, + const google::protobuf::RepeatedPtrField<std::string>& partition_sites) { + std::string host_key = net::SchemefulSite(token_origin_host).Serialize(); + for (const std::string& site : partition_sites) { + if (site == host_key) { + return true; + } + } + return false; +} + const base::FilePath::StringPieceType kPersistentTrialTokenDbPath = FILE_PATH_LITERAL("PersistentOriginTrials"); @@ -71,9 +89,21 @@ it->token_signature(), current_time); if (valid) { + UMA_HISTOGRAM_COUNTS_100( + "OriginTrials.PersistentOriginTrial.PartitionSetSize", + it->partition_sites().size()); + UMA_HISTOGRAM_BOOLEAN( + "OriginTrials.PersistentOriginTrial.TokenHasFirstPartyPartition", + HasFirstPartyPartition(key, it->partition_sites())); + // Move the strings out of the protobuffer to avoid allocations + base::flat_set<std::string> partition_sites; + for (std::string& site : *it->mutable_partition_sites()) { + partition_sites.insert(std::move(site)); + } new_tokens.emplace(std::move(*it->mutable_trial_name()), token_expiry, usage_restriction, - std::move(*it->mutable_token_signature())); + std::move(*it->mutable_token_signature()), + std::move(partition_sites)); } }
diff --git a/components/origin_trials/browser/leveldb_persistence_provider_unittest.cc b/components/origin_trials/browser/leveldb_persistence_provider_unittest.cc index 177fe1e..db15fff 100644 --- a/components/origin_trials/browser/leveldb_persistence_provider_unittest.cc +++ b/components/origin_trials/browser/leveldb_persistence_provider_unittest.cc
@@ -30,11 +30,13 @@ namespace { -const char kTrialOrigin[] = "https://example.com"; -const char kTrialOriginSecondary[] = "https://secondary.example.com"; +const char kExampleComOrigin[] = "https://example.com"; +const char kSecondaryExampleComOrigin[] = "https://secondary.example.com"; const char kTrialName[] = "FrobulatePersistent"; const char kTrialSignature[] = "trial signature"; const char kTrialSignatureAlternate[] = "alternate trial signature"; +const char kExampleComDomain[] = "https://example.com"; +const char kGoogleComDomain[] = "https://google.com"; using leveldb_proto::test::FakeDB; @@ -104,6 +106,7 @@ ht.ExpectUniqueSample("OriginTrials.PersistentOriginTrial.LevelDbLoadSize", 0, 1); ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.LevelDbLoadTime", 1); + ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.PartitionSetSize", 0); } TEST_F(LevelDbPersistenceProviderUnitTest, FailedInitLogsHistograms) { @@ -123,6 +126,7 @@ "OriginTrials.PersistentOriginTrial.OriginLookupsBeforeDbLoad", 0); ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.LevelDbLoadSize", 0); ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.LevelDbLoadTime", 0); + ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.PartitionSetSize", 0); } TEST_F(LevelDbPersistenceProviderUnitTest, FailedLoadLogsHistograms) { @@ -143,18 +147,20 @@ "OriginTrials.PersistentOriginTrial.OriginLookupsBeforeDbLoad", 0); ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.LevelDbLoadSize", 0); ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.LevelDbLoadTime", 0); + ht.ExpectTotalCount("OriginTrials.PersistentOriginTrial.PartitionSetSize", 0); } TEST_F(LevelDbPersistenceProviderUnitTest, UpdatesAppliedInMemoryAndToDb) { InitPersistenceProvider(); - url::Origin origin = url::Origin::Create(GURL(kTrialOrigin)); + url::Origin origin = url::Origin::Create(GURL(kExampleComOrigin)); + base::flat_set<std::string> partition_sites = {kExampleComDomain}; base::Time expiry = base::Time::Now() + base::Days(365); base::flat_set<PersistedTrialToken> tokens; tokens.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + kTrialSignature, partition_sites); persistence_provider_->SavePersistentTrialTokens(origin, tokens); @@ -167,8 +173,8 @@ // Expect the DB to have been updated in the back after an update EXPECT_EQ(1ul, db_entries_.size()); - EXPECT_NE(db_entries_.end(), db_entries_.find(kTrialOrigin)) - << "Expect to find a value for kTrialOrigin in the map"; + EXPECT_NE(db_entries_.end(), db_entries_.find(kExampleComOrigin)) + << "Expect to find a value for kExampleComOrigin in the map"; persistence_provider_->ClearPersistedTokens(); stored_tokens = persistence_provider_->GetPersistentTrialTokens(origin); @@ -180,43 +186,64 @@ TEST_F(LevelDbPersistenceProviderUnitTest, TokensLoadedFromDbOnStartup) { base::HistogramTester ht; - url::Origin origin = url::Origin::Create(GURL(kTrialOrigin)); - base::Time expiry = base::Time::Now() + base::Days(365); - base::flat_set<PersistedTrialToken> tokens; - tokens.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + url::Origin origin_a = url::Origin::Create(GURL(kExampleComOrigin)); + base::flat_set<std::string> partition_sites_a = {kExampleComDomain}; + base::flat_set<PersistedTrialToken> tokens_a; + tokens_a.emplace(kTrialName, expiry, + blink::TrialToken::UsageRestriction::kNone, kTrialSignature, + partition_sites_a); + db_entries_[origin_a.Serialize()] = + origin_trials_pb::ProtoFromTokens(origin_a, tokens_a); - db_entries_[origin.Serialize()] = - origin_trials_pb::ProtoFromTokens(origin, tokens); + url::Origin origin_b = url::Origin::Create(GURL(kSecondaryExampleComOrigin)); + base::flat_set<std::string> partition_sites_b = {kExampleComDomain, + kGoogleComDomain}; + base::flat_set<PersistedTrialToken> tokens_b; + tokens_b.emplace(kTrialName, expiry, + blink::TrialToken::UsageRestriction::kNone, kTrialSignature, + partition_sites_b); + db_entries_[origin_b.Serialize()] = + origin_trials_pb::ProtoFromTokens(origin_b, tokens_b); InitPersistenceProvider(); - // One item should have been loaded - ht.ExpectUniqueSample("OriginTrials.PersistentOriginTrial.LevelDbLoadSize", 1, + // Two items should have been loaded + ht.ExpectUniqueSample("OriginTrials.PersistentOriginTrial.LevelDbLoadSize", 2, 1); - // The DB should not have been used before load + // The PartitionSetSize should be reported for each token individually. + ht.ExpectBucketCount("OriginTrials.PersistentOriginTrial.PartitionSetSize", 1, + 1); + ht.ExpectBucketCount("OriginTrials.PersistentOriginTrial.PartitionSetSize", 2, + 1); + // Both tokens are in a first-party partition. + ht.ExpectBucketCount( + "OriginTrials.PersistentOriginTrial.TokenHasFirstPartyPartition", true, + 2); + // The DB should not have been used before load. ht.ExpectUniqueSample( "OriginTrials.PersistentOriginTrial.OriginsAddedBeforeDbLoad", 0, 1); ht.ExpectUniqueSample( "OriginTrials.PersistentOriginTrial.OriginLookupsBeforeDbLoad", 0, 1); - base::flat_set<PersistedTrialToken> stored_tokens = - persistence_provider_->GetPersistentTrialTokens(origin); - EXPECT_EQ(tokens, stored_tokens); + EXPECT_EQ(tokens_a, + persistence_provider_->GetPersistentTrialTokens(origin_a)); + EXPECT_EQ(tokens_b, + persistence_provider_->GetPersistentTrialTokens(origin_b)); } TEST_F(LevelDbPersistenceProviderUnitTest, TokensLoadedFromDbOnStartupAreCleanedUpIfExpired) { base::HistogramTester ht; - url::Origin origin = url::Origin::Create(GURL(kTrialOrigin)); + url::Origin origin = url::Origin::Create(GURL(kExampleComOrigin)); + base::flat_set<std::string> partition_sites = {kExampleComDomain}; base::Time expiry = base::Time::Now() - base::Days(1); base::flat_set<PersistedTrialToken> tokens; tokens.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + kTrialSignature, partition_sites); db_entries_[origin.Serialize()] = origin_trials_pb::ProtoFromTokens(origin, tokens); @@ -241,22 +268,23 @@ TEST_F(LevelDbPersistenceProviderUnitTest, QueriesBeforeDbLoad) { base::HistogramTester ht; - url::Origin origin_a = url::Origin::Create(GURL(kTrialOrigin)); - url::Origin origin_b = url::Origin::Create(GURL(kTrialOriginSecondary)); + url::Origin origin_a = url::Origin::Create(GURL(kExampleComOrigin)); + url::Origin origin_b = url::Origin::Create(GURL(kSecondaryExampleComOrigin)); + base::flat_set<std::string> partition_sites = {kExampleComDomain}; base::Time expiry = base::Time::Now() + base::Days(365); base::flat_set<PersistedTrialToken> tokens_in_db; tokens_in_db.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + kTrialSignature, partition_sites); db_entries_[origin_a.Serialize()] = origin_trials_pb::ProtoFromTokens(origin_a, tokens_in_db); base::flat_set<PersistedTrialToken> tokens_before_load; tokens_before_load.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + kTrialSignature, partition_sites); base::flat_set<PersistedTrialToken> all_tokens; all_tokens.insert(tokens_in_db.begin(), tokens_in_db.end()); @@ -300,18 +328,19 @@ TEST_F(LevelDbPersistenceProviderUnitTest, LoadFromDbDoesNotOverwriteInMemoryData) { base::HistogramTester ht; - url::Origin origin = url::Origin::Create(GURL(kTrialOrigin)); + url::Origin origin = url::Origin::Create(GURL(kExampleComOrigin)); + base::flat_set<std::string> partition_sites = {kExampleComDomain}; base::Time expiry = base::Time::Now() + base::Days(365); base::flat_set<PersistedTrialToken> db_tokens; db_tokens.emplace(kTrialName, expiry, - blink::TrialToken::UsageRestriction::kNone, - kTrialSignature); + blink::TrialToken::UsageRestriction::kNone, kTrialSignature, + partition_sites); base::flat_set<PersistedTrialToken> live_tokens; live_tokens.emplace(kTrialName, expiry, blink::TrialToken::UsageRestriction::kNone, - kTrialSignatureAlternate); + kTrialSignatureAlternate, partition_sites); db_entries_[origin.Serialize()] = origin_trials_pb::ProtoFromTokens(origin, db_tokens);
diff --git a/components/origin_trials/browser/origin_trials.cc b/components/origin_trials/browser/origin_trials.cc index 421f4191..62eee407 100644 --- a/components/origin_trials/browser/origin_trials.cc +++ b/components/origin_trials/browser/origin_trials.cc
@@ -6,7 +6,9 @@ #include <algorithm> +#include "base/containers/flat_set.h" #include "components/origin_trials/common/persisted_trial_token.h" +#include "net/base/schemeful_site.h" #include "third_party/blink/public/common/origin_trials/origin_trials.h" #include "third_party/blink/public/common/origin_trials/trial_token.h" #include "third_party/blink/public/common/origin_trials/trial_token_result.h" @@ -16,6 +18,12 @@ namespace origin_trials { +namespace { +// A string to denote opaque origins for partitioning. It should not be +// possible to have a valid origin serialize to this value. +const char kOpaqueOriginPartitionKey[] = ":opaque"; +} // namespace + OriginTrials::OriginTrials( std::unique_ptr<OriginTrialsPersistenceProvider> persistence_provider, std::unique_ptr<blink::TrialTokenValidator> token_validator) @@ -26,46 +34,57 @@ base::flat_set<std::string> OriginTrials::GetPersistedTrialsForOrigin( const url::Origin& origin, + const url::Origin& partition_origin, const base::Time current_time) { - return GetPersistedTrialsForOriginWithMatch(origin, current_time, - absl::nullopt); + return GetPersistedTrialsForOriginWithMatch(origin, partition_origin, + current_time, absl::nullopt); } -bool OriginTrials::IsTrialPersistedForOrigin(const url::Origin& origin, - const base::StringPiece trial_name, - const base::Time current_time) { - return !GetPersistedTrialsForOriginWithMatch(origin, current_time, trial_name) +bool OriginTrials::IsTrialPersistedForOrigin( + const url::Origin& origin, + const url::Origin& partition_origin, + const base::StringPiece trial_name, + const base::Time current_time) { + return !GetPersistedTrialsForOriginWithMatch(origin, partition_origin, + current_time, trial_name) .empty(); } void OriginTrials::PersistTrialsFromTokens( const url::Origin& origin, + const url::Origin& partition_origin, const base::span<const std::string> header_tokens, const base::Time current_time) { - if (origin.opaque()) + if (origin.opaque()) { return; + } - base::flat_set<PersistedTrialToken> enabled_persistent_trial_tokens; + base::flat_set<PersistedTrialToken> existing_tokens = + persistence_provider_->GetPersistentTrialTokens(origin); + + std::vector<blink::TrialToken> valid_tokens; for (const base::StringPiece token : header_tokens) { blink::TrialTokenResult validation_result = trial_token_validator_->ValidateTokenAndTrial(token, origin, current_time); + const blink::TrialToken* parsed_token = validation_result.ParsedToken(); if (validation_result.Status() == blink::OriginTrialTokenStatus::kSuccess && blink::origin_trials::IsTrialPersistentToNextResponse( parsed_token->feature_name())) { - enabled_persistent_trial_tokens.emplace( - parsed_token->feature_name(), parsed_token->expiry_time(), - parsed_token->usage_restriction(), parsed_token->signature()); + valid_tokens.push_back(std::move(*parsed_token)); } } - persistence_provider_->SavePersistentTrialTokens( - origin, std::move(enabled_persistent_trial_tokens)); + UpdatePersistedTokenSet(existing_tokens, std::move(valid_tokens), + GetTokenPartitionSite(partition_origin)); + persistence_provider_->SavePersistentTrialTokens(origin, + std::move(existing_tokens)); } base::flat_set<std::string> OriginTrials::GetPersistedTrialsForOriginWithMatch( const url::Origin& origin, + const url::Origin& partition_origin, const base::Time current_time, const absl::optional<const base::StringPiece> trial_name_match) const { if (origin.opaque()) @@ -82,7 +101,9 @@ token.token_signature, current_time); bool persistent = blink::origin_trials::IsTrialPersistentToNextResponse( token.trial_name); - if (valid && persistent) { + if (valid && persistent && + token.partition_sites.contains( + GetTokenPartitionSite(partition_origin))) { // Move the string into the flat_set to avoid extra heap allocations enabled_trials.insert(std::move(token.trial_name)); } @@ -96,4 +117,56 @@ persistence_provider_->ClearPersistedTokens(); } +// static +std::string OriginTrials::GetTokenPartitionSite(const url::Origin& origin) { + if (origin.opaque()) { + return kOpaqueOriginPartitionKey; + } + return net::SchemefulSite(origin).Serialize(); +} + +// static +void OriginTrials::UpdatePersistedTokenSet( + base::flat_set<PersistedTrialToken>& token_set, + std::vector<blink::TrialToken> new_tokens, + std::string partition_site) { + // First, clean up token registrations for this origin and partition + // by removing any trials in the active partition that aren't being set + // by the new parameters. + for (PersistedTrialToken& token : token_set) { + const auto new_token_iter = + std::find_if(new_tokens.begin(), new_tokens.end(), + [&token](const blink::TrialToken& trial_token) { + return token.Matches(trial_token); + }); + + // Remove registration of the token for the first party or top-level site + // partition. + if (new_token_iter == new_tokens.end()) { + token.RemoveFromPartition(partition_site); + } + } + // Cleanup of tokens no longer in any partitions. + base::EraseIf(token_set, [](const PersistedTrialToken& token) { + return !token.InAnyPartition(); + }); + + // Update the set with new partition information. + for (blink::TrialToken& new_token : new_tokens) { + const auto found_token = + std::find_if(token_set.begin(), token_set.end(), + [&new_token](const PersistedTrialToken& existing_token) { + return existing_token.Matches(new_token); + }); + + if (found_token != token_set.end()) { + // Update the existing stored trial token with the metadata fields, as it + // may be a newly issued token. + found_token->AddToPartition(partition_site); + } else { + token_set.emplace(new_token, partition_site); + } + } +} + } // namespace origin_trials
diff --git a/components/origin_trials/browser/origin_trials.h b/components/origin_trials/browser/origin_trials.h index e88a035..e299fc1 100644 --- a/components/origin_trials/browser/origin_trials.h +++ b/components/origin_trials/browser/origin_trials.h
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "components/keyed_service/core/keyed_service.h" #include "components/origin_trials/common/origin_trials_persistence_provider.h" +#include "components/origin_trials/common/persisted_trial_token.h" #include "content/public/browser/origin_trials_controller_delegate.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/origin_trials/trial_token_validator.h" @@ -48,17 +49,21 @@ // content::OriginTrialsControllerDelegate void PersistTrialsFromTokens( const url::Origin& origin, + const url::Origin& partition_origin, const base::span<const std::string> header_tokens, const base::Time current_time) override; bool IsTrialPersistedForOrigin(const url::Origin& origin, + const url::Origin& partition_origin, const base::StringPiece trial_name, const base::Time current_time) override; base::flat_set<std::string> GetPersistedTrialsForOrigin( const url::Origin& origin, + const url::Origin& partition_origin, base::Time current_time) override; void ClearPersistedTokens() override; private: + friend class OriginTrialsTest; std::unique_ptr<OriginTrialsPersistenceProvider> persistence_provider_; std::unique_ptr<blink::TrialTokenValidator> trial_token_validator_; @@ -69,8 +74,22 @@ // that are still valid. base::flat_set<std::string> GetPersistedTrialsForOriginWithMatch( const url::Origin& origin, + const url::Origin& partition_origin, const base::Time current_time, const absl::optional<const base::StringPiece> trial_name_match) const; + + // Update the passed |token_set| with the new tokens, partitioned by + // |partition_site|. Performs the update directly on the passed |token_set|. + static void UpdatePersistedTokenSet( + base::flat_set<PersistedTrialToken>& token_set, + std::vector<blink::TrialToken> new_tokens, + std::string partition_site); + + // Get the 'site' used as the partitioning key for trial tokens. + // + // The key is the eTLD+1 of the |origin|, taking private registries such as + // blogspot.com into account. + static std::string GetTokenPartitionSite(const url::Origin& origin); }; } // namespace origin_trials
diff --git a/components/origin_trials/browser/origin_trials_unittest.cc b/components/origin_trials/browser/origin_trials_unittest.cc index 70fe3e5..5295726f 100644 --- a/components/origin_trials/browser/origin_trials_unittest.cc +++ b/components/origin_trials/browser/origin_trials_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <memory> +#include <utility> #include <vector> #include "base/containers/flat_set.h" @@ -24,6 +25,8 @@ const char kPersistentTrialName[] = "FrobulatePersistent"; const char kNonPersistentTrialName[] = "Frobulate"; const char kInvalidTrialName[] = "InvalidTrial"; +const char kTrialEnabledOriginA[] = "https://enabled.example.com"; +const char kTrialEnabledOriginB[] = "https://enabled.alternate.com"; // A dummy value that hasn't been explicitly disabled const char kDummyTokenSignature[] = ""; @@ -41,6 +44,18 @@ "V4YW1wbGUuY29tOjQ0MyIsICJmZWF0dXJlIjogIkZyb2J1bGF0ZVBlcnNpc3RlbnQiLCAiZXhw" "aXJ5IjogMjAwMDAwMDAwMH0="; +// Valid header token for FrobulatePersistent +// generated with +// tools/origin_trials/generate_token.py enabled.alternate.com +// FrobulatePersistent +// --expire-timestamp=2000000000 +const char kFrobulatePersistentTokenAlternate[] = + "A9djuSDQQSirNBctmtYIXSXBz9NyOjFWTMQeuZ2N3AaBA0O/" + "Rk8e1hZ8t5adUNzO5O+" + "vGamPUaicRBPNKwe2TAYAAABneyJvcmlnaW4iOiAiaHR0cHM6Ly9lbmFibGVkLmFsdGVybmF0Z" + "S5jb206NDQzIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlUGVyc2lzdGVudCIsICJleHBpcnkiOiA" + "yMDAwMDAwMDAwfQ=="; + // Valid header token for Frobulate // generated with // tools/origin_trials/generate_token.py enabled.example.com Frobulate @@ -51,6 +66,11 @@ "eyJvcmlnaW4iOiAiaHR0cHM6Ly9lbmFibGVkLmV4YW1wbGUuY29tOjQ0MyIsICJmZWF0dXJlIj" "ogIkZyb2J1bGF0ZSIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ=="; +// Valid header token for Frobulate +// generated with +// tools/origin_trials/generate_token.py enabled.example.com +// FrobulateManualCompletion +// --expire-timestamp=2000000000 const char kFrobulateManualCompletionToken[] = "A4TCodS8fnQFVyShubc4TKr+" "Ss6br97EBk4Kh1bQiskjJHwHXKjhxMjwviiL60RD4byiVF3D9UmoPdXcz7Kg8w8AAAB2eyJvcm" @@ -96,19 +116,56 @@ base::flat_set<std::string> user_disabled_trials_; }; +} // namespace + class OriginTrialsTest : public testing::Test { public: OriginTrialsTest() : origin_trials_(std::make_unique<test::TestPersistenceProvider>(), std::make_unique<blink::TrialTokenValidator>()), - trial_enabled_origin_( - url::Origin::Create(GURL("https://enabled.example.com"))) {} + trial_enabled_origin_(url::Origin::Create(GURL(kTrialEnabledOriginA))) { + } OriginTrialsTest(const OriginTrialsTest&) = delete; OriginTrialsTest& operator=(const OriginTrialsTest&) = delete; ~OriginTrialsTest() override = default; + // PersistTrialsFromTokens using |origin| as partition origin. + void PersistTrialsFromTokens(const url::Origin& origin, + base::span<std::string> tokens, + base::Time time) { + origin_trials_.PersistTrialsFromTokens(origin, + /* partition_origin*/ origin, tokens, + time); + } + + // GetPersistedTrialsForOrigin using |trial_origin| as partition origin. + base::flat_set<std::string> GetPersistedTrialsForOrigin( + const url::Origin& trial_origin, + base::Time lookup_time) { + return origin_trials_.GetPersistedTrialsForOrigin( + trial_origin, /* partition_origin */ trial_origin, lookup_time); + } + + // IsTrialPersistedForOrigin using |origin| as partition origin. + bool IsTrialPersistedForOrigin(const url::Origin& origin, + const std::string& trial_name, + base::Time lookup_time) { + return origin_trials_.IsTrialPersistedForOrigin( + origin, /* partition_origin */ origin, trial_name, lookup_time); + } + + std::string GetTokenPartitionSite(const url::Origin& origin) { + return OriginTrials::GetTokenPartitionSite(origin); + } + + // Test helper that creates an origin for the domain_name with https scheme + // and port 443. + url::Origin DomainAsOrigin(const std::string& domain_name) { + return url::Origin::CreateFromNormalizedTuple("https", domain_name, 443); + } + protected: OriginTrials origin_trials_; url::Origin trial_enabled_origin_; @@ -117,19 +174,15 @@ TEST_F(OriginTrialsTest, CleanObjectHasNoPersistentTrials) { EXPECT_TRUE( - origin_trials_ - .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime) - .empty()); + GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime).empty()); } TEST_F(OriginTrialsTest, EnabledTrialsArePersisted) { std::vector<std::string> tokens = {kFrobulatePersistentToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); base::flat_set<std::string> enabled_trials = - origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime); ASSERT_EQ(1ul, enabled_trials.size()); EXPECT_TRUE(enabled_trials.contains(kPersistentTrialName)); } @@ -137,12 +190,10 @@ TEST_F(OriginTrialsTest, OnlyPersistentTrialsAreEnabled) { std::vector<std::string> tokens = {kFrobulateToken, kFrobulatePersistentToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); base::flat_set<std::string> enabled_trials = - origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime); ASSERT_EQ(1ul, enabled_trials.size()); EXPECT_TRUE(enabled_trials.contains(kPersistentTrialName)); EXPECT_FALSE(enabled_trials.contains(kNonPersistentTrialName)); @@ -150,45 +201,37 @@ TEST_F(OriginTrialsTest, ResetClearsPersistedTrials) { std::vector<std::string> tokens = {kFrobulatePersistentToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); EXPECT_FALSE( - origin_trials_ - .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime) - .empty()); + GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime).empty()); tokens = {}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); EXPECT_TRUE( - origin_trials_ - .GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime) - .empty()); + GetPersistedTrialsForOrigin(trial_enabled_origin_, kValidTime).empty()); } TEST_F(OriginTrialsTest, TrialNotEnabledByDefault) { - EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin( - trial_enabled_origin_, kPersistentTrialName, kValidTime)); + EXPECT_FALSE(IsTrialPersistedForOrigin(trial_enabled_origin_, + kPersistentTrialName, kValidTime)); } TEST_F(OriginTrialsTest, TrialEnablesFeature) { std::vector<std::string> tokens = {kFrobulatePersistentToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); - EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( - trial_enabled_origin_, kPersistentTrialName, kValidTime)); + EXPECT_TRUE(IsTrialPersistedForOrigin(trial_enabled_origin_, + kPersistentTrialName, kValidTime)); } TEST_F(OriginTrialsTest, TrialDoesNotEnableOtherFeatures) { std::vector<std::string> tokens = {kFrobulatePersistentToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + PersistTrialsFromTokens(trial_enabled_origin_, tokens, kValidTime); - EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin( - trial_enabled_origin_, kNonPersistentTrialName, kValidTime)); + EXPECT_FALSE(IsTrialPersistedForOrigin(trial_enabled_origin_, + kNonPersistentTrialName, kValidTime)); } // Check that a stored trial name is not returned if that trial is no longer @@ -198,21 +241,27 @@ std::make_unique<test::TestPersistenceProvider>(); base::Time token_expiry = base::Time::FromTimeT(2000000000); + base::flat_set<std::string> partition_sites = { + GetTokenPartitionSite(trial_enabled_origin_)}; base::flat_set<PersistedTrialToken> stored_tokens = { {kNonPersistentTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}, + blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature, + partition_sites}, {kInvalidTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}, + blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature, + partition_sites}, {kPersistentTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}}; + blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature, + partition_sites}}; persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_, stored_tokens); OriginTrials origin_trials(std::move(persistence_provider), std::make_unique<blink::TrialTokenValidator>()); base::flat_set<std::string> enabled_trials = - origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + origin_trials.GetPersistedTrialsForOrigin( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + kValidTime); ASSERT_EQ(1ul, enabled_trials.size()); EXPECT_EQ(kPersistentTrialName, *(enabled_trials.begin())); } @@ -224,9 +273,12 @@ std::make_unique<test::TestPersistenceProvider>(); base::Time token_expiry = base::Time::FromTimeT(2000000000); + base::flat_set<std::string> partition_sites = { + GetTokenPartitionSite(trial_enabled_origin_)}; base::flat_set<PersistedTrialToken> stored_tokens = { {kPersistentTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}}; + blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature, + partition_sites}}; persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_, stored_tokens); @@ -235,8 +287,9 @@ OriginTrials origin_trials(std::move(persistence_provider), std::make_unique<blink::TrialTokenValidator>()); base::flat_set<std::string> enabled_trials = - origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + origin_trials.GetPersistedTrialsForOrigin( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + kValidTime); EXPECT_TRUE(enabled_trials.empty()); } @@ -247,9 +300,12 @@ std::make_unique<test::TestPersistenceProvider>(); base::Time token_expiry = base::Time::FromTimeT(2000000000); + base::flat_set<std::string> partition_sites = { + GetTokenPartitionSite(trial_enabled_origin_)}; base::flat_set<PersistedTrialToken> stored_tokens = { {kPersistentTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature}}; + blink::TrialToken::UsageRestriction::kNone, kDummyTokenSignature, + partition_sites}}; persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_, stored_tokens); @@ -258,8 +314,9 @@ OriginTrials origin_trials(std::move(persistence_provider), std::make_unique<blink::TrialTokenValidator>()); base::flat_set<std::string> enabled_trials = - origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + origin_trials.GetPersistedTrialsForOrigin( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + kValidTime); EXPECT_TRUE(enabled_trials.empty()); } @@ -268,9 +325,12 @@ std::make_unique<test::TestPersistenceProvider>(); base::Time token_expiry = base::Time::FromTimeT(2000000000); + base::flat_set<std::string> partition_sites = { + GetTokenPartitionSite(trial_enabled_origin_)}; base::flat_set<PersistedTrialToken> stored_tokens = { {kPersistentTrialName, token_expiry, - blink::TrialToken::UsageRestriction::kSubset, kDummyTokenSignature}}; + blink::TrialToken::UsageRestriction::kSubset, kDummyTokenSignature, + partition_sites}}; persistence_provider->SavePersistentTrialTokens(trial_enabled_origin_, stored_tokens); @@ -279,48 +339,148 @@ OriginTrials origin_trials(std::move(persistence_provider), std::make_unique<blink::TrialTokenValidator>()); base::flat_set<std::string> enabled_trials = - origin_trials.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kValidTime); + origin_trials.GetPersistedTrialsForOrigin( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + kValidTime); EXPECT_TRUE(enabled_trials.empty()); } TEST_F(OriginTrialsTest, GracePeriodIsRespected) { std::vector<std::string> tokens = {kFrobulateManualCompletionToken}; - origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, tokens, - kValidTime); + origin_trials_.PersistTrialsFromTokens( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, tokens, + kValidTime); base::flat_set<std::string> enabled_trials = - origin_trials_.GetPersistedTrialsForOrigin(trial_enabled_origin_, - kExpiryTime); + origin_trials_.GetPersistedTrialsForOrigin( + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + kExpiryTime); EXPECT_EQ(1ul, enabled_trials.size()) << "Expect trial to be valid at the expiry time limit"; base::Time in_grace_period = kExpiryTime + base::Days(1); enabled_trials = origin_trials_.GetPersistedTrialsForOrigin( - trial_enabled_origin_, in_grace_period); + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + in_grace_period); EXPECT_EQ(1ul, enabled_trials.size()) << "Expect trial to be valid within the grace period"; base::Time end_of_grace_period = kExpiryTime + blink::kExpiryGracePeriod; enabled_trials = origin_trials_.GetPersistedTrialsForOrigin( - trial_enabled_origin_, end_of_grace_period); + trial_enabled_origin_, /*partition_origin=*/trial_enabled_origin_, + end_of_grace_period); EXPECT_EQ(0ul, enabled_trials.size()) << "Do not expect the trial to be valid after the grace period ends"; } -TEST_F(OriginTrialsTest, GracefullyHandleOpaqueOrigins) { - std::vector<std::string> tokens = {kFrobulateManualCompletionToken}; +TEST_F(OriginTrialsTest, DoNotPersistTokensForOpaqueOrigins) { + std::vector<std::string> tokens = {kFrobulatePersistentToken}; url::Origin opaque_origin; - origin_trials_.PersistTrialsFromTokens(opaque_origin, tokens, kValidTime); - // No assert, this just shouldn't crash + // Opaque primary origin + origin_trials_.PersistTrialsFromTokens( + opaque_origin, /*partition_origin=*/trial_enabled_origin_, tokens, + kValidTime); - base::flat_set<std::string> trials = - origin_trials_.GetPersistedTrialsForOrigin(opaque_origin, kValidTime); - EXPECT_TRUE(trials.empty()); - - EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin( - opaque_origin, kPersistentTrialName, kValidTime)); + EXPECT_TRUE(origin_trials_ + .GetPersistedTrialsForOrigin( + opaque_origin, /*partition_origin=*/trial_enabled_origin_, + kValidTime) + .empty()); } -} // namespace -} // namespace origin_trials \ No newline at end of file +TEST_F(OriginTrialsTest, PersistTokensInOpaquePartition) { + std::vector<std::string> tokens = {kFrobulatePersistentToken}; + url::Origin opaque_origin; + // Opaque partition origin + origin_trials_.PersistTrialsFromTokens(trial_enabled_origin_, + /*partition_origin=*/opaque_origin, + tokens, kValidTime); + + EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( + trial_enabled_origin_, /*partition_origin=*/opaque_origin, + kPersistentTrialName, kValidTime)); +} + +TEST_F(OriginTrialsTest, TokensArePartitionedByTopLevelSite) { + url::Origin origin_a = trial_enabled_origin_; + url::Origin origin_b = url::Origin::Create(GURL(kTrialEnabledOriginB)); + url::Origin partition_site_a = origin_a; + url::Origin partition_site_b = origin_b; + std::vector<std::string> tokens_a = {kFrobulatePersistentToken}; + std::vector<std::string> tokens_b = {kFrobulatePersistentTokenAlternate}; + + origin_trials_.PersistTrialsFromTokens(origin_a, partition_site_a, tokens_a, + kValidTime); + origin_trials_.PersistTrialsFromTokens(origin_a, partition_site_b, tokens_a, + kValidTime); + + origin_trials_.PersistTrialsFromTokens(origin_b, partition_site_b, tokens_b, + kValidTime); + + // Only expect trials to be enabled for partitions where they have been set + EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( + origin_a, partition_site_a, kPersistentTrialName, kValidTime)); + + EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( + origin_a, partition_site_b, kPersistentTrialName, kValidTime)); + + EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( + origin_b, partition_site_b, kPersistentTrialName, kValidTime)); + + EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin( + origin_b, partition_site_a, kPersistentTrialName, kValidTime)); + + // Removing a token should only be from one partition + origin_trials_.PersistTrialsFromTokens(origin_a, partition_site_b, {}, + kValidTime); + + EXPECT_TRUE(origin_trials_.IsTrialPersistedForOrigin( + origin_a, partition_site_a, kPersistentTrialName, kValidTime)); + + EXPECT_FALSE(origin_trials_.IsTrialPersistedForOrigin( + origin_a, partition_site_b, kPersistentTrialName, kValidTime)); +} + +TEST_F(OriginTrialsTest, PartitionSiteIsETLDPlusOne) { + EXPECT_EQ("https://example.com", + GetTokenPartitionSite(DomainAsOrigin("example.com"))); + EXPECT_EQ("https://example.com", + GetTokenPartitionSite(DomainAsOrigin("enabled.example.com"))); + EXPECT_EQ("https://example.co.uk", + GetTokenPartitionSite(DomainAsOrigin("example.co.uk"))); + EXPECT_EQ("https://example.co.uk", + GetTokenPartitionSite(DomainAsOrigin("enabled.example.co.uk"))); +} + +TEST_F(OriginTrialsTest, + PartitionSiteUsesPrivateRegistryAsEffectiveTopLevelDomain) { + EXPECT_EQ("https://example.blogspot.com", + GetTokenPartitionSite(DomainAsOrigin("example.blogspot.com"))); + EXPECT_EQ( + "https://example.blogspot.com", + GetTokenPartitionSite(DomainAsOrigin("enabled.example.blogspot.com"))); +} + +TEST_F(OriginTrialsTest, PartitionSiteCanBeIpAddress) { + EXPECT_EQ("http://127.0.0.1", + GetTokenPartitionSite(url::Origin::CreateFromNormalizedTuple( + "http", "127.0.0.1", 80))); +} + +TEST_F(OriginTrialsTest, PartitionSiteCanBeLocalhost) { + EXPECT_EQ("http://localhost", + GetTokenPartitionSite(url::Origin::CreateFromNormalizedTuple( + "http", "localhost", 80))); +} + +TEST_F(OriginTrialsTest, PartitionSiteCanHaveNonstandardPort) { + EXPECT_EQ("http://example.com", + GetTokenPartitionSite(url::Origin::CreateFromNormalizedTuple( + "http", "enabled.example.com", 5555))); +} + +TEST_F(OriginTrialsTest, OpaqueOriginAsPartitionSiteSerializesAsSentinelValue) { + EXPECT_EQ(":opaque", GetTokenPartitionSite(url::Origin())); +} + +} // namespace origin_trials
diff --git a/components/origin_trials/common/persisted_trial_token.cc b/components/origin_trials/common/persisted_trial_token.cc index f878aa1..7a977db0c 100644 --- a/components/origin_trials/common/persisted_trial_token.cc +++ b/components/origin_trials/common/persisted_trial_token.cc
@@ -7,6 +7,7 @@ #include <tuple> #include "base/base64.h" +#include "base/check_op.h" #include "base/json/values_util.h" #include "base/values.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -22,12 +23,66 @@ } // namespace +PersistedTrialToken::PersistedTrialToken( + std::string name, + base::Time expiry, + blink::TrialToken::UsageRestriction usage, + std::string signature, + base::flat_set<std::string> partitions) + : trial_name(std::move(name)), + token_expiry(expiry), + usage_restriction(usage), + token_signature(std::move(signature)), + partition_sites(std::move(partitions)) {} + +PersistedTrialToken::PersistedTrialToken(const blink::TrialToken& parsed_token, + const std::string& partition_site) + : PersistedTrialToken(parsed_token.feature_name(), + parsed_token.expiry_time(), + parsed_token.usage_restriction(), + parsed_token.signature(), + base::flat_set<std::string>()) { + AddToPartition(partition_site); +} + +PersistedTrialToken::~PersistedTrialToken() = default; +PersistedTrialToken::PersistedTrialToken(const PersistedTrialToken&) = default; +PersistedTrialToken& PersistedTrialToken::operator=( + const PersistedTrialToken&) = default; +PersistedTrialToken::PersistedTrialToken(PersistedTrialToken&&) = default; +PersistedTrialToken& PersistedTrialToken::operator=(PersistedTrialToken&&) = + default; + +void PersistedTrialToken::AddToPartition(const std::string& partition_site) { + DCHECK_NE("", partition_site); + partition_sites.insert(partition_site); +} + +void PersistedTrialToken::RemoveFromPartition( + const std::string& partition_site) { + partition_sites.erase(partition_site); +} + +bool PersistedTrialToken::InAnyPartition() const { + return partition_sites.size() > 0; +} + +bool PersistedTrialToken::Matches(const blink::TrialToken& token) const { + return trial_name == token.feature_name() && + token_expiry == token.expiry_time() && + token_signature == token.signature(); +} + bool operator<(const PersistedTrialToken& a, const PersistedTrialToken& b) { return to_tuple(a) < to_tuple(b); } bool operator==(const PersistedTrialToken& a, const PersistedTrialToken& b) { - return to_tuple(a) == to_tuple(b); + return to_tuple(a) == to_tuple(b) && a.partition_sites == b.partition_sites; +} + +bool operator!=(const PersistedTrialToken& a, const PersistedTrialToken& b) { + return !(a == b); } std::ostream& operator<<(std::ostream& out, const PersistedTrialToken& token) { @@ -37,7 +92,12 @@ out << "usage: " << static_cast<int>(token.usage_restriction) << ", "; std::string signature_blob; base::Base64Encode(token.token_signature, &signature_blob); - out << "signature: " << signature_blob; + out << "signature: " << signature_blob << ", "; + out << "partition_sites: ["; + for (const auto& site : token.partition_sites) { + out << site << " "; + } + out << "]"; out << "}"; return out; }
diff --git a/components/origin_trials/common/persisted_trial_token.h b/components/origin_trials/common/persisted_trial_token.h index 214f7de..41f548b6 100644 --- a/components/origin_trials/common/persisted_trial_token.h +++ b/components/origin_trials/common/persisted_trial_token.h
@@ -7,34 +7,64 @@ #include <string> +#include "base/containers/flat_set.h" #include "base/time/time.h" #include "third_party/blink/public/common/origin_trials/trial_token.h" namespace origin_trials { // Parsed information about a token to be persisted. +// +// The token stores partitioning information as a set of strings, but this is +// not part of the tokens sort order with respect to being inserted in sorted +// sets. struct PersistedTrialToken { std::string trial_name; base::Time token_expiry; blink::TrialToken::UsageRestriction usage_restriction; std::string token_signature; + base::flat_set<std::string> partition_sites; PersistedTrialToken(std::string name, base::Time expiry, blink::TrialToken::UsageRestriction usage, - std::string signature) - : trial_name(std::move(name)), - token_expiry(expiry), - usage_restriction(usage), - token_signature(std::move(signature)) {} + std::string signature, + base::flat_set<std::string> partition_sites); + PersistedTrialToken(const blink::TrialToken& parsed_token, + const std::string& partition_site); + ~PersistedTrialToken(); + + PersistedTrialToken(const PersistedTrialToken&); + PersistedTrialToken& operator=(const PersistedTrialToken&); + + PersistedTrialToken(PersistedTrialToken&&); + PersistedTrialToken& operator=(PersistedTrialToken&&); + + // Add the trial token to the partition of the passed |partition_site|. + void AddToPartition(const std::string& partition_site); + + // Removes the trial token from the partition of the given |partition_site|. + void RemoveFromPartition(const std::string& partition_site); + + // Returns whether this PersistedTrialToken is currently logically in any + // top-level partition, either first-party or third-party. + bool InAnyPartition() const; + + // Return true if this token matches the information in |trial_token|, + // specifically trial name, expiry time, and signature. + bool Matches(const blink::TrialToken& trial_token) const; }; -// Comparison operator to let us store PersistedTokens in a flat_set +// Comparison operator to let us store PersistedTokens in a flat_set. +// Does not take partitioning metadata into account. bool operator<(const PersistedTrialToken& a, const PersistedTrialToken& b); -// Equality operator for testing +// Equality operator for testing. bool operator==(const PersistedTrialToken& a, const PersistedTrialToken& b); +// In-equality operator for testing +bool operator!=(const PersistedTrialToken& a, const PersistedTrialToken& b); + // Stream operator, mainly for GTEST output std::ostream& operator<<(std::ostream& out, const PersistedTrialToken& token);
diff --git a/components/origin_trials/common/persisted_trial_token_unittest.cc b/components/origin_trials/common/persisted_trial_token_unittest.cc index 6b32e6a..4e041e2 100644 --- a/components/origin_trials/common/persisted_trial_token_unittest.cc +++ b/components/origin_trials/common/persisted_trial_token_unittest.cc
@@ -4,21 +4,69 @@ #include "components/origin_trials/common/persisted_trial_token.h" -#include <sstream> #include <string> +#include "base/containers/flat_set.h" +#include "base/strings/string_util.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/origin_trials/trial_token.h" +#include "url/origin.h" namespace origin_trials { namespace { +const char kTrialTopLevelSite[] = "example.com"; + +TEST(PersistedTrialTokenTest, ConstructFromBlinkToken) { + url::Origin origin = + url::Origin::CreateFromNormalizedTuple("https", "example.com", 443); + std::string trial_name = "FrobulatePersistent"; + base::Time expiry = base::Time::Now(); + std::string signature = "signature"; + + std::unique_ptr<blink::TrialToken> blink_token = + blink::TrialToken::CreateTrialTokenForTesting( + origin, /*match_subdomains=*/false, trial_name, expiry, + /*is_third_party=*/false, + blink::TrialToken::UsageRestriction::kSubset, signature); + PersistedTrialToken token(*blink_token, kTrialTopLevelSite); + + EXPECT_EQ(trial_name, token.trial_name); + EXPECT_EQ(expiry, token.token_expiry); + EXPECT_EQ(signature, token.token_signature); + EXPECT_EQ(blink::TrialToken::UsageRestriction::kSubset, + token.usage_restriction); +} + +TEST(PersistedTrialTokenTest, Partitioning) { + std::string trial_name = "FrobulatePersistent"; + base::Time expiry = base::Time::Now(); + std::string signature = "signature"; + + base::flat_set<std::string> partition_sites = {kTrialTopLevelSite}; + PersistedTrialToken token(trial_name, expiry, + blink::TrialToken::UsageRestriction::kNone, + signature, partition_sites); + + EXPECT_TRUE(token.InAnyPartition()) + << "Was constructed with one partition set"; + + token.RemoveFromPartition(kTrialTopLevelSite); + EXPECT_FALSE(token.InAnyPartition()) + << "Should not be in any partition after removal"; + + token.AddToPartition(kTrialTopLevelSite); + EXPECT_TRUE(token.InAnyPartition()) << "Added to a partition"; +} + TEST(PersistedTrialTokenTest, TestLessThan) { base::Time expiry = base::Time::Now(); base::Time higher_expiry = expiry + base::Hours(1); std::string signature = "signature_a"; std::string higher_signature = "signature_b"; + base::flat_set<std::string> partition_sites = {kTrialTopLevelSite}; blink::TrialToken::UsageRestriction restriction_none = blink::TrialToken::UsageRestriction::kNone; @@ -26,41 +74,36 @@ blink::TrialToken::UsageRestriction::kSubset; // Tokens should be sorted by name all else being equal - EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature), - PersistedTrialToken("b", expiry, restriction_none, signature)); + EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("b", expiry, restriction_none, signature, + partition_sites)); // Tokens should be sorted by expiry all else being equal - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_none, signature), - PersistedTrialToken("a", higher_expiry, restriction_none, signature)); + EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", higher_expiry, restriction_none, signature, + partition_sites)); // Tokens should be sorted by usage restriction all else being equal - EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature), - PersistedTrialToken("a", expiry, restriction_subset, signature)); + EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_subset, signature, + partition_sites)); // Tokens should be sorted by signature all else being equal - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_none, signature), - PersistedTrialToken("a", expiry, restriction_none, higher_signature)); + EXPECT_LT(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_none, higher_signature, + partition_sites)); - // Name should be the primary sorting factor - EXPECT_LT( - PersistedTrialToken("a", higher_expiry, restriction_none, signature), - PersistedTrialToken("b", expiry, restriction_none, signature)); - EXPECT_LT(PersistedTrialToken("a", expiry, restriction_subset, signature), - PersistedTrialToken("b", expiry, restriction_none, signature)); - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_none, higher_signature), - PersistedTrialToken("b", expiry, restriction_none, signature)); + // Partition set is not part of sort order / token identity (for sets) + EXPECT_FALSE(PersistedTrialToken("a", expiry, restriction_none, signature, + base::flat_set<std::string>()) < + PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites)); - // Expiry should be the secondary sorting factor - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_subset, signature), - PersistedTrialToken("a", higher_expiry, restriction_none, signature)); - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_none, higher_signature), - PersistedTrialToken("a", higher_expiry, restriction_none, signature)); - // Subset should be the third sorting factor - EXPECT_LT( - PersistedTrialToken("a", expiry, restriction_none, higher_signature), - PersistedTrialToken("a", expiry, restriction_subset, signature)); + EXPECT_FALSE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites) < + PersistedTrialToken("a", expiry, restriction_none, signature, + base::flat_set<std::string>())); } TEST(PersistedTrialTokenTest, TestEquals) { @@ -72,24 +115,51 @@ blink::TrialToken::UsageRestriction::kNone; blink::TrialToken::UsageRestriction restriction_subset = blink::TrialToken::UsageRestriction::kSubset; + base::flat_set<std::string> partition_sites = {kTrialTopLevelSite}; // Two tokens with equal objects should be equal - EXPECT_EQ(PersistedTrialToken("a", expiry, restriction_none, signature), - PersistedTrialToken("a", expiry, restriction_none, signature)); + EXPECT_EQ(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites)); // Tokens should not be equal if their fields differ - EXPECT_FALSE(PersistedTrialToken("a", expiry, restriction_none, signature) == - PersistedTrialToken("b", expiry, restriction_none, signature)); + EXPECT_NE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("b", expiry, restriction_none, signature, + partition_sites)); - EXPECT_FALSE( - PersistedTrialToken("a", expiry, restriction_none, signature) == - PersistedTrialToken("a", higher_expiry, restriction_none, signature)); + EXPECT_NE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", higher_expiry, restriction_none, signature, + partition_sites)); - EXPECT_FALSE(PersistedTrialToken("a", expiry, restriction_none, signature) == - PersistedTrialToken("a", expiry, restriction_subset, signature)); + EXPECT_NE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_subset, signature, + partition_sites)); - EXPECT_FALSE( - PersistedTrialToken("a", expiry, restriction_none, signature) == - PersistedTrialToken("a", expiry, restriction_none, higher_signature)); + EXPECT_NE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_none, higher_signature, + partition_sites)); + + EXPECT_NE(PersistedTrialToken("a", expiry, restriction_none, signature, + partition_sites), + PersistedTrialToken("a", expiry, restriction_none, signature, + base::flat_set<std::string>())); +} + +TEST(PersistedTrialTokenTest, StreamOperatorTest) { + // Ensure that streaming the token produces non-empty output that contains the + // name of the token. + base::flat_set<std::string> partition_sites = {kTrialTopLevelSite}; + std::string token_name = "TokenNameInExpectedOutput"; + PersistedTrialToken token(token_name, base::Time::Now(), + blink::TrialToken::UsageRestriction::kSubset, + "signature", partition_sites); + std::string token_str = base::StreamableToString(token); + EXPECT_NE("", token_str); + EXPECT_NE(std::string::npos, token_str.find(token_name)); } } // namespace
diff --git a/components/origin_trials/proto/db_trial_token.proto b/components/origin_trials/proto/db_trial_token.proto index 060e04e..8b1a387 100644 --- a/components/origin_trials/proto/db_trial_token.proto +++ b/components/origin_trials/proto/db_trial_token.proto
@@ -13,6 +13,8 @@ optional uint64 token_expiry = 2; optional uint32 usage_restriction = 3; optional bytes token_signature = 4; + + repeated string partition_sites = 5; } // Message to store an already-parsed origin to avoid re-parsing origins from
diff --git a/components/origin_trials/proto/proto_util.cc b/components/origin_trials/proto/proto_util.cc index 98a09d7b6..0d70d65 100644 --- a/components/origin_trials/proto/proto_util.cc +++ b/components/origin_trials/proto/proto_util.cc
@@ -33,6 +33,9 @@ proto->set_token_signature(token.token_signature); proto->set_usage_restriction( static_cast<uint32_t>(token.usage_restriction)); + for (const auto& site : token.partition_sites) { + proto->add_partition_sites(site); + } } return entries; }
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc index 7a2f5b2..48a1cff 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
@@ -1391,8 +1391,9 @@ public: MetricsWebContentsObserverBackForwardCacheTest() { feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc index fa8ba8b..55d900e 100644 --- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -162,6 +162,30 @@ ukm::GetExponentialBucketMin(rounded.Abs(), kBucketSpacing); } +void RecordPageLoadInitiatorForAdTaggingUkm( + content::NavigationHandle* navigation_handle) { + auto* ukm_recorder = ukm::UkmRecorder::Get(); + + ukm::builders::PageLoadInitiatorForAdTagging builder( + navigation_handle->GetRenderFrameHost()->GetPageUkmSourceId()); + + bool renderer_initiated = navigation_handle->IsRendererInitiated(); + bool renderer_initiated_with_user_activation = + (navigation_handle->GetNavigationInitiatorActivationAndAdStatus() != + blink::mojom::NavigationInitiatorActivationAndAdStatus:: + kDidNotStartWithTransientActivation); + bool renderer_initiated_with_user_activation_from_ad = + (navigation_handle->GetNavigationInitiatorActivationAndAdStatus() == + blink::mojom::NavigationInitiatorActivationAndAdStatus:: + kStartedWithTransientActivationFromAd); + + builder.SetFromUser(!renderer_initiated || + renderer_initiated_with_user_activation); + builder.SetFromAdClick(renderer_initiated_with_user_activation_from_ad); + + builder.Record(ukm_recorder->Get()); +} + } // namespace // static @@ -303,6 +327,8 @@ content::NavigationHandle* navigation_handle) { DCHECK(ad_frames_data_.empty()); + RecordPageLoadInitiatorForAdTaggingUkm(navigation_handle); + page_load_is_reload_ = navigation_handle->GetReloadType() != content::ReloadType::NONE;
diff --git a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc index 3c382ae..7051494 100644 --- a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
@@ -57,6 +57,14 @@ "PageLoad.InteractiveTiming.WorstUserInteractionLatency.MaxEventDuration." "Prerender"; +// Intentionally this metric doesn't record observer events per trigger type +// (e.g., SpeculationRules) because some functions can be called before +// `PrerenderPageLoadMetricsObserver::trigger_type_` is set (e.g., when +// `OnComplete()` called from the destructor of PageLoadTracker before +// prerender activation). +const char kPageLoadPrerenderObserverEvent[] = + "PageLoad.Internal.Prerender2.ObserverEvent"; + } // namespace internal PrerenderPageLoadMetricsObserver::PrerenderPageLoadMetricsObserver() = default; @@ -84,6 +92,10 @@ PrerenderPageLoadMetricsObserver::OnPrerenderStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnPrerenderStart); + // TODO(https://crbug.com/1335481): Prerendering pages embedding FencedFrames // are not supported. DCHECK(navigation_handle->GetNavigatingFrameType() != @@ -93,6 +105,10 @@ void PrerenderPageLoadMetricsObserver::DidActivatePrerenderedPage( content::NavigationHandle* navigation_handle) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kDidActivatePrerenderedPage); + // Copy the trigger type and histogram suffix for an embedder. These data will // be lost after NavigationRequest is destroyed. DCHECK(!trigger_type_.has_value()); @@ -129,6 +145,10 @@ void PrerenderPageLoadMetricsObserver::OnFirstPaintInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstPaintInPage); + if (!WasActivatedInForegroundOptionalEventInForeground( timing.paint_timing->first_paint, GetDelegate())) { return; @@ -143,6 +163,10 @@ void PrerenderPageLoadMetricsObserver::OnFirstContentfulPaintInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstContentfulPaintInPage); + if (!WasActivatedInForegroundOptionalEventInForeground( timing.paint_timing->first_contentful_paint, GetDelegate())) { return; @@ -162,6 +186,10 @@ void PrerenderPageLoadMetricsObserver::OnFirstInputInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnFirstInputInPage); + if (!WasActivatedInForegroundOptionalEventInForeground( timing.interactive_timing->first_input_timestamp, GetDelegate())) { return; @@ -179,12 +207,18 @@ void PrerenderPageLoadMetricsObserver::OnComplete( const page_load_metrics::mojom::PageLoadTiming& timing) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kOnComplete); RecordSessionEndHistograms(timing, /*app_entering_background=*/false); } page_load_metrics::PageLoadMetricsObserver::ObservePolicy PrerenderPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground( const page_load_metrics::mojom::PageLoadTiming& timing) { + base::UmaHistogramEnumeration(internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent:: + kFlushMetricsOnAppEnterBackground); RecordSessionEndHistograms(timing, /*app_entering_background=*/true); return STOP_OBSERVING; } @@ -192,6 +226,10 @@ void PrerenderPageLoadMetricsObserver::RecordSessionEndHistograms( const page_load_metrics::mojom::PageLoadTiming& main_frame_timing, bool app_entering_background) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordSessionEndHistograms); + if (!GetDelegate().WasPrerenderedThenActivatedInForeground() || !main_frame_timing.activation_start) { // Even if the page was activated, activation_start may not yet been @@ -246,6 +284,10 @@ void PrerenderPageLoadMetricsObserver::RecordLayoutShiftScoreMetrics( const page_load_metrics::mojom::PageLoadTiming& main_frame_timing) { + base::UmaHistogramEnumeration( + internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent::kRecordLayoutShiftScoreMetrics); + DCHECK(GetDelegate().WasPrerenderedThenActivatedInForeground()); DCHECK(main_frame_timing.activation_start); @@ -279,6 +321,10 @@ } void PrerenderPageLoadMetricsObserver::RecordNormalizedResponsivenessMetrics() { + base::UmaHistogramEnumeration(internal::kPageLoadPrerenderObserverEvent, + internal::PageLoadPrerenderObserverEvent:: + kRecordNormalizedResponsivenessMetrics); + DCHECK(GetDelegate().WasPrerenderedThenActivatedInForeground()); const page_load_metrics::NormalizedResponsivenessMetrics&
diff --git a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h index 56283dc9..f14f068 100644 --- a/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h +++ b/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.h
@@ -32,6 +32,24 @@ extern const char kHistogramPrerenderWorstUserInteractionLatencyMaxEventDuration[]; +extern const char kPageLoadPrerenderObserverEvent[]; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class PageLoadPrerenderObserverEvent { + kOnPrerenderStart = 0, + kDidActivatePrerenderedPage = 1, + kOnFirstPaintInPage = 2, + kOnFirstContentfulPaintInPage = 3, + kOnFirstInputInPage = 4, + kOnComplete = 5, + kFlushMetricsOnAppEnterBackground = 6, + kRecordSessionEndHistograms = 7, + kRecordLayoutShiftScoreMetrics = 8, + kRecordNormalizedResponsivenessMetrics = 9, + kMaxValue = kRecordNormalizedResponsivenessMetrics, +}; + } // namespace internal // Prerender2 (content/browser/preloading/prerender/README.md):
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc index d9bdd43..c284f32 100644 --- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc +++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -269,6 +269,11 @@ WebFeature::kGetDisplayMediaWithoutUserActivation, WebFeature::kDataUrlInSvgUse, WebFeature::kExecutedNonTrivialJavaScriptURL, + WebFeature::kV8DeprecatedStorageQuota_QueryUsageAndQuota_Method, + WebFeature::kV8DeprecatedStorageQuota_RequestQuota_Method, + WebFeature::kRequestFileSystem, + WebFeature::kRequestFileSystemWorker, + WebFeature::kRequestFileSystemSyncWorker, })); return *opt_in_features; }
diff --git a/components/paint_preview/browser/paint_preview_base_service_unittest.cc b/components/paint_preview/browser/paint_preview_base_service_unittest.cc index 3194a77f..011498f 100644 --- a/components/paint_preview/browser/paint_preview_base_service_unittest.cc +++ b/components/paint_preview/browser/paint_preview_base_service_unittest.cc
@@ -240,7 +240,7 @@ EXPECT_TRUE(result->proto.has_root_frame()); EXPECT_EQ(result->proto.subframes_size(), 0); EXPECT_TRUE(result->proto.root_frame().is_main_frame()); - auto token = base::UnguessableToken::Deserialize2( + auto token = base::UnguessableToken::Deserialize( result->proto.root_frame().embedding_token_high(), result->proto.root_frame().embedding_token_low()) .value();
diff --git a/components/paint_preview/browser/paint_preview_client_unittest.cc b/components/paint_preview/browser/paint_preview_client_unittest.cc index 6ccbb07..8f09a870 100644 --- a/components/paint_preview/browser/paint_preview_client_unittest.cc +++ b/components/paint_preview/browser/paint_preview_client_unittest.cc
@@ -191,7 +191,7 @@ EXPECT_EQ(returned_guid, expected_guid); EXPECT_EQ(status, mojom::PaintPreviewStatus::kOk); - auto token = base::UnguessableToken::Deserialize2( + auto token = base::UnguessableToken::Deserialize( result->proto.root_frame().embedding_token_high(), result->proto.root_frame().embedding_token_low()) .value();
diff --git a/components/paint_preview/common/recording_map.cc b/components/paint_preview/common/recording_map.cc index 711bc72..34c6e5dd 100644 --- a/components/paint_preview/common/recording_map.cc +++ b/components/paint_preview/common/recording_map.cc
@@ -62,7 +62,7 @@ return {}; absl::optional<base::UnguessableToken> root_frame_embedding_token = - base::UnguessableToken::Deserialize2( + base::UnguessableToken::Deserialize( proto.root_frame().embedding_token_high(), proto.root_frame().embedding_token_low()); // TODO(https://crbug.com/1406995): Investigate whether a deserialization @@ -83,8 +83,8 @@ continue; absl::optional<base::UnguessableToken> subframe_embedding_token = - base::UnguessableToken::Deserialize2(subframe.embedding_token_high(), - subframe.embedding_token_low()); + base::UnguessableToken::Deserialize(subframe.embedding_token_high(), + subframe.embedding_token_low()); // TODO(https://crbug.com/1406995): Investigate whether a deserialization // failure can actually occur here and if it can, add a comment discussing // how this can happen.
diff --git a/components/paint_preview/player/player_compositor_delegate.cc b/components/paint_preview/player/player_compositor_delegate.cc index 46f1e231..b5a6acbf 100644 --- a/components/paint_preview/player/player_compositor_delegate.cc +++ b/components/paint_preview/player/player_compositor_delegate.cc
@@ -42,8 +42,8 @@ std::pair<base::UnguessableToken, std::unique_ptr<HitTester>> BuildHitTester( const PaintPreviewFrameProto& proto) { absl::optional<base::UnguessableToken> embedding_token = - base::UnguessableToken::Deserialize2(proto.embedding_token_high(), - proto.embedding_token_low()); + base::UnguessableToken::Deserialize(proto.embedding_token_high(), + proto.embedding_token_low()); // TODO(https://crbug.com/1406995): Investigate whether a deserialization // failure can actually occur here and if it can, add a comment discussing how // this can happen.
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index e5f278d..cf43fde 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -11,6 +11,7 @@ #include "components/autofill/content/browser/content_autofill_driver.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/unique_ids.h" #include "components/password_manager/content/browser/bad_message.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" #include "components/password_manager/content/browser/form_meta_data.h" @@ -209,6 +210,12 @@ GetAutofillAgent()->ClearPreviewedForm(); } +void ContentPasswordManagerDriver::SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) { + GetAutofillAgent()->SetSuggestionAvailability(generation_element_id, state); +} + PasswordGenerationFrameHelper* ContentPasswordManagerDriver::GetPasswordGenerationHelper() { return &password_generation_helper_;
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h index 992a2d08..15016ee 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.h +++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -81,6 +81,9 @@ const std::u16string& password) override; void PreviewGenerationSuggestion(const std::u16string& password) override; void ClearPreviewedForm() override; + void SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) override; PasswordGenerationFrameHelper* GetPasswordGenerationHelper() override; PasswordManager* GetPasswordManager() override; PasswordAutofillManager* GetPasswordAutofillManager() override;
diff --git a/components/password_manager/content/browser/content_password_manager_driver_factory.h b/components/password_manager/content/browser/content_password_manager_driver_factory.h index ee0d70a..e71dcb8 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_factory.h +++ b/components/password_manager/content/browser/content_password_manager_driver_factory.h
@@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" -#include "base/supports_user_data.h" #include "components/autofill/content/common/mojom/autofill_driver.mojom.h" #include "components/password_manager/core/browser/password_autofill_manager.h" #include "components/password_manager/core/browser/password_generation_frame_helper.h"
diff --git a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc index 35c519d56..ba4d7ed 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc +++ b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
@@ -175,8 +175,9 @@ } MATCHER(WerePasswordsCleared, "Passwords not cleared") { - if (!arg.password_field.value.empty()) + if (!arg.preferred_login.password.empty()) { return false; + } for (auto& credentials : arg.additional_logins) if (!credentials.password.empty())
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 07da563..6b28c15 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -166,11 +166,11 @@ bool show_all, bool is_password_field, std::vector<autofill::Suggestion>* suggestions) { - AppendSuggestionIfMatching(fill_data.username_field.value, current_username, - custom_icon, fill_data.preferred_realm, show_all, - is_password_field, fill_data.uses_account_store, - fill_data.password_field.value.size(), - suggestions); + AppendSuggestionIfMatching( + fill_data.preferred_login.username, current_username, custom_icon, + fill_data.preferred_login.realm, show_all, is_password_field, + fill_data.preferred_login.uses_account_store, + fill_data.preferred_login.password.size(), suggestions); int prefered_match = suggestions->size(); @@ -350,8 +350,9 @@ [](const autofill::PasswordAndMetadata& metadata) { return metadata.uses_account_store; }); - if (fill_data.uses_account_store) + if (fill_data.preferred_login.uses_account_store) { ++account_store_passwords_count; + } metrics_util::LogPasswordsCountFromAccountStoreAfterUnlock( account_store_passwords_count); } @@ -599,8 +600,8 @@ // If there are no username or password suggestions, WebAuthn credentials // can still cause a popup to appear. - if (fill_data.username_field.value.empty() && - fill_data.password_field.value.empty()) { + if (fill_data.preferred_login.username.empty() && + fill_data.preferred_login.password.empty()) { return; } @@ -876,12 +877,13 @@ item_id == autofill::POPUP_ITEM_ID_ACCOUNT_STORAGE_PASSWORD_ENTRY; // Look for any suitable matches to current field text. - if (fill_data.username_field.value == current_username && - fill_data.uses_account_store == item_uses_account_store) { + if (fill_data.preferred_login.username == current_username && + fill_data.preferred_login.uses_account_store == item_uses_account_store) { password_and_meta_data->username = current_username; - password_and_meta_data->password = fill_data.password_field.value; - password_and_meta_data->realm = fill_data.preferred_realm; - password_and_meta_data->uses_account_store = fill_data.uses_account_store; + password_and_meta_data->password = fill_data.preferred_login.password; + password_and_meta_data->realm = fill_data.preferred_login.realm; + password_and_meta_data->uses_account_store = + fill_data.preferred_login.uses_account_store; return true; }
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc index 9fbf008..f44f388cc1 100644 --- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc +++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -65,9 +65,7 @@ #endif // The name of the username/password element in the form. -const char16_t kUsernameName[] = u"username"; const char16_t kInvalidUsername[] = u"no-username"; -const char16_t kPasswordName[] = u"password"; const char16_t kAliceUsername[] = u"alice"; const char16_t kAlicePassword[] = u"password"; @@ -297,16 +295,9 @@ : test_username_(kAliceUsername), test_password_(kAlicePassword) {} void SetUp() override { - // Add a preferred login and an additional login to the FillData. - autofill::FormFieldData username_field; - username_field.name = kUsernameName; - username_field.value = test_username_; - fill_data_.username_field = username_field; - - autofill::FormFieldData password_field; - password_field.name = kPasswordName; - password_field.value = test_password_; - fill_data_.password_field = password_field; + // Add a preferred login. + fill_data_.preferred_login.username = test_username_; + fill_data_.preferred_login.password = test_password_; } void InitializePasswordAutofillManager(TestPasswordManagerClient* client, @@ -342,9 +333,9 @@ autofill::PasswordFormFillData CreateTestFormFillData() { autofill::PasswordFormFillData data; - data.username_field.value = test_username_; - data.password_field.value = test_password_; - data.preferred_realm = "http://foo.com/"; + data.preferred_login.username = test_username_; + data.preferred_login.password = test_password_; + data.preferred_login.realm = "http://foo.com/"; return data; } @@ -455,7 +446,7 @@ // Load filling and favicon data. autofill::PasswordFormFillData data = CreateTestFormFillData(); - data.uses_account_store = false; + data.preferred_login.uses_account_store = false; favicon::MockFaviconService favicon_service; EXPECT_CALL(client, GetFaviconService()).WillOnce(Return(&favicon_service)); EXPECT_CALL(favicon_service, GetFaviconImageForPageURL(data.url, _, _)) @@ -522,9 +513,9 @@ autofill::PasswordFormFillData data = CreateTestFormFillData(); autofill::PasswordAndMetadata duplicate; duplicate.password = kAliceAccountStoredPassword; - duplicate.realm = data.preferred_realm; + duplicate.realm = data.preferred_login.realm; duplicate.uses_account_store = true; - duplicate.username = data.username_field.value; + duplicate.username = data.preferred_login.username; data.additional_logins.push_back(duplicate); favicon::MockFaviconService favicon_service; EXPECT_CALL(client, GetFaviconService()).WillOnce(Return(&favicon_service)); @@ -970,7 +961,7 @@ // Once the data is loaded, an update fills the new passwords: autofill::PasswordFormFillData new_data = CreateTestFormFillData(); - new_data.uses_account_store = true; + new_data.preferred_login.uses_account_store = true; autofill::PasswordAndMetadata additional; additional.realm = "https://foobarrealm.org"; additional.username = u"bar.foo@example.com"; @@ -1101,8 +1092,8 @@ InitializePasswordAutofillManager(&client, &autofill_client); autofill::PasswordFormFillData data; - data.username_field.value = test_username_; - data.preferred_realm = "android://hash@com.example1.android/"; + data.preferred_login.username = test_username_; + data.preferred_login.realm = "android://hash@com.example1.android/"; autofill::PasswordAndMetadata additional; additional.realm = "android://hash@com.example2.android/"; @@ -1177,9 +1168,9 @@ gfx::RectF element_bounds; autofill::PasswordFormFillData data; std::u16string username = u"foo.bar@example.com"; - data.username_field.value = username; - data.password_field.value = u"foobar"; - data.preferred_realm = "http://foo.com/"; + data.preferred_login.username = username; + data.preferred_login.password = u"foobar"; + data.preferred_login.realm = "http://foo.com/"; autofill::PasswordAndMetadata additional; additional.realm = "https://foobarrealm.org"; @@ -1221,9 +1212,9 @@ gfx::RectF element_bounds; autofill::PasswordFormFillData data; std::u16string username = u"foo.bar@example.com"; - data.username_field.value = username; - data.password_field.value = u"foobar"; - data.preferred_realm = "http://foo.com/"; + data.preferred_login.username = username; + data.preferred_login.password = u"foobar"; + data.preferred_login.realm = "http://foo.com/"; autofill::PasswordAndMetadata additional; additional.realm = "https://foobarrealm.org"; @@ -1254,9 +1245,9 @@ gfx::RectF element_bounds; autofill::PasswordFormFillData data; std::u16string username = u"foo.bar@example.com"; - data.username_field.value = username; - data.password_field.value = u"foobar"; - data.preferred_realm = "http://foo.com/"; + data.preferred_login.username = username; + data.preferred_login.password = u"foobar"; + data.preferred_login.realm = "http://foo.com/"; autofill::PasswordAndMetadata additional; additional.realm = "https://foobarrealm.org"; @@ -1299,9 +1290,9 @@ gfx::RectF element_bounds; autofill::PasswordFormFillData data; std::u16string username = u"foo.bar@example.com"; - data.username_field.value = username; - data.password_field.value = u"foobar"; - data.preferred_realm = "http://foo.com/"; + data.preferred_login.username = username; + data.preferred_login.password = u"foobar"; + data.preferred_login.realm = "http://foo.com/"; autofill::PasswordAndMetadata additional; additional.realm = "https://foobarrealm.org"; @@ -1334,7 +1325,7 @@ // Initialize PasswordAutofillManager with credentials without username. TestPasswordManagerClient client; NiceMock<MockAutofillClient> autofill_client; - fill_data().username_field.value.clear(); + fill_data().preferred_login.username.clear(); InitializePasswordAutofillManager(&client, &autofill_client); std::u16string no_username_string = @@ -1637,9 +1628,9 @@ gfx::RectF element_bounds; autofill::PasswordFormFillData data; - data.username_field.value = test_username_; - data.password_field.value = u"foobar"; - data.uses_account_store = true; + data.preferred_login.username = test_username_; + data.preferred_login.password = u"foobar"; + data.preferred_login.uses_account_store = true; password_autofill_manager_->OnAddPasswordFillData(data);
diff --git a/components/password_manager/core/browser/password_form_filling.cc b/components/password_manager/core/browser/password_form_filling.cc index 3373a3e..ed27090 100644 --- a/components/password_manager/core/browser/password_form_filling.cc +++ b/components/password_manager/core/browser/password_form_filling.cc
@@ -44,7 +44,7 @@ base::FEATURE_ENABLED_BY_DEFAULT); bool PreferredRealmIsFromAndroid(const PasswordFormFillData& fill_data) { - return FacetURI::FromPotentiallyInvalidSpec(fill_data.preferred_realm) + return FacetURI::FromPotentiallyInvalidSpec(fill_data.preferred_login.realm) .IsValidAndroidFacetURI(); } @@ -285,41 +285,33 @@ result.form_renderer_id = form_on_page.form_data.unique_renderer_id; result.url = form_on_page.url; - result.uses_account_store = preferred_match.IsUsingAccountStore(); result.wait_for_username = wait_for_username; - // Note that many of the |FormFieldData| members are not initialized for - // |username_field| and |password_field| because they are currently not used - // by the password autocomplete code. - // Although the |host_frame| is currently not used by Password Manager, it - // must be set because serializing an empty LocalFrameToken is illegal. - result.username_field.host_frame = form_on_page.form_data.host_frame; - result.password_field.host_frame = form_on_page.form_data.host_frame; - result.username_field.value = preferred_match.username_value; - result.password_field.value = preferred_match.password_value; + result.preferred_login.username = preferred_match.username_value; + result.preferred_login.password = preferred_match.password_value; + if (!form_on_page.only_for_fallback && (form_on_page.HasPasswordElement() || form_on_page.IsSingleUsername())) { // Fill fields identifying information only for non-fallback case when // password element is found. In other cases a fill popup is shown on // clicking on each password field so no need in any field identifiers. - result.username_field.name = form_on_page.username_element; - result.username_field.unique_renderer_id = + result.username_element_renderer_id = form_on_page.username_element_renderer_id; result.username_may_use_prefilled_placeholder = form_on_page.username_may_use_prefilled_placeholder; - result.password_field.name = form_on_page.password_element; - result.password_field.unique_renderer_id = + result.password_element_renderer_id = form_on_page.password_element_renderer_id; - result.password_field.form_control_type = "password"; } - if (IsPublicSuffixMatchOrAffiliationBasedMatch(preferred_match)) { - result.preferred_realm = GetPreferredRealm(preferred_match); - } else if (!IsSameOrigin(main_frame_origin, form_on_page.url)) { - // If the suggestion is for a cross-origin iframe, display the origin of - // the suggestion. - result.preferred_realm = GetPreferredRealm(preferred_match); + result.preferred_login.uses_account_store = + preferred_match.IsUsingAccountStore(); + + if (IsPublicSuffixMatchOrAffiliationBasedMatch(preferred_match) || + !IsSameOrigin(main_frame_origin, form_on_page.url)) { + // If the origins of the |preferred_match|, the main frame and the form's + // frame differ, then show the origin of the match. + result.preferred_login.realm = GetPreferredRealm(preferred_match); } // Copy additional username/value pairs.
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc index 53070cc9..c1b2860 100644 --- a/components/password_manager/core/browser/password_form_filling_unittest.cc +++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -199,10 +199,8 @@ // Check that the message to the renderer (i.e. |fill_data|) is filled // correctly. EXPECT_EQ(observed_form_.url, fill_data.url); - EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); // Check that information about non-preferred best matches is filled. ASSERT_EQ(1u, fill_data.additional_logins.size()); @@ -376,11 +374,13 @@ // correctly. EXPECT_EQ(observed_form_.url, fill_data.url); EXPECT_TRUE(fill_data.wait_for_username); - EXPECT_EQ(psl_saved_match_.signon_realm, fill_data.preferred_realm); - EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_EQ(observed_form_.username_element_renderer_id, + fill_data.username_element_renderer_id); + EXPECT_EQ(observed_form_.password_element_renderer_id, + fill_data.password_element_renderer_id); + EXPECT_EQ(psl_saved_match_.signon_realm, fill_data.preferred_login.realm); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); } TEST_F(PasswordFormFillingTest, NoAutofillOnHttp) { @@ -450,11 +450,9 @@ // correctly. EXPECT_EQ(observed_form_.url, fill_data.url); EXPECT_TRUE(fill_data.wait_for_username); - EXPECT_EQ(affiliated_match.signon_realm, fill_data.preferred_realm); - EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_EQ(affiliated_match.signon_realm, fill_data.preferred_login.realm); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); histogram_tester.ExpectUniqueSample( "PasswordManager.MatchedFormType", @@ -557,7 +555,7 @@ EXPECT_TRUE(result.wait_for_username); // The preferred realm should be empty since it's the same as the realm of // the form. - EXPECT_EQ(std::string(), result.preferred_realm); + EXPECT_EQ(std::string(), result.preferred_login.realm); PasswordFormFillData result2 = CreatePasswordFormFillData( form_on_page, matches, preferred_match, page_origin, false); @@ -635,7 +633,7 @@ EXPECT_TRUE(result.wait_for_username); // The preferred realm should match the signon realm from the // preferred match so the user can see where the result came from. - EXPECT_EQ(preferred_match.signon_realm, result.preferred_realm); + EXPECT_EQ(preferred_match.signon_realm, result.preferred_login.realm); // The realm of the exact match should be empty. PasswordFormFillData::LoginCollection::const_iterator iter = @@ -708,7 +706,7 @@ EXPECT_FALSE(result.wait_for_username); // The preferred realm should match the signon realm from the // preferred match so the user can see where the result came from. - EXPECT_EQ(preferred_match.signon_realm, result.preferred_realm); + EXPECT_EQ(preferred_match.signon_realm, result.preferred_login.realm); // The realm of the exact match should be empty. PasswordFormFillData::LoginCollection::const_iterator iter = @@ -755,12 +753,10 @@ form_on_page, {}, preferred_match, page_origin, true); EXPECT_EQ(form_data.unique_renderer_id, result.form_renderer_id); - EXPECT_EQ(form_data.host_frame, result.username_field.host_frame); - EXPECT_EQ(form_data.host_frame, result.password_field.host_frame); EXPECT_EQ(form_on_page.username_element_renderer_id, - result.username_field.unique_renderer_id); + result.username_element_renderer_id); EXPECT_EQ(form_on_page.password_element_renderer_id, - result.password_field.unique_renderer_id); + result.password_element_renderer_id); EXPECT_TRUE(result.username_may_use_prefilled_placeholder); } @@ -791,8 +787,8 @@ form_on_page, {} /* matches */, preferred_match, page_origin, true); // Check that nor username nor password fields are set. - EXPECT_TRUE(result.username_field.unique_renderer_id.is_null()); - EXPECT_TRUE(result.password_field.unique_renderer_id.is_null()); + EXPECT_TRUE(result.username_element_renderer_id.is_null()); + EXPECT_TRUE(result.password_element_renderer_id.is_null()); } // Tests that the constructing a PasswordFormFillData behaves correctly when @@ -831,7 +827,7 @@ EXPECT_FALSE(result.wait_for_username); // The preferred realm should match the app name from the affiliated match so // the user can see and understand where the result came from. - EXPECT_EQ(affiliated_match.app_display_name, result.preferred_realm); + EXPECT_EQ(affiliated_match.app_display_name, result.preferred_login.realm); } // Tests that the constructing a PasswordFormFillData behaves correctly inside @@ -863,7 +859,7 @@ EXPECT_FALSE(result.wait_for_username); // The preferred realm should match the form signon_realm. - EXPECT_EQ(result.preferred_realm, form_on_page.signon_realm); + EXPECT_EQ(result.preferred_login.realm, form_on_page.signon_realm); // The realm of the additional login match should match the form // signon_realm. EXPECT_EQ(result.additional_logins[0].realm, additional_match.signon_realm);
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 7c411c4..cbecdf0 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -581,10 +581,8 @@ EXPECT_FALSE(fill_data.wait_for_username); #endif - EXPECT_EQ(observed_form_.fields[1].name, fill_data.username_field.name); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(observed_form_.fields[2].name, fill_data.password_field.name); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); } TEST_P(PasswordFormManagerTest, AutofillNotMoreThan5Times) { @@ -625,8 +623,8 @@ SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); task_environment_.FastForwardUntilNoTasksRemain(); - EXPECT_TRUE(fill_data.password_field.unique_renderer_id.is_null()); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_TRUE(fill_data.password_element_renderer_id.is_null()); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); #if BUILDFLAG(IS_IOS) EXPECT_EQ(observed_form_.unique_renderer_id, generation_data.form_renderer_id); @@ -681,8 +679,8 @@ task_environment_.FastForwardUntilNoTasksRemain(); EXPECT_EQ(observed_form_.url, fill_data.url); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); } TEST_P(PasswordFormManagerTest, SetSubmitted) { @@ -1761,16 +1759,12 @@ form_manager_->FillForm(form, {}); task_environment_.FastForwardUntilNoTasksRemain(); - EXPECT_EQ(form.fields[kUsernameFieldIndex].name, - fill_data.username_field.name); EXPECT_EQ(form.fields[kUsernameFieldIndex].unique_renderer_id, - fill_data.username_field.unique_renderer_id); - EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value); - EXPECT_EQ(form.fields[kPasswordFieldIndex].name, - fill_data.password_field.name); + fill_data.username_element_renderer_id); + EXPECT_EQ(saved_match_.username_value, fill_data.preferred_login.username); EXPECT_EQ(form.fields[kPasswordFieldIndex].unique_renderer_id, - fill_data.password_field.unique_renderer_id); - EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); + fill_data.password_element_renderer_id); + EXPECT_EQ(saved_match_.password_value, fill_data.preferred_login.password); base::HistogramTester histogram_tester; form_manager_.reset(); @@ -1805,9 +1799,9 @@ task_environment_.FastForwardUntilNoTasksRemain(); EXPECT_EQ(changed_form.fields[kUsernameFieldIndex].unique_renderer_id, - fill_data.username_field.unique_renderer_id); + fill_data.username_element_renderer_id); EXPECT_EQ(changed_form.fields[kPasswordFieldIndex].unique_renderer_id, - fill_data.password_field.unique_renderer_id); + fill_data.password_element_renderer_id); base::HistogramTester histogram_tester; form_manager_.reset(); @@ -1844,9 +1838,9 @@ // Check new fill task trigger form filling task_environment_.FastForwardUntilNoTasksRemain(); EXPECT_EQ(changed_form.fields[kUsernameFieldIndex].unique_renderer_id, - fill_data.username_field.unique_renderer_id); + fill_data.username_element_renderer_id); EXPECT_EQ(changed_form.fields[kPasswordFieldIndex].unique_renderer_id, - fill_data.password_field.unique_renderer_id); + fill_data.password_element_renderer_id); } TEST_P(PasswordFormManagerTest, Update) {
diff --git a/components/password_manager/core/browser/password_manager_driver.h b/components/password_manager/core/browser/password_manager_driver.h index a458c31..efc40c1 100644 --- a/components/password_manager/core/browser/password_manager_driver.h +++ b/components/password_manager/core/browser/password_manager_driver.h
@@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" #include "base/types/strong_alias.h" +#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #include "components/autofill/core/common/unique_ids.h" #include "ui/accessibility/ax_tree_id.h" @@ -110,6 +111,13 @@ // Tells the driver to clear previewed password and username fields. virtual void ClearPreviewedForm() = 0; + // Updates the autofill availability state of the DOM node with + // |generation_element_id|. It is critical for a11y to keep it updated + // to make proper announcements. + virtual void SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) = 0; + // Returns the PasswordGenerationFrameHelper associated with this instance. virtual PasswordGenerationFrameHelper* GetPasswordGenerationHelper() = 0;
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index efdc0dc3..e43e8f48 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -1550,7 +1550,7 @@ observed.push_back(form.form_data); manager()->OnPasswordFormsParsed(&driver_, observed); task_environment_.RunUntilIdle(); - EXPECT_EQ(form.password_value, form_data.password_field.value); + EXPECT_EQ(form.password_value, form_data.preferred_login.password); } TEST_P(PasswordManagerTest, @@ -2288,8 +2288,8 @@ manager()->UpdateFormManagers(); task_environment_.RunUntilIdle(); - EXPECT_EQ(form.username_value, form_data.username_field.value); - EXPECT_EQ(form.password_value, form_data.password_field.value); + EXPECT_EQ(form.username_value, form_data.preferred_login.username); + EXPECT_EQ(form.password_value, form_data.preferred_login.password); } TEST_P(PasswordManagerTest, AutofillingOfAffiliatedCredentials) { @@ -2308,15 +2308,15 @@ manager()->OnPasswordFormsRendered(&driver_, observed_forms); task_environment_.RunUntilIdle(); - EXPECT_EQ(android_form.username_value, form_data.username_field.value); - EXPECT_EQ(android_form.password_value, form_data.password_field.value); + EXPECT_EQ(android_form.username_value, form_data.preferred_login.username); + EXPECT_EQ(android_form.password_value, form_data.preferred_login.password); // On Android Touch To Fill will prevent autofilling credentials on page load. #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) EXPECT_TRUE(form_data.wait_for_username); #else EXPECT_FALSE(form_data.wait_for_username); #endif - EXPECT_EQ(android_form.signon_realm, form_data.preferred_realm); + EXPECT_EQ(android_form.signon_realm, form_data.preferred_login.realm); EXPECT_CALL(client_, IsSavingAndFillingEnabled(observed_form.url)) .WillRepeatedly(Return(true)); @@ -3343,11 +3343,11 @@ task_environment_.RunUntilIdle(); // Check that manual filling fallback available. - EXPECT_EQ(saved_match.username_value, form_data.username_field.value); - EXPECT_EQ(saved_match.password_value, form_data.password_field.value); + EXPECT_EQ(saved_match.username_value, form_data.preferred_login.username); + EXPECT_EQ(saved_match.password_value, form_data.preferred_login.password); // Check that no automatic filling available. - EXPECT_TRUE(form_data.username_field.unique_renderer_id.is_null()); - EXPECT_TRUE(form_data.password_field.unique_renderer_id.is_null()); + EXPECT_TRUE(form_data.username_element_renderer_id.is_null()); + EXPECT_TRUE(form_data.password_element_renderer_id.is_null()); // Check that saving fallback is available. std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; @@ -3428,10 +3428,10 @@ manager()->ProcessAutofillPredictions(&driver_, {&form_structure}); task_environment_.RunUntilIdle(); EXPECT_EQ(form_id, fill_data.form_renderer_id); - EXPECT_EQ(saved_match.username_value, fill_data.username_field.value); - EXPECT_EQ(field_id, fill_data.username_field.unique_renderer_id); - EXPECT_EQ(saved_match.password_value, fill_data.password_field.value); - EXPECT_TRUE(fill_data.password_field.unique_renderer_id.is_null()); + EXPECT_EQ(saved_match.username_value, fill_data.preferred_login.username); + EXPECT_EQ(field_id, fill_data.username_element_renderer_id); + EXPECT_EQ(saved_match.password_value, fill_data.preferred_login.password); + EXPECT_TRUE(fill_data.password_element_renderer_id.is_null()); } #endif // !BUILDFLAG(IS_IOS)
diff --git a/components/password_manager/core/browser/store_metrics_reporter.cc b/components/password_manager/core/browser/store_metrics_reporter.cc index 15f747b..023005a 100644 --- a/components/password_manager/core/browser/store_metrics_reporter.cc +++ b/components/password_manager/core/browser/store_metrics_reporter.cc
@@ -4,12 +4,14 @@ #include "components/password_manager/core/browser/store_metrics_reporter.h" #include <memory> +#include <utility> #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" #include "components/password_manager/core/browser/affiliation/affiliation_utils.h" #include "components/password_manager/core/browser/password_feature_manager.h" #include "components/password_manager/core/browser/password_manager_features_util.h" @@ -351,6 +353,34 @@ count_phished); } +void ReportStoreMetrics(bool is_account_store, + bool custom_passphrase_sync_enabled, + const std::string& sync_username, + BulkCheckDone bulk_check_done, + std::vector<std::unique_ptr<PasswordForm>> results) { + ReportNumberOfAccountsMetrics(is_account_store, + custom_passphrase_sync_enabled, results); + ReportLoginsWithSchemesMetrics(is_account_store, results); + ReportTimesPasswordUsedMetrics(is_account_store, + custom_passphrase_sync_enabled, results); + ReportPasswordNotesMetrics(is_account_store, results); + + // The remaining metrics are not recorded for the account store: + // - SyncingAccountState2 just doesn't make sense, since syncing users only + // use + // the profile store. + // - DuplicateCredentials *could* be recorded for the account store, but are + // not very critical. + // - Compromised credentials are only stored in the profile store. + if (is_account_store) { + return; + } + + ReportSyncingAccountStateMetrics(sync_username, results); + ReportDuplicateCredentialsMetrics(results); + ReportPasswordIssuesMetrics(bulk_check_done, results); +} + void ReportMultiStoreMetrics( std::unique_ptr<std::map<std::pair<std::string, std::u16string>, std::u16string>> profile_store_results, @@ -429,6 +459,82 @@ } } +void ReportAllMetrics(bool custom_passphrase_sync_enabled, + const std::string& sync_username, + BulkCheckDone bulk_check_done, + bool is_opted_in_account_storage, + absl::optional<std::vector<std::unique_ptr<PasswordForm>>> + profile_store_results, + absl::optional<std::vector<std::unique_ptr<PasswordForm>>> + account_store_results) { + // Maps from (signon_realm, username) to password. + std::unique_ptr< + std::map<std::pair<std::string, std::u16string>, std::u16string>> + profile_store_passwords_per_signon_and_username; + std::unique_ptr< + std::map<std::pair<std::string, std::u16string>, std::u16string>> + account_store_passwords_per_signon_and_username; + + if (profile_store_results.has_value()) { + profile_store_passwords_per_signon_and_username = std::make_unique< + std::map<std::pair<std::string, std::u16string>, std::u16string>>(); + for (const std::unique_ptr<PasswordForm>& form : + profile_store_results.value()) { + profile_store_passwords_per_signon_and_username->insert(std::make_pair( + std::make_pair(form->signon_realm, form->username_value), + form->password_value)); + } + } + + if (account_store_results.has_value()) { + account_store_passwords_per_signon_and_username = std::make_unique< + std::map<std::pair<std::string, std::u16string>, std::u16string>>(); + for (const std::unique_ptr<PasswordForm>& form : + account_store_results.value()) { + account_store_passwords_per_signon_and_username->insert(std::make_pair( + std::make_pair(form->signon_realm, form->username_value), + form->password_value)); + } + } + + if (profile_store_results.has_value()) { + ReportStoreMetrics(/*is_account_store=*/false, + custom_passphrase_sync_enabled, sync_username, + bulk_check_done, + std::move(profile_store_results).value()); + } + if (account_store_results.has_value()) { + ReportStoreMetrics(/*is_account_store=*/true, + custom_passphrase_sync_enabled, sync_username, + bulk_check_done, + std::move(account_store_results).value()); + } + + // If both stores exist, kick off the MultiStoreMetricsReporter. + if (profile_store_passwords_per_signon_and_username && + account_store_passwords_per_signon_and_username) { + ReportMultiStoreMetrics( + std::move(profile_store_passwords_per_signon_and_username), + std::move(account_store_passwords_per_signon_and_username), + is_opted_in_account_storage); + } +} + +void OnMetricsReportingCompleted( + base::WeakPtr<StoreMetricsReporter> reporter_weak_ptr, + base::OnceClosure done_callback) { + // Metrics reporting is performed asynchronously on a background thread. By + // the time metrics reporting is completed, it could be the case that the + // StoreMetricsReporter has been destructed already (e.g. if the user closes + // the browser profile for which metrics are being reported). If the reporter + // doesn't exist anymore, it's pointless (and wrong) to run the + // `done_callback` since the main purpose of the `done_callback` is to + // destroy the reporter (as in password_store_utils.cc). + if (reporter_weak_ptr) { + std::move(done_callback).Run(); + } +} + void ReportBiometricAuthenticationBeforeFillingMetrics(PrefService* prefs) { #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) base::UmaHistogramBoolean( @@ -485,7 +591,8 @@ bulk_check_done_ = BulkCheckDone(prefs->HasPrefPath(prefs::kLastTimePasswordCheckCompleted)); - is_opted_in_ = features_util::IsOptedInForAccountStorage(prefs, sync_service); + is_opted_in_account_storage_ = + features_util::IsOptedInForAccountStorage(prefs, sync_service); base::UmaHistogramBoolean( base::StrCat({kPasswordManager, ".Enabled4"}), @@ -525,66 +632,31 @@ void StoreMetricsReporter::OnGetPasswordStoreResultsFrom( PasswordStoreInterface* store, std::vector<std::unique_ptr<PasswordForm>> results) { - bool is_account_store = store == account_store_; - - if (is_account_store) { - account_store_results_ = std::make_unique< - std::map<std::pair<std::string, std::u16string>, std::u16string>>(); - for (const std::unique_ptr<PasswordForm>& form : results) { - account_store_results_->insert(std::make_pair( - std::make_pair(form->signon_realm, form->username_value), - form->password_value)); - } + if (store == account_store_) { + account_store_results_ = std::move(results); } else { - profile_store_results_ = std::make_unique< - std::map<std::pair<std::string, std::u16string>, std::u16string>>(); - for (const std::unique_ptr<PasswordForm>& form : results) { - profile_store_results_->insert(std::make_pair( - std::make_pair(form->signon_realm, form->username_value), - form->password_value)); - } + profile_store_results_ = std::move(results); } - ReportStoreMetrics(is_account_store, std::move(results)); - - // If we are still expecting more results, there is nothing else to do. + // Wait until all expected results are available before starting metrics + // reporting. if ((profile_store_ && !profile_store_results_) || (account_store_ && !account_store_results_)) { return; } - // If both stores exist, kick off the MultiStoreMetricsReporter. - if (profile_store_results_ && account_store_results_) { - ReportMultiStoreMetrics(std::move(profile_store_results_), - std::move(account_store_results_), is_opted_in_); - } DCHECK(done_callback_); - std::move(done_callback_).Run(); -} -void StoreMetricsReporter::ReportStoreMetrics( - bool is_account_store, - std::vector<std::unique_ptr<PasswordForm>> results) { - ReportNumberOfAccountsMetrics(is_account_store, - custom_passphrase_sync_enabled_, results); - ReportLoginsWithSchemesMetrics(is_account_store, results); - ReportTimesPasswordUsedMetrics(is_account_store, - custom_passphrase_sync_enabled_, results); - ReportPasswordNotesMetrics(is_account_store, results); - - // The remaining metrics are not recorded for the account store: - // - SyncingAccountState2 just doesn't make sense, since syncing users only - // use - // the profile store. - // - DuplicateCredentials *could* be recorded for the account store, but are - // not very critical. - // - Compromised credentials are only stored in the profile store. - if (is_account_store) - return; - - ReportSyncingAccountStateMetrics(sync_username_, results); - ReportDuplicateCredentialsMetrics(results); - ReportPasswordIssuesMetrics(bulk_check_done_, results); + base::ThreadPool::PostTaskAndReply( + FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, + base::BindOnce(&ReportAllMetrics, custom_passphrase_sync_enabled_, + sync_username_, bulk_check_done_, + is_opted_in_account_storage_, + std::exchange(profile_store_results_, absl::nullopt), + std::exchange(account_store_results_, absl::nullopt)), + base::BindOnce(&OnMetricsReportingCompleted, + weak_ptr_factory_.GetWeakPtr(), + std::move(done_callback_))); } StoreMetricsReporter::~StoreMetricsReporter() = default;
diff --git a/components/password_manager/core/browser/store_metrics_reporter.h b/components/password_manager/core/browser/store_metrics_reporter.h index e7c8f5c..9a21d18 100644 --- a/components/password_manager/core/browser/store_metrics_reporter.h +++ b/components/password_manager/core/browser/store_metrics_reporter.h
@@ -10,7 +10,6 @@ #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/supports_user_data.h" #include "components/password_manager/core/browser/insecure_credentials_table.h" #include "components/password_manager/core/browser/password_store_consumer.h" @@ -60,9 +59,6 @@ PasswordStoreInterface* store, std::vector<std::unique_ptr<PasswordForm>> results) override; - void ReportStoreMetrics(bool is_account_store, - std::vector<std::unique_ptr<PasswordForm>> results); - // Since metrics reporting is run in a delayed task, we grab refptrs to the // stores, to ensure they're still alive when the delayed task runs. scoped_refptr<PasswordStoreInterface> profile_store_; @@ -76,14 +72,14 @@ BulkCheckDone bulk_check_done_; - bool is_opted_in_; + bool is_opted_in_account_storage_; - // Maps from (signon_realm, username) to password. - std::unique_ptr< - std::map<std::pair<std::string, std::u16string>, std::u16string>> + // Temporarily holds the credentials stored in the profile and account stores + // till the actual metric computation starts. They don't have a value until + // the credentials are loaded from the storage. + absl::optional<std::vector<std::unique_ptr<PasswordForm>>> profile_store_results_; - std::unique_ptr< - std::map<std::pair<std::string, std::u16string>, std::u16string>> + absl::optional<std::vector<std::unique_ptr<PasswordForm>>> account_store_results_; base::OnceClosure done_callback_;
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.cc b/components/password_manager/core/browser/stub_password_manager_driver.cc index fe0a698..10d3237 100644 --- a/components/password_manager/core/browser/stub_password_manager_driver.cc +++ b/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -39,6 +39,10 @@ void StubPasswordManagerDriver::ClearPreviewedForm() { } +void StubPasswordManagerDriver::SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) {} + PasswordGenerationFrameHelper* StubPasswordManagerDriver::GetPasswordGenerationHelper() { return nullptr;
diff --git a/components/password_manager/core/browser/stub_password_manager_driver.h b/components/password_manager/core/browser/stub_password_manager_driver.h index 318fd8b..3f922bc 100644 --- a/components/password_manager/core/browser/stub_password_manager_driver.h +++ b/components/password_manager/core/browser/stub_password_manager_driver.h
@@ -36,6 +36,9 @@ const std::u16string& password) override; void PreviewGenerationSuggestion(const std::u16string& password) override; void ClearPreviewedForm() override; + void SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) override; PasswordGenerationFrameHelper* GetPasswordGenerationHelper() override; PasswordManagerInterface* GetPasswordManager() override; PasswordAutofillManager* GetPasswordAutofillManager() override;
diff --git a/components/password_manager/ios/account_select_fill_data.cc b/components/password_manager/ios/account_select_fill_data.cc index 2079376d..65a07e3 100644 --- a/components/password_manager/ios/account_select_fill_data.cc +++ b/components/password_manager/ios/account_select_fill_data.cc
@@ -36,8 +36,8 @@ FormInfo& form_info = iter_ok.first->second; form_info.origin = form_data.url; form_info.form_id = form_data.form_renderer_id; - form_info.username_element_id = form_data.username_field.unique_renderer_id; - form_info.password_element_id = form_data.password_field.unique_renderer_id; + form_info.username_element_id = form_data.username_element_renderer_id; + form_info.password_element_id = form_data.password_element_renderer_id; // Suggested credentials don't depend on a clicked form. It's better to use // the latest known credentials, since credentials can be updated between @@ -45,10 +45,10 @@ credentials_.clear(); credentials_.push_back( - {form_data.username_field.value, form_data.password_field.value, - is_cross_origin_iframe && form_data.preferred_realm.empty() + {form_data.preferred_login.username, form_data.preferred_login.password, + is_cross_origin_iframe && form_data.preferred_login.realm.empty() ? form_data.url.spec() - : form_data.preferred_realm}); + : form_data.preferred_login.realm}); for (const auto& username_password_and_realm : form_data.additional_logins) { const std::u16string& username = username_password_and_realm.username;
diff --git a/components/password_manager/ios/account_select_fill_data_unittest.cc b/components/password_manager/ios/account_select_fill_data_unittest.cc index 158d0d4..2f3f3e3 100644 --- a/components/password_manager/ios/account_select_fill_data_unittest.cc +++ b/components/password_manager/ios/account_select_fill_data_unittest.cc
@@ -67,18 +67,16 @@ // Suggestions are available for the correct form and field ids. EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( form_data_[0].form_renderer_id, - form_data_[0].username_field.unique_renderer_id, false)); + form_data_[0].username_element_renderer_id, false)); // Suggestion should be available to any password field. EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( form_data_[0].form_renderer_id, FieldRendererId(404), true)); // Suggestions are not available for different form renderer_id. EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( - FormRendererId(404), form_data_[0].username_field.unique_renderer_id, - false)); + FormRendererId(404), form_data_[0].username_element_renderer_id, false)); EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( - FormRendererId(404), form_data_[0].password_field.unique_renderer_id, - true)); + FormRendererId(404), form_data_[0].password_element_renderer_id, true)); // Suggestions are not available for different field id. EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( @@ -93,15 +91,14 @@ // Suggestions are available for the correct form and field names. EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( form_data_[0].form_renderer_id, - form_data_[0].username_field.unique_renderer_id, false)); + form_data_[0].username_element_renderer_id, false)); // Suggestions are available for the correct form and field names. EXPECT_TRUE(account_select_fill_data.IsSuggestionsAvailable( form_data_[1].form_renderer_id, - form_data_[1].username_field.unique_renderer_id, false)); + form_data_[1].username_element_renderer_id, false)); // Suggestions are not available for different form id. EXPECT_FALSE(account_select_fill_data.IsSuggestionsAvailable( - FormRendererId(404), form_data_[0].username_field.unique_renderer_id, - false)); + FormRendererId(404), form_data_[0].username_element_renderer_id, false)); } TEST_F(AccountSelectFillDataTest, RetrieveSuggestionsOneForm) { @@ -110,8 +107,8 @@ for (bool is_password_field : {false, true}) { const FieldRendererId field_id = - is_password_field ? form_data_[0].password_field.unique_renderer_id - : form_data_[0].username_field.unique_renderer_id; + is_password_field ? form_data_[0].password_element_renderer_id + : form_data_[0].username_element_renderer_id; std::vector<UsernameAndRealm> suggestions = account_select_fill_data.RetrieveSuggestions( form_data_[0].form_renderer_id, field_id, is_password_field); @@ -136,13 +133,13 @@ std::vector<UsernameAndRealm> suggestions = account_select_fill_data.RetrieveSuggestions( form_data_[0].form_renderer_id, - form_data_[0].username_field.unique_renderer_id, false); + form_data_[0].username_element_renderer_id, false); EXPECT_EQ(1u, suggestions.size()); EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username); suggestions = account_select_fill_data.RetrieveSuggestions( form_data_[1].form_renderer_id, - form_data_[1].username_field.unique_renderer_id, false); + form_data_[1].username_element_renderer_id, false); EXPECT_EQ(1u, suggestions.size()); EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username); } @@ -153,14 +150,14 @@ std::string kAdditionalRealm = "http://b.example.com/"; // Make logins to be PSL matched by setting non-empy realm. - form_data_[0].preferred_realm = kRealm; + form_data_[0].preferred_login.realm = kRealm; form_data_[0].additional_logins.begin()->realm = kAdditionalRealm; account_select_fill_data.Add(form_data_[0], /*is_cross_origin_iframe=*/false); std::vector<UsernameAndRealm> suggestions = account_select_fill_data.RetrieveSuggestions( form_data_[0].form_renderer_id, - form_data_[0].username_field.unique_renderer_id, false); + form_data_[0].username_element_renderer_id, false); EXPECT_EQ(2u, suggestions.size()); EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username); EXPECT_EQ(kRealm, suggestions[0].realm); @@ -182,10 +179,10 @@ // existing field ids. const FieldRendererId password_field_id = is_password_field ? FieldRendererId(1000) - : form_data.password_field.unique_renderer_id; + : form_data.password_element_renderer_id; const FieldRendererId clicked_field = is_password_field ? password_field_id - : form_data.username_field.unique_renderer_id; + : form_data.username_element_renderer_id; // GetFillData() doesn't have form identifier in arguments, it should be // provided in RetrieveSuggestions(). @@ -216,7 +213,7 @@ // provided in RetrieveSuggestions(). account_select_fill_data.RetrieveSuggestions( form_data_[0].form_renderer_id, - form_data_[0].username_field.unique_renderer_id, false); + form_data_[0].username_element_renderer_id, false); // AccountSelectFillData should keep only last credentials. Check that in // request of old credentials nothing is returned. @@ -231,8 +228,8 @@ for (bool is_password_field : {false, true}) { const FieldRendererId field_id = - is_password_field ? form_data_[0].password_field.unique_renderer_id - : form_data_[0].username_field.unique_renderer_id; + is_password_field ? form_data_[0].password_element_renderer_id + : form_data_[0].username_element_renderer_id; std::vector<UsernameAndRealm> suggestions = account_select_fill_data.RetrieveSuggestions( form_data_[0].form_renderer_id, field_id, is_password_field);
diff --git a/components/password_manager/ios/ios_password_manager_driver.h b/components/password_manager/ios/ios_password_manager_driver.h index 729ee99..ff660452 100644 --- a/components/password_manager/ios/ios_password_manager_driver.h +++ b/components/password_manager/ios/ios_password_manager_driver.h
@@ -47,6 +47,9 @@ const std::u16string& password) override; void PreviewGenerationSuggestion(const std::u16string& password) override; void ClearPreviewedForm() override; + void SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) override; password_manager::PasswordGenerationFrameHelper* GetPasswordGenerationHelper() override; password_manager::PasswordManagerInterface* GetPasswordManager() override;
diff --git a/components/password_manager/ios/ios_password_manager_driver.mm b/components/password_manager/ios/ios_password_manager_driver.mm index 6d9fde96..92d2a3d 100644 --- a/components/password_manager/ios/ios_password_manager_driver.mm +++ b/components/password_manager/ios/ios_password_manager_driver.mm
@@ -94,6 +94,12 @@ NOTIMPLEMENTED(); } +void IOSPasswordManagerDriver::SetSuggestionAvailability( + autofill::FieldRendererId generation_element_id, + const autofill::mojom::AutofillState state) { + NOTIMPLEMENTED(); +} + password_manager::PasswordGenerationFrameHelper* IOSPasswordManagerDriver::GetPasswordGenerationHelper() { return password_generation_helper_.get();
diff --git a/components/password_manager/ios/test_helpers.cc b/components/password_manager/ios/test_helpers.cc index 73a80c2..9e60b2ec 100644 --- a/components/password_manager/ios/test_helpers.cc +++ b/components/password_manager/ios/test_helpers.cc
@@ -33,16 +33,10 @@ PasswordFormFillData* form_data) { form_data->url = GURL(url); form_data->form_renderer_id = FormRendererId(unique_renderer_id); - autofill::FormFieldData username; - username.name = base::UTF8ToUTF16(username_field); - username.unique_renderer_id = FieldRendererId(username_unique_id); - username.value = base::UTF8ToUTF16(username_value); - form_data->username_field = username; - autofill::FormFieldData password; - password.name = base::UTF8ToUTF16(password_field); - password.unique_renderer_id = FieldRendererId(password_unique_id); - password.value = base::UTF8ToUTF16(password_value); - form_data->password_field = password; + form_data->username_element_renderer_id = FieldRendererId(username_unique_id); + form_data->preferred_login.username = base::UTF8ToUTF16(username_value); + form_data->password_element_renderer_id = FieldRendererId(password_unique_id); + form_data->preferred_login.password = base::UTF8ToUTF16(password_value); if (additional_username) { autofill::PasswordAndMetadata additional_password_data; additional_password_data.username = base::UTF8ToUTF16(additional_username);
diff --git a/components/performance_manager/decorators/page_live_state_decorator.cc b/components/performance_manager/decorators/page_live_state_decorator.cc index bb183d7..07c8c7b74 100644 --- a/components/performance_manager/decorators/page_live_state_decorator.cc +++ b/components/performance_manager/decorators/page_live_state_decorator.cc
@@ -371,20 +371,19 @@ if (!data) return base::Value(); - base::Value ret(base::Value::Type::DICTIONARY); - ret.SetBoolKey("IsConnectedToUSBDevice", data->IsConnectedToUSBDevice()); - ret.SetBoolKey("IsConnectedToBluetoothDevice", - data->IsConnectedToBluetoothDevice()); - ret.SetBoolKey("IsCapturingVideo", data->IsCapturingVideo()); - ret.SetBoolKey("IsCapturingAudio", data->IsCapturingAudio()); - ret.SetBoolKey("IsBeingMirrored", data->IsBeingMirrored()); - ret.SetBoolKey("IsCapturingWindow", data->IsCapturingWindow()); - ret.SetBoolKey("IsCapturingDisplay", data->IsCapturingDisplay()); - ret.SetBoolKey("IsAutoDiscardable", data->IsAutoDiscardable()); - ret.SetBoolKey("WasDiscarded", data->WasDiscarded()); - ret.SetBoolKey("IsActiveTab", data->IsActiveTab()); + base::Value::Dict ret; + ret.Set("IsConnectedToUSBDevice", data->IsConnectedToUSBDevice()); + ret.Set("IsConnectedToBluetoothDevice", data->IsConnectedToBluetoothDevice()); + ret.Set("IsCapturingVideo", data->IsCapturingVideo()); + ret.Set("IsCapturingAudio", data->IsCapturingAudio()); + ret.Set("IsBeingMirrored", data->IsBeingMirrored()); + ret.Set("IsCapturingWindow", data->IsCapturingWindow()); + ret.Set("IsCapturingDisplay", data->IsCapturingDisplay()); + ret.Set("IsAutoDiscardable", data->IsAutoDiscardable()); + ret.Set("WasDiscarded", data->WasDiscarded()); + ret.Set("IsActiveTab", data->IsActiveTab()); - return ret; + return base::Value(std::move(ret)); } void PageLiveStateDecorator::OnMainFrameUrlChanged(const PageNode* page_node) {
diff --git a/components/performance_manager/decorators/page_load_tracker_decorator.cc b/components/performance_manager/decorators/page_load_tracker_decorator.cc index b789019..9323c673 100644 --- a/components/performance_manager/decorators/page_load_tracker_decorator.cc +++ b/components/performance_manager/decorators/page_load_tracker_decorator.cc
@@ -108,12 +108,12 @@ if (data == nullptr) return base::Value(); - base::Value ret(base::Value::Type::DICTIONARY); - ret.SetStringKey("load_idle_state", ToString(data->load_idle_state())); - ret.SetBoolKey("is_loading", data->is_loading_); - ret.SetBoolKey("did_commit", data->did_commit_); + base::Value::Dict ret; + ret.Set("load_idle_state", ToString(data->load_idle_state())); + ret.Set("is_loading", data->is_loading_); + ret.Set("did_commit", data->did_commit_); - return ret; + return base::Value(std::move(ret)); } void PageLoadTrackerDecorator::OnMainThreadTaskLoadIsLow(
diff --git a/components/performance_manager/decorators/process_metrics_decorator.cc b/components/performance_manager/decorators/process_metrics_decorator.cc index e3e03099c..72e1ed5 100644 --- a/components/performance_manager/decorators/process_metrics_decorator.cc +++ b/components/performance_manager/decorators/process_metrics_decorator.cc
@@ -161,6 +161,12 @@ uint64_t process_rss = process_dump_iter.os_dump().resident_set_kb; process_node->set_resident_set_kb(process_rss); + // Now attribute the RSS and PMF of the process to its frames and workers. + // Only renderers can host frames and workers. + if (process_node->process_type() != content::PROCESS_TYPE_RENDERER) { + continue; + } + size_t frame_and_worker_node_count = process_node->frame_nodes().size() + process_node->worker_nodes().size();
diff --git a/components/performance_manager/freezing/freezing_vote_aggregator.cc b/components/performance_manager/freezing/freezing_vote_aggregator.cc index 56f1045..ac8d3e39 100644 --- a/components/performance_manager/freezing/freezing_vote_aggregator.cc +++ b/components/performance_manager/freezing/freezing_vote_aggregator.cc
@@ -122,9 +122,9 @@ if (votes_for_page == vote_data_map_.end()) return base::Value(); - base::Value ret(base::Value::Type::DICTIONARY); - votes_for_page->second.DescribeVotes(&ret); - return ret; + base::Value::Dict ret; + votes_for_page->second.DescribeVotes(ret); + return base::Value(std::move(ret)); } FreezingVoteAggregator::FreezingVoteData::FreezingVoteData() = default; @@ -165,13 +165,12 @@ } void FreezingVoteAggregator::FreezingVoteData::DescribeVotes( - base::Value* ret) const { + base::Value::Dict& ret) const { size_t i = 0; for (const auto& it : votes_) { - ret->SetStringKey( - base::StringPrintf("Vote %zu (%s)", i++, - FreezingVoteValueToString(it.second.value())), - it.second.reason()); + ret.Set(base::StringPrintf("Vote %zu (%s)", i++, + FreezingVoteValueToString(it.second.value())), + it.second.reason()); } }
diff --git a/components/performance_manager/freezing/freezing_vote_aggregator.h b/components/performance_manager/freezing/freezing_vote_aggregator.h index 0604084..5820752 100644 --- a/components/performance_manager/freezing/freezing_vote_aggregator.h +++ b/components/performance_manager/freezing/freezing_vote_aggregator.h
@@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" +#include "base/values.h" #include "components/performance_manager/public/freezing/freezing.h" #include "components/performance_manager/public/graph/graph_registered.h" #include "components/performance_manager/public/graph/node_data_describer.h" @@ -112,7 +113,7 @@ const FreezingVote& GetChosenVote(); // Helper for FreezingVoteAggregator::DescribePageNodeData. - void DescribeVotes(base::Value* ret) const; + void DescribeVotes(base::Value::Dict& ret) const; private: friend class FreezingVoteAggregatorTestAccess;
diff --git a/components/performance_manager/graph/frame_node_impl_describer.cc b/components/performance_manager/graph/frame_node_impl_describer.cc index 465dcce..44c4376 100644 --- a/components/performance_manager/graph/frame_node_impl_describer.cc +++ b/components/performance_manager/graph/frame_node_impl_describer.cc
@@ -56,42 +56,37 @@ const FrameNode* node) const { const FrameNodeImpl* impl = FrameNodeImpl::FromNode(node); - base::Value ret(base::Value::Type::DICTIONARY); + base::Value::Dict ret; // Document specific properties. These are emitted in a nested dictionary, as // a frame node can be reused for different documents. - base::Value doc(base::Value::Type::DICTIONARY); - doc.SetStringKey("url", impl->document_.url.value().possibly_invalid_spec()); - doc.SetBoolKey("has_nonempty_beforeunload", - impl->document_.has_nonempty_beforeunload); - doc.SetBoolKey("network_almost_idle", - impl->document_.network_almost_idle.value()); - doc.SetBoolKey("had_form_interaction", - impl->document_.had_form_interaction.value()); - ret.SetKey("document", std::move(doc)); + base::Value::Dict doc; + doc.Set("url", impl->document_.url.value().possibly_invalid_spec()); + doc.Set("has_nonempty_beforeunload", + impl->document_.has_nonempty_beforeunload); + doc.Set("network_almost_idle", impl->document_.network_almost_idle.value()); + doc.Set("had_form_interaction", impl->document_.had_form_interaction.value()); + ret.Set("document", std::move(doc)); // Frame node properties. - ret.SetIntKey("render_frame_id", impl->render_frame_id_); - ret.SetStringKey("frame_token", impl->frame_token_.value().ToString()); - ret.SetIntKey("browsing_instance_id", impl->browsing_instance_id_.value()); - ret.SetIntKey("site_instance_id", impl->site_instance_id_.value()); - ret.SetStringKey("lifecycle_state", - MojoEnumToString(impl->lifecycle_state_.value())); - ret.SetBoolKey("is_ad_frame", impl->is_ad_frame_.value()); - ret.SetBoolKey("is_holding_weblock", impl->is_holding_weblock_.value()); - ret.SetBoolKey("is_holding_indexeddb_lock", - impl->is_holding_indexeddb_lock_.value()); - ret.SetBoolKey("is_current", impl->is_current_.value()); - ret.SetKey("priority", - PriorityAndReasonToValue(impl->priority_and_reason_.value())); - ret.SetBoolKey("is_audible", impl->is_audible_.value()); - ret.SetStringKey( - "viewport_intersection", - ViewportIntersectionToString(impl->viewport_intersection_.value())); - ret.SetStringKey("visibility", - FrameNodeVisibilityToString(impl->visibility_.value())); + ret.Set("render_frame_id", impl->render_frame_id_); + ret.Set("frame_token", impl->frame_token_.value().ToString()); + ret.Set("browsing_instance_id", impl->browsing_instance_id_.value()); + ret.Set("site_instance_id", impl->site_instance_id_.value()); + ret.Set("lifecycle_state", MojoEnumToString(impl->lifecycle_state_.value())); + ret.Set("is_ad_frame", impl->is_ad_frame_.value()); + ret.Set("is_holding_weblock", impl->is_holding_weblock_.value()); + ret.Set("is_holding_indexeddb_lock", + impl->is_holding_indexeddb_lock_.value()); + ret.Set("is_current", impl->is_current_.value()); + ret.Set("priority", + PriorityAndReasonToValue(impl->priority_and_reason_.value())); + ret.Set("is_audible", impl->is_audible_.value()); + ret.Set("viewport_intersection", + ViewportIntersectionToString(impl->viewport_intersection_.value())); + ret.Set("visibility", FrameNodeVisibilityToString(impl->visibility_.value())); - return ret; + return base::Value(std::move(ret)); } } // namespace performance_manager
diff --git a/components/performance_manager/graph/graph_impl_unittest.cc b/components/performance_manager/graph/graph_impl_unittest.cc index 63a9bd6..32528d0b 100644 --- a/components/performance_manager/graph/graph_impl_unittest.cc +++ b/components/performance_manager/graph/graph_impl_unittest.cc
@@ -206,38 +206,38 @@ explicit TestNodeDataDescriber(base::StringPiece name) : name_(name) {} base::Value DescribeFrameNodeData(const FrameNode* node) const override { - base::Value list(base::Value::Type::LIST); + base::Value::List list; list.Append(name_); list.Append("FrameNode"); - return list; + return base::Value(std::move(list)); } base::Value DescribePageNodeData(const PageNode* node) const override { - base::Value list(base::Value::Type::LIST); + base::Value::List list; list.Append(name_); list.Append("PageNode"); - return list; + return base::Value(std::move(list)); } base::Value DescribeProcessNodeData(const ProcessNode* node) const override { - base::Value list(base::Value::Type::LIST); + base::Value::List list; list.Append(name_); list.Append("ProcessNode"); - return list; + return base::Value(std::move(list)); } base::Value DescribeSystemNodeData(const SystemNode* node) const override { - base::Value list(base::Value::Type::LIST); + base::Value::List list; list.Append(name_); list.Append("SystemNode"); - return list; + return base::Value(std::move(list)); } base::Value DescribeWorkerNodeData(const WorkerNode* node) const override { - base::Value list(base::Value::Type::LIST); + base::Value::List list; list.Append(name_); list.Append("WorkerNode"); - return list; + return base::Value(std::move(list)); } private:
diff --git a/components/performance_manager/graph/page_node_impl_describer.cc b/components/performance_manager/graph/page_node_impl_describer.cc index b2327b09..828c676e 100644 --- a/components/performance_manager/graph/page_node_impl_describer.cc +++ b/components/performance_manager/graph/page_node_impl_describer.cc
@@ -44,58 +44,49 @@ const PageNodeImpl* page_node_impl = PageNodeImpl::FromNode(page_node); DCHECK_CALLED_ON_VALID_SEQUENCE(page_node_impl->sequence_checker_); - base::Value result(base::Value::Type::DICTIONARY); + base::Value::Dict result; - result.SetKey( - "visibility_change_time", - TimeDeltaFromNowToValue(page_node_impl->visibility_change_time_)); - result.SetKey( + result.Set("visibility_change_time", + TimeDeltaFromNowToValue(page_node_impl->visibility_change_time_)); + result.Set( "navigation_committed_time", TimeDeltaFromNowToValue(page_node_impl->navigation_committed_time_)); - result.SetKey("usage_estimate_time", - TimeDeltaFromNowToValue(page_node_impl->usage_estimate_time_)); + result.Set("usage_estimate_time", + TimeDeltaFromNowToValue(page_node_impl->usage_estimate_time_)); // TODO(pmonette): Instead of emitting a raw number, this could be a human // readable string. E.g. "14.8 MiB" instead of "14523". - result.SetStringKey( + result.Set( "private_footprint_kb_estimate", base::NumberToString(page_node_impl->private_footprint_kb_estimate_)); - result.SetBoolKey("has_nonempty_beforeunload", - page_node_impl->has_nonempty_beforeunload_); - result.SetStringKey("main_frame_url", - page_node_impl->main_frame_url_.value().spec()); - result.SetStringKey("navigation_id", - base::NumberToString(page_node_impl->navigation_id_)); - result.SetStringKey("contents_mime_type", - page_node_impl->contents_mime_type_); - result.SetStringKey("browser_context_id", - page_node_impl->browser_context_id_); - result.SetStringKey("type", - PageNode::ToString(page_node_impl->type_.value())); - result.SetBoolKey("is_visible", page_node_impl->is_visible_.value()); - result.SetBoolKey("is_audible", page_node_impl->is_audible_.value()); - result.SetStringKey( - "loading_state", - PageNode::ToString(page_node_impl->loading_state_.value())); - result.SetStringKey( - "ukm_source_id", - base::NumberToString(page_node_impl->ukm_source_id_.value())); - result.SetStringKey( - "lifecycle_state", - MojoEnumToString(page_node_impl->lifecycle_state_.value())); - result.SetBoolKey("is_holding_weblock", - page_node_impl->is_holding_weblock_.value()); - result.SetBoolKey("is_holding_indexeddb_lock", - page_node_impl->is_holding_indexeddb_lock_.value()); - result.SetBoolKey("had_form_interaction", - page_node_impl->had_form_interaction_.value()); + result.Set("has_nonempty_beforeunload", + page_node_impl->has_nonempty_beforeunload_); + result.Set("main_frame_url", page_node_impl->main_frame_url_.value().spec()); + result.Set("navigation_id", + base::NumberToString(page_node_impl->navigation_id_)); + result.Set("contents_mime_type", page_node_impl->contents_mime_type_); + result.Set("browser_context_id", page_node_impl->browser_context_id_); + result.Set("type", PageNode::ToString(page_node_impl->type_.value())); + result.Set("is_visible", page_node_impl->is_visible_.value()); + result.Set("is_audible", page_node_impl->is_audible_.value()); + result.Set("loading_state", + PageNode::ToString(page_node_impl->loading_state_.value())); + result.Set("ukm_source_id", + base::NumberToString(page_node_impl->ukm_source_id_.value())); + result.Set("lifecycle_state", + MojoEnumToString(page_node_impl->lifecycle_state_.value())); + result.Set("is_holding_weblock", page_node_impl->is_holding_weblock_.value()); + result.Set("is_holding_indexeddb_lock", + page_node_impl->is_holding_indexeddb_lock_.value()); + result.Set("had_form_interaction", + page_node_impl->had_form_interaction_.value()); if (page_node_impl->embedding_type_ != PageNode::EmbeddingType::kInvalid) { - result.SetStringKey("embedding_type", - PageNode::ToString(page_node_impl->embedding_type_)); + result.Set("embedding_type", + PageNode::ToString(page_node_impl->embedding_type_)); } - result.SetStringKey("freezing_vote", - FreezingVoteToString(page_node_impl->freezing_vote())); + result.Set("freezing_vote", + FreezingVoteToString(page_node_impl->freezing_vote())); - return result; + return base::Value(std::move(result)); } } // namespace performance_manager
diff --git a/components/performance_manager/graph/process_node_impl.cc b/components/performance_manager/graph/process_node_impl.cc index d819b393..7b67137 100644 --- a/components/performance_manager/graph/process_node_impl.cc +++ b/components/performance_manager/graph/process_node_impl.cc
@@ -95,6 +95,7 @@ void ProcessNodeImpl::SetMainThreadTaskLoadIsLow( bool main_thread_task_load_is_low) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); main_thread_task_load_is_low_.SetAndMaybeNotify(this, main_thread_task_load_is_low); @@ -104,6 +105,7 @@ mojom::V8ContextDescriptionPtr description, mojom::IframeAttributionDataPtr iframe_attribution_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) { tracker->OnV8ContextCreated(PassKey(), this, *description, std::move(iframe_attribution_data)); @@ -113,6 +115,7 @@ void ProcessNodeImpl::OnV8ContextDetached( const blink::V8ContextToken& v8_context_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) tracker->OnV8ContextDetached(PassKey(), this, v8_context_token); } @@ -120,6 +123,7 @@ void ProcessNodeImpl::OnV8ContextDestroyed( const blink::V8ContextToken& v8_context_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) tracker->OnV8ContextDestroyed(PassKey(), this, v8_context_token); } @@ -129,6 +133,7 @@ const blink::RemoteFrameToken& remote_frame_token, mojom::IframeAttributionDataPtr iframe_attribution_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) { auto* ec_registry = execution_context::ExecutionContextRegistry::GetFromGraph(graph()); @@ -147,6 +152,7 @@ const blink::LocalFrameToken& parent_frame_token, const blink::RemoteFrameToken& remote_frame_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); if (auto* tracker = v8_memory::V8ContextTracker::GetFromGraph(graph())) { auto* ec_registry = execution_context::ExecutionContextRegistry::GetFromGraph(graph()); @@ -164,6 +170,7 @@ void ProcessNodeImpl::FireBackgroundTracingTrigger( const std::string& trigger_name) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce( @@ -204,16 +211,19 @@ const base::flat_set<FrameNodeImpl*>& ProcessNodeImpl::frame_nodes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return frame_nodes_; } const base::flat_set<WorkerNodeImpl*>& ProcessNodeImpl::worker_nodes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return worker_nodes_; } PageNodeImpl* ProcessNodeImpl::GetPageNodeIfExclusive() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); PageNodeImpl* page_node = nullptr; for (auto* frame_node : frame_nodes_) { @@ -227,30 +237,33 @@ RenderProcessHostId ProcessNodeImpl::GetRenderProcessId() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return RenderProcessHostId( - render_process_host_proxy().render_process_host_id()); + return render_process_host_proxy().render_process_host_id(); } void ProcessNodeImpl::AddFrame(FrameNodeImpl* frame_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); const bool inserted = frame_nodes_.insert(frame_node).second; DCHECK(inserted); } void ProcessNodeImpl::RemoveFrame(FrameNodeImpl* frame_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); DCHECK(base::Contains(frame_nodes_, frame_node)); frame_nodes_.erase(frame_node); } void ProcessNodeImpl::AddWorker(WorkerNodeImpl* worker_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); const bool inserted = worker_nodes_.insert(worker_node).second; DCHECK(inserted); } void ProcessNodeImpl::RemoveWorker(WorkerNodeImpl* worker_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); DCHECK(base::Contains(worker_nodes_, worker_node)); worker_nodes_.erase(worker_node); } @@ -262,6 +275,7 @@ void ProcessNodeImpl::add_hosted_content_type(ContentType content_type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); hosted_content_types_.Put(content_type); } @@ -337,6 +351,7 @@ bool ProcessNodeImpl::VisitFrameNodes(const FrameNodeVisitor& visitor) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); for (auto* frame_impl : frame_nodes()) { const FrameNode* frame = frame_impl; if (!visitor.Run(frame)) @@ -378,6 +393,7 @@ const RenderProcessHostProxy& ProcessNodeImpl::GetRenderProcessHostProxy() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return render_process_host_proxy(); } @@ -396,11 +412,13 @@ ProcessNode::ContentTypes ProcessNodeImpl::GetHostedContentTypes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return hosted_content_types(); } void ProcessNodeImpl::OnAllFramesInProcessFrozen() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); for (auto* observer : GetObservers()) observer->OnAllFramesInProcessFrozen(this); }
diff --git a/components/performance_manager/graph/process_node_impl.h b/components/performance_manager/graph/process_node_impl.h index cdcace6d..e0ce516 100644 --- a/components/performance_manager/graph/process_node_impl.h +++ b/components/performance_manager/graph/process_node_impl.h
@@ -112,7 +112,6 @@ } void set_resident_set_kb(uint64_t resident_set_kb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - resident_set_kb_ = resident_set_kb; } @@ -157,14 +156,18 @@ bool main_thread_task_load_is_low() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return main_thread_task_load_is_low_.value(); } const RenderProcessHostProxy& render_process_host_proxy() const { + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return absl::get<RenderProcessHostProxy>(child_process_host_proxy_); } const BrowserChildProcessHostProxy& browser_child_process_host_proxy() const { + DCHECK_NE(process_type_, content::PROCESS_TYPE_BROWSER); + DCHECK_NE(process_type_, content::PROCESS_TYPE_RENDERER); return absl::get<BrowserChildProcessHostProxy>(child_process_host_proxy_); } @@ -175,6 +178,7 @@ ContentTypes hosted_content_types() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(process_type_, content::PROCESS_TYPE_RENDERER); return hosted_content_types_; } @@ -259,8 +263,8 @@ absl::optional<int32_t> exit_status_ GUARDED_BY_CONTEXT(sequence_checker_); std::string metrics_name_ GUARDED_BY_CONTEXT(sequence_checker_); - const content::ProcessType process_type_ - GUARDED_BY_CONTEXT(sequence_checker_); + // The type of the process that this node represents. + const content::ProcessType process_type_; // The proxy that allows access to either the RenderProcessHost or the // BrowserChildProcessHost associated with this process, if `this` is a
diff --git a/components/performance_manager/graph/process_node_impl_describer.cc b/components/performance_manager/graph/process_node_impl_describer.cc index 3a393611..31cd844 100644 --- a/components/performance_manager/graph/process_node_impl_describer.cc +++ b/components/performance_manager/graph/process_node_impl_describer.cc
@@ -60,55 +60,56 @@ } base::Value GetProcessValueDict(const base::Process& process) { - base::Value ret(base::Value::Type::DICTIONARY); + base::Value::Dict ret; // On Windows, handle is a void *. On Fuchsia it's an int. On other platforms // it is equal to the pid, so don't bother to record it. #if BUILDFLAG(IS_WIN) - ret.SetIntKey("handle", base::win::HandleToUint32(process.Handle())); + ret.Set("handle", + static_cast<int>(base::win::HandleToUint32(process.Handle()))); #elif BUILDFLAG(IS_FUCHSIA) - ret.SetIntKey("handle", process.Handle()); + ret.Set("handle", static_cast<int>(process.Handle())); #endif // Most processes are not current, so only show the outliers. if (process.is_current()) { - ret.SetBoolKey("is_current", true); + ret.Set("is_current", true); } #if BUILDFLAG(IS_CHROMEOS_ASH) if (process.GetPidInNamespace() != base::kNullProcessId) { - ret.SetIntKey("pid_in_namespace", process.GetPidInNamespace()); + ret.Set("pid_in_namespace", process.GetPidInNamespace()); } #endif #if BUILDFLAG(IS_WIN) // Creation time is always available on Windows, even for dead processes. // On other platforms it is available only for valid processes (see below). - ret.SetStringKey("creation_time", base::TimeFormatTimeOfDayWithMilliseconds( - process.CreationTime())); + ret.Set("creation_time", + base::TimeFormatTimeOfDayWithMilliseconds(process.CreationTime())); #endif if (process.IsValid()) { // These properties can only be accessed for valid processes. - ret.SetIntKey("os_priority", process.GetPriority()); + ret.Set("os_priority", process.GetPriority()); #if !BUILDFLAG(IS_APPLE) - ret.SetBoolKey("is_backgrounded", process.IsProcessBackgrounded()); + ret.Set("is_backgrounded", process.IsProcessBackgrounded()); #endif #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) - ret.SetStringKey("creation_time", base::TimeFormatTimeOfDayWithMilliseconds( - process.CreationTime())); + ret.Set("creation_time", + base::TimeFormatTimeOfDayWithMilliseconds(process.CreationTime())); #endif #if BUILDFLAG(IS_WIN) // Most processes are running, so only show the outliers. if (!process.IsRunning()) { - ret.SetBoolKey("is_running", false); + ret.Set("is_running", false); } #endif } else { - ret.SetBoolKey("is_valid", false); + ret.Set("is_valid", false); } - return ret; + return base::Value(std::move(ret)); } // Converts TimeTicks to Time. The conversion will be incorrect if system @@ -135,56 +136,62 @@ const ProcessNode* node) const { const ProcessNodeImpl* impl = ProcessNodeImpl::FromNode(node); - base::Value ret(base::Value::Type::DICTIONARY); + base::Value::Dict ret; + + ret.Set("pid", base::NumberToString(impl->process_id())); + + ret.Set("process", GetProcessValueDict(impl->process())); + + ret.Set("launch_time", base::TimeFormatTimeOfDayWithMilliseconds( + TicksToTime(impl->launch_time()))); + + if (impl->exit_status()) { + ret.Set("exit_status", impl->exit_status().value()); + } + + if (!impl->metrics_name().empty()) { + ret.Set("metrics_name", impl->metrics_name()); + } + + ret.Set("priority", base::TaskPriorityToString(impl->priority())); if (impl->private_footprint_kb()) { - ret.SetIntKey("private_footprint_kb", - base::saturated_cast<int>(impl->private_footprint_kb())); + ret.Set("private_footprint_kb", + base::saturated_cast<int>(impl->private_footprint_kb())); } if (impl->resident_set_kb()) { - ret.SetIntKey("resident_set_kb", - base::saturated_cast<int>(impl->resident_set_kb())); - } - - constexpr RenderProcessHostId kInvalidRenderProcessHostId = - RenderProcessHostId(content::ChildProcessHost::kInvalidUniqueID); - if (impl->GetRenderProcessId() != kInvalidRenderProcessHostId) { - ret.SetIntKey("render_process_id", impl->GetRenderProcessId().value()); + ret.Set("resident_set_kb", + base::saturated_cast<int>(impl->resident_set_kb())); } // The content function returns "Tab" for renderers - whereas "Renderer" is // the common vernacular here. std::string process_type = content::GetProcessTypeNameInEnglish(impl->process_type()); - if (impl->process_type() == content::PROCESS_TYPE_RENDERER) + if (impl->process_type() == content::PROCESS_TYPE_RENDERER) { process_type = "Renderer"; - ret.SetStringKey("process_type", process_type); + } + ret.Set("process_type", process_type); - ret.SetStringKey("pid", base::NumberToString(impl->process_id())); + if (impl->process_type() == content::PROCESS_TYPE_RENDERER) { + // Renderer-only properties. + ret.Set("render_process_id", impl->GetRenderProcessId().value()); - ret.SetKey("process", GetProcessValueDict(impl->process())); + ret.Set("main_thread_task_load_is_low", + impl->main_thread_task_load_is_low()); - ret.SetStringKey("launch_time", base::TimeFormatTimeOfDayWithMilliseconds( - TicksToTime(impl->launch_time()))); - - if (impl->exit_status()) { - ret.SetIntKey("exit_status", impl->exit_status().value()); + ret.Set("hosted_content_types", + HostedProcessTypesToString(impl->hosted_content_types())); + } else if (impl->process_type() != content::PROCESS_TYPE_BROWSER) { + // Non-renderer child process properties. + ret.Set("browser_child_process_host_id", + impl->browser_child_process_host_proxy() + .browser_child_process_host_id() + .value()); } - if (!impl->metrics_name().empty()) { - ret.SetStringKey("metrics_name", impl->metrics_name()); - } - - ret.SetBoolKey("main_thread_task_load_is_low", - impl->main_thread_task_load_is_low()); - - ret.SetStringKey("priority", base::TaskPriorityToString(impl->priority())); - - ret.SetStringKey("hosted_content_types", - HostedProcessTypesToString(impl->hosted_content_types())); - - return ret; + return base::Value(std::move(ret)); } } // namespace performance_manager
diff --git a/components/performance_manager/graph/worker_node_impl_describer.cc b/components/performance_manager/graph/worker_node_impl_describer.cc index 2008296..72db192b 100644 --- a/components/performance_manager/graph/worker_node_impl_describer.cc +++ b/components/performance_manager/graph/worker_node_impl_describer.cc
@@ -42,15 +42,14 @@ if (!impl) return base::Value(); - base::Value ret(base::Value::Type::DICTIONARY); - ret.SetKey("browser_context_id", base::Value(impl->browser_context_id())); - ret.SetKey("worker_token", base::Value(impl->worker_token().ToString())); - ret.SetKey("url", base::Value(impl->url().spec())); - ret.SetKey("worker_type", - base::Value(WorkerTypeToString(impl->worker_type()))); - ret.SetKey("priority", PriorityAndReasonToValue(impl->priority_and_reason())); + base::Value::Dict ret; + ret.Set("browser_context_id", impl->browser_context_id()); + ret.Set("worker_token", impl->worker_token().ToString()); + ret.Set("url", impl->url().spec()); + ret.Set("worker_type", WorkerTypeToString(impl->worker_type())); + ret.Set("priority", PriorityAndReasonToValue(impl->priority_and_reason())); - return ret; + return base::Value(std::move(ret)); } } // namespace performance_manager
diff --git a/components/performance_manager/persistence/site_data/site_data_cache_inspector.h b/components/performance_manager/persistence/site_data/site_data_cache_inspector.h index 5ac68bd5..e5f8cfd2 100644 --- a/components/performance_manager/persistence/site_data/site_data_cache_inspector.h +++ b/components/performance_manager/persistence/site_data/site_data_cache_inspector.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/functional/callback.h" -#include "base/supports_user_data.h" #include "components/performance_manager/persistence/site_data/site_data.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h"
diff --git a/components/performance_manager/public/graph/node_data_describer_util.cc b/components/performance_manager/public/graph/node_data_describer_util.cc index 181c8e0b..89b086f 100644 --- a/components/performance_manager/public/graph/node_data_describer_util.cc +++ b/components/performance_manager/public/graph/node_data_describer_util.cc
@@ -27,12 +27,11 @@ base::Value PriorityAndReasonToValue( const execution_context_priority::PriorityAndReason& priority_and_reason) { - base::Value priority(base::Value::Type::DICTIONARY); - priority.SetStringKey( - "priority", base::TaskPriorityToString(priority_and_reason.priority())); - priority.SetPath("reason", - MaybeNullStringToValue(priority_and_reason.reason())); - return priority; + base::Value::Dict priority; + priority.Set("priority", + base::TaskPriorityToString(priority_and_reason.priority())); + priority.Set("reason", MaybeNullStringToValue(priority_and_reason.reason())); + return base::Value(std::move(priority)); } } // namespace performance_manager
diff --git a/components/performance_manager/v8_memory/v8_context_tracker.cc b/components/performance_manager/v8_memory/v8_context_tracker.cc index 6ab8fc9..69d07b2 100644 --- a/components/performance_manager/v8_memory/v8_context_tracker.cc +++ b/components/performance_manager/v8_memory/v8_context_tracker.cc
@@ -417,9 +417,9 @@ if (ec_data) v8_context_count = ec_data->v8_context_count(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("v8_context_count", v8_context_count); - return dict; + base::Value::Dict dict; + dict.Set("v8_context_count", static_cast<int>(v8_context_count)); + return base::Value(std::move(dict)); } base::Value V8ContextTracker::DescribeProcessNodeData( @@ -439,13 +439,15 @@ process_data->GetDestroyedExecutionContextDataCount(); } - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("v8_context_count", v8_context_count); - dict.SetIntKey("detached_v8_context_count", detached_v8_context_count); - dict.SetIntKey("execution_context_count", execution_context_count); - dict.SetIntKey("destroyed_execution_context_count", - destroyed_execution_context_count); - return dict; + base::Value::Dict dict; + dict.Set("v8_context_count", static_cast<int>(v8_context_count)); + dict.Set("detached_v8_context_count", + static_cast<int>(detached_v8_context_count)); + dict.Set("execution_context_count", + static_cast<int>(execution_context_count)); + dict.Set("destroyed_execution_context_count", + static_cast<int>(destroyed_execution_context_count)); + return base::Value(std::move(dict)); } base::Value V8ContextTracker::DescribeWorkerNodeData( @@ -457,9 +459,9 @@ if (ec_data) v8_context_count = ec_data->v8_context_count(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("v8_context_count", v8_context_count); - return dict; + base::Value::Dict dict; + dict.Set("v8_context_count", static_cast<int>(v8_context_count)); + return base::Value(std::move(dict)); } void V8ContextTracker::OnBeforeProcessNodeRemoved(const ProcessNode* node) {
diff --git a/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc b/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc index 3aa978e..c811a2d 100644 --- a/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc +++ b/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc
@@ -761,9 +761,9 @@ if (!frame_data) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("v8_bytes_used", frame_data->v8_bytes_used()); - return dict; + base::Value::Dict dict; + dict.Set("v8_bytes_used", static_cast<int>(frame_data->v8_bytes_used())); + return base::Value(std::move(dict)); } base::Value V8DetailedMemoryDecorator::DescribeProcessNodeData( @@ -776,11 +776,12 @@ DCHECK_EQ(content::PROCESS_TYPE_RENDERER, process_node->GetProcessType()); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("detached_v8_bytes_used", - process_data->detached_v8_bytes_used()); - dict.SetIntKey("shared_v8_bytes_used", process_data->shared_v8_bytes_used()); - return dict; + base::Value::Dict dict; + dict.Set("detached_v8_bytes_used", + static_cast<int>(process_data->detached_v8_bytes_used())); + dict.Set("shared_v8_bytes_used", + static_cast<int>(process_data->shared_v8_bytes_used())); + return base::Value(std::move(dict)); } const V8DetailedMemoryRequest* V8DetailedMemoryDecorator::GetNextRequest()
diff --git a/components/permissions/constants.cc b/components/permissions/constants.cc index 000453e46..f08f9c5 100644 --- a/components/permissions/constants.cc +++ b/components/permissions/constants.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/permissions/constants.h" +#include "base/time/clock.h" namespace permissions { @@ -10,36 +11,25 @@ "https://support.google.com/chrome?p=bluetooth"; #if !BUILDFLAG(IS_ANDROID) -// The key in `Product Specific String Data` under which the disposition of the -// permission prompt is recorded in the post-prompt HaTS survey. const char kPermissionsPostPromptSurveyPromptDispositionKey[] = "PromptDisposition"; -// The key in `Product Specific String Data` under which the quiet UI reason is -// recorded in the post-prompt HaTS survey. const char kPermissionsPostPromptSurveyPromptDispositionReasonKey[] = "PromptDispositionReason"; -// The key in `Product Specific String Data` under which the request action is -// recorded in the post-prompt HaTS survey. const char kPermissionsPostPromptSurveyActionKey[] = "Action"; -// The key in `Product Specific String Data` under which the request type is -// recorded in the post-prompt HaTS survey. const char kPermissionsPostPromptSurveyRequestTypeKey[] = "RequestType"; -// The key in `Product Specific Bits Data` under which whether the prompt was -// triggered by a user gestured is recorded in the post-prompt HaTS survey. const char kPermissionsPostPromptSurveyHadGestureKey[] = "HadGesture"; -// The key in `Product Specific Bits Data` under which the release channel on -// which the prompt was triggered is recorded in the post-prompt HaTS survey. -// Note that a finch config typically defines a min_version to run the -// experiment. When Version V is stable, Beta (V+1), Dev (V+2) and Canary (V+3) -// all have higher version numbers and will therefore be part of the experiment -// with min_version V with the rollout plan for stable. This filter allows -// restriction to specific channels (typically to stable). const char kPermissionsPostPromptSurveyReleaseChannelKey[] = "ReleaseChannel"; #endif +// TODO(crbug.com/1410489): Remove the code related to unused site permissions +// from Android builds. + +const char kRevokedKey[] = "revoked"; + +const base::TimeDelta kRevocationCleanUpThreshold = base::Days(30); } // namespace permissions
diff --git a/components/permissions/constants.h b/components/permissions/constants.h index 909ff9c..6093ccf 100644 --- a/components/permissions/constants.h +++ b/components/permissions/constants.h
@@ -6,6 +6,7 @@ #define COMPONENTS_PERMISSIONS_CONSTANTS_H_ #include "base/component_export.h" +#include "base/time/clock.h" #include "build/build_config.h" namespace permissions { @@ -16,25 +17,55 @@ extern const char kChooserBluetoothOverviewURL[]; #if !BUILDFLAG(IS_ANDROID) +// The key in `Product Specific String Data` under which the disposition of the +// permission prompt is recorded in the post-prompt HaTS survey. COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyPromptDispositionKey[]; +// The key in `Product Specific String Data` under which the quiet UI reason is +// recorded in the post-prompt HaTS survey. COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyPromptDispositionReasonKey[]; +// The key in `Product Specific String Data` under which the request action is +// recorded in the post-prompt HaTS survey. COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyActionKey[]; +// The key in `Product Specific String Data` under which the request type is +// recorded in the post-prompt HaTS survey. COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyRequestTypeKey[]; +// The key in `Product Specific Bits Data` under which whether the prompt was +// triggered by a user gestured is recorded in the post-prompt HaTS survey. COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyHadGestureKey[]; +// The key in `Product Specific Bits Data` under which the release channel on +// which the prompt was triggered is recorded in the post-prompt HaTS survey. +// Note that a finch config typically defines a min_version to run the +// experiment. When Version V is stable, Beta (V+1), Dev (V+2) and Canary (V+3) +// all have higher version numbers and will therefore be part of the experiment +// with min_version V with the rollout plan for stable. This filter allows +// restriction to specific channels (typically to stable). COMPONENT_EXPORT(PERMISSIONS_COMMON) extern const char kPermissionsPostPromptSurveyReleaseChannelKey[]; #endif +// TODO(crbug.com/1410489): Remove the code related to unused site permissions +// from Android builds. + +// The key used for marking permissions as revoked, as per the unused site +// permissions module of Safety Check. +COMPONENT_EXPORT(PERMISSIONS_COMMON) +extern const char kRevokedKey[]; + +// The duration for which a site's permissions are revoked and presented for +// review to the user in the unused site permissions module of Safety Check. +COMPONENT_EXPORT(PERMISSIONS_COMMON) +extern const base::TimeDelta kRevocationCleanUpThreshold; + } // namespace permissions #endif // COMPONENTS_PERMISSIONS_CONSTANTS_H_
diff --git a/components/permissions/contexts/bluetooth_chooser_context.cc b/components/permissions/contexts/bluetooth_chooser_context.cc index 7e48c3e..1a82cbd 100644 --- a/components/permissions/contexts/bluetooth_chooser_context.cc +++ b/components/permissions/contexts/bluetooth_chooser_context.cc
@@ -98,7 +98,19 @@ manufacturer_data_list.Append(manufacturer_code); } -base::Value::Dict DeviceInfoToDeviceObject( +} // namespace + +BluetoothChooserContext::BluetoothChooserContext( + content::BrowserContext* browser_context) + : ObjectPermissionContextBase( + ContentSettingsType::BLUETOOTH_GUARD, + ContentSettingsType::BLUETOOTH_CHOOSER_DATA, + PermissionsClient::Get()->GetSettingsMap(browser_context)) {} + +BluetoothChooserContext::~BluetoothChooserContext() = default; + +// static +base::Value::Dict BluetoothChooserContext::DeviceInfoToValue( const device::BluetoothDevice* device, const blink::mojom::WebBluetoothRequestDeviceOptions* options, const WebBluetoothDeviceId& device_id) { @@ -116,17 +128,6 @@ return device_value; } -} // namespace - -BluetoothChooserContext::BluetoothChooserContext( - content::BrowserContext* browser_context) - : ObjectPermissionContextBase( - ContentSettingsType::BLUETOOTH_GUARD, - ContentSettingsType::BLUETOOTH_CHOOSER_DATA, - PermissionsClient::Get()->GetSettingsMap(browser_context)) {} - -BluetoothChooserContext::~BluetoothChooserContext() = default; - WebBluetoothDeviceId BluetoothChooserContext::GetWebBluetoothDeviceId( const url::Origin& origin, const std::string& device_address) { @@ -238,7 +239,7 @@ device_id = WebBluetoothDeviceId::Create(); base::Value::Dict permission_object = - DeviceInfoToDeviceObject(device, options, device_id); + DeviceInfoToValue(device, options, device_id); GrantObjectPermission(origin, base::Value(std::move(permission_object))); return device_id; }
diff --git a/components/permissions/contexts/bluetooth_chooser_context.h b/components/permissions/contexts/bluetooth_chooser_context.h index 371eb8f..e3b4565 100644 --- a/components/permissions/contexts/bluetooth_chooser_context.h +++ b/components/permissions/contexts/bluetooth_chooser_context.h
@@ -48,6 +48,11 @@ BluetoothChooserContext(const BluetoothChooserContext&) = delete; BluetoothChooserContext& operator=(const BluetoothChooserContext&) = delete; + static base::Value::Dict DeviceInfoToValue( + const device::BluetoothDevice* device, + const blink::mojom::WebBluetoothRequestDeviceOptions* options, + const blink::WebBluetoothDeviceId& device_id); + // Helper methods for converting between a WebBluetoothDeviceId and a // Bluetooth device address string for a given origin pair. blink::WebBluetoothDeviceId GetWebBluetoothDeviceId(
diff --git a/components/permissions/unused_site_permissions_service.cc b/components/permissions/unused_site_permissions_service.cc index a0e4b46..b19f855 100644 --- a/components/permissions/unused_site_permissions_service.cc +++ b/components/permissions/unused_site_permissions_service.cc
@@ -25,16 +25,15 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/content_settings/core/common/features.h" +#include "components/permissions/constants.h" #include "content/public/browser/browser_thread.h" #include "url/gurl.h" #include "url/origin.h" -constexpr char kRevokedKey[] = "revoked"; constexpr base::TimeDelta kRevocationThreshold = base::Days(60); constexpr base::TimeDelta kRevocationThresholdNoDelayForTesting = base::Days(0); constexpr base::TimeDelta kRevocationThresholdWithDelayForTesting = base::Minutes(5); -constexpr base::TimeDelta kRevocationCleanUpThreshold = base::Days(30); constexpr base::TimeDelta kRevocationCleanUpThresholdWithDelayForTesting = base::Minutes(30); @@ -99,7 +98,7 @@ .Get()) { return kRevocationCleanUpThresholdWithDelayForTesting; } - return kRevocationCleanUpThreshold; + return permissions::kRevocationCleanUpThreshold; } } // namespace @@ -294,6 +293,7 @@ ContentSetting setting = content_settings::ValueToContentSetting(entry.source.setting_value); if (!content_settings::CanBeAutoRevoked(entry.type, setting)) { + permission_itr++; continue; } @@ -358,8 +358,9 @@ base::Value::Dict dict = cur_value.is_dict() ? std::move(cur_value.GetDict()) : base::Value::Dict(); base::Value::List permission_type_list = - dict.FindList(kRevokedKey) ? std::move(*dict.FindList(kRevokedKey)) - : base::Value::List(); + dict.FindList(permissions::kRevokedKey) + ? std::move(*dict.FindList(permissions::kRevokedKey)) + : base::Value::List(); for (const auto& permission : recently_revoked_permissions) { permission_type_list.Append(static_cast<int32_t>(permission.type));
diff --git a/components/permissions/unused_site_permissions_service_unittest.cc b/components/permissions/unused_site_permissions_service_unittest.cc index b89cbd6b..9051dc3 100644 --- a/components/permissions/unused_site_permissions_service_unittest.cc +++ b/components/permissions/unused_site_permissions_service_unittest.cc
@@ -18,12 +18,11 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/features.h" +#include "components/permissions/constants.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" -constexpr char kRevokedKey[] = "revoked"; - namespace permissions { class UnusedSitePermissionsServiceTest : public content::RenderViewHostTestHarness { @@ -77,12 +76,12 @@ base::Value::List permissions_list; if (!setting_value.is_dict() || - !setting_value.GetDict().FindList(kRevokedKey)) { + !setting_value.GetDict().FindList(permissions::kRevokedKey)) { return permissions_list; } permissions_list = - std::move(*setting_value.GetDict().FindList(kRevokedKey)); + std::move(*setting_value.GetDict().FindList(permissions::kRevokedKey)); return permissions_list; } @@ -196,6 +195,34 @@ EXPECT_EQ(GURL(tracked_origin.source.primary_pattern.ToString()), url1); } +TEST_F(UnusedSitePermissionsServiceTest, TrackUnusedButDontRevoke) { + base::test::ScopedFeatureList scoped_feature; + scoped_feature.InitAndEnableFeature( + content_settings::features::kSafetyCheckUnusedSitePermissions); + + const GURL url("https://example1.com"); + const content_settings::ContentSettingConstraints constraint{ + .track_last_visit_for_autoexpiration = true}; + + // Grant GEOLOCATION permission for the url. + hcsm()->SetContentSettingDefaultScope( + url, url, ContentSettingsType::GEOLOCATION, + ContentSetting::CONTENT_SETTING_BLOCK, constraint); + + // Travel through time for 20 days. + clock()->Advance(base::Days(20)); + + // GEOLOCATION permission should be on the tracked unused site permissions + // list as it is denied 20 days before. The permission is not suitable for + // revocation and this test verifies that RevokeUnusedPermissions() does not + // enter infinite loop in such case. + service()->UpdateUnusedPermissionsForTesting(); + auto unused_permissions = service()->GetTrackedUnusedPermissionsForTesting(); + ASSERT_EQ(unused_permissions.size(), 1u); + EXPECT_EQ(unused_permissions[0].type, ContentSettingsType::GEOLOCATION); + EXPECT_EQ(GetRevokedPermissionsForOneOrigin(hcsm(), url).size(), 0u); +} + TEST_F(UnusedSitePermissionsServiceTest, MultipleRevocationsForSameOrigin) { base::test::ScopedFeatureList scoped_feature; scoped_feature.InitAndEnableFeature(
diff --git a/components/policy/core/browser/browser_policy_connector.cc b/components/policy/core/browser/browser_policy_connector.cc index cf4978ff..4b56da9c7 100644 --- a/components/policy/core/browser/browser_policy_connector.cc +++ b/components/policy/core/browser/browser_policy_connector.cc
@@ -119,18 +119,6 @@ } // static -bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) { - TRACE_EVENT0("browser", "BrowserPolicyConnector::IsNonEnterpriseUser"); - return signin::AccountManagedStatusFinder::IsNonEnterpriseUser(username); -} - -// static -void BrowserPolicyConnector::SetNonEnterpriseDomainForTesting( - const char* domain) { - signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting(domain); -} - -// static void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterIntegerPref( policy_prefs::kUserPolicyRefreshRate,
diff --git a/components/policy/core/browser/browser_policy_connector.h b/components/policy/core/browser/browser_policy_connector.h index 447b67e..258507128 100644 --- a/components/policy/core/browser/browser_policy_connector.h +++ b/components/policy/core/browser/browser_policy_connector.h
@@ -67,20 +67,6 @@ // Returns the URL for the encrypted reporting service endpoint. std::string GetEncryptedReportingUrl() const; - // Check whether a user is known to be non-enterprise. Domains such as - // gmail.com and googlemail.com are known to not be managed. Also returns - // true if the username is empty or not a valid email address. - // TODO(crbug.com/1378553): Migrate callers to - // signin::AccountManagedStatusFinder::IsNonEnterpriseUser(). - static bool IsNonEnterpriseUser(const std::string& username); - - // Allows to register domain for tests that is recognized as non-enterprise. - // Note that |domain| basically needs to live until this method is invoked - // with a nullptr. - // TODO(crbug.com/1378553): Migrate callers to - // signin::AccountManagedStatusFinder::SetNonEnterpriseDomainForTesting(). - static void SetNonEnterpriseDomainForTesting(const char* domain); - // Registers refresh rate prefs. static void RegisterPrefs(PrefRegistrySimple* registry);
diff --git a/components/policy/core/browser/cloud/user_policy_signin_service_base.cc b/components/policy/core/browser/cloud/user_policy_signin_service_base.cc index 4874b83c..ef2f9d6 100644 --- a/components/policy/core/browser/cloud/user_policy_signin_service_base.cc +++ b/components/policy/core/browser/cloud/user_policy_signin_service_base.cc
@@ -11,12 +11,12 @@ #include "base/location.h" #include "base/task/single_thread_task_runner.h" #include "build/build_config.h" -#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" #include "components/prefs/pref_service.h" #include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/account_managed_status_finder.h" namespace em = enterprise_management; @@ -174,7 +174,9 @@ if (username.empty()) return false; // Not signed in. - return !BrowserPolicyConnector::IsNonEnterpriseUser(username); + return signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + username) == + signin::AccountManagedStatusFinder::EmailEnterpriseStatus::kUnknown; } void UserPolicySigninServiceBase::InitializeForSignedInUser(
diff --git a/components/policy/core/browser/cloud/user_policy_signin_service_base.h b/components/policy/core/browser/cloud/user_policy_signin_service_base.h index c07c69db..55703348 100644 --- a/components/policy/core/browser/cloud/user_policy_signin_service_base.h +++ b/components/policy/core/browser/cloud/user_policy_signin_service_base.h
@@ -183,7 +183,7 @@ // Returns false if cloud policy is disabled or if the passed |email_address| // is definitely not from a hosted domain (according to the list in - // BrowserPolicyConnector::IsNonEnterpriseUser()). + // signin::AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail()). bool ShouldLoadPolicyForUser(const std::string& email_address); // Handler to call the policy registration callback that provides the DM
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/ChromeAppsEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/ChromeAppsEnabled.yaml index 8945c9b..3b3eb42 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/ChromeAppsEnabled.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/ChromeAppsEnabled.yaml
@@ -22,7 +22,7 @@ - mattm@chromium.org schema: type: boolean -supported_on: +supported_on: # Disable in m114: b/266505189 - chrome.win:104- - chrome.mac:104- - chrome.linux:104-
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/DefaultHandlersForFileExtensions.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/DefaultHandlersForFileExtensions.yaml index 23116190..0af81c4 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/DefaultHandlersForFileExtensions.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/DefaultHandlersForFileExtensions.yaml
@@ -34,8 +34,8 @@ can_be_recommended: true dynamic_refresh: true per_profile: true -future_on: -- chrome_os +supported_on: +- chrome_os:110- owners: - greengrape@google.com - file://ui/file_manager/OWNERS
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/OriginAgentClusterDefaultEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/OriginAgentClusterDefaultEnabled.yaml index 0dd2a7c8..c608e78 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/OriginAgentClusterDefaultEnabled.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/OriginAgentClusterDefaultEnabled.yaml
@@ -1,19 +1,28 @@ caption: Allows origin-keyed agent clustering by default. default: true -desc: "This policy allows origin-keyed agent clustering by default.\n\n The Origin-Agent-Cluster:\ - \ HTTP header controls whether a document is\n isolated in an origin-keyed\ - \ agent cluster, or in a site-keyed agent\n cluster. This has security implications\ - \ since an origin-keyed agent\n cluster allows isolating documents by origin.\ - \ The developer-visible\n consequence of this is that the document.domain accessor\ - \ can no longer\n be set.\n\n The default behaviour - when no Origin-Agent-Cluster:\ - \ header has been set\n - changes in M106 from site-keyed to origin-keyed.\ - \ If this policy\n is enabled or not set, the browser will follow this new\ - \ default from that\n version on. If this policy is disabled this change is\ - \ reversed and\n documents without Origin-Agent-Cluster: headers will be assigned\ - \ to\n site-keyed agent clusters. As a consequence, the document.domain accessor\n\ - \ remains settable by default. This matches the legacy behaviour.\n\n \ - \ See https://developer.chrome.com/blog/immutable-document-domain/\n for additional\ - \ details.\n " +desc: |- + This policy allows origin-keyed agent clustering by default. + + The Origin-Agent-Cluster HTTP header controls whether a document is + isolated in an origin-keyed agent cluster, or in a site-keyed agent + cluster. This has security implications since an origin-keyed agent + cluster allows isolating documents by origin. The developer-visible + consequence of this is that the document.domain accessor can no longer + be set. + + The default behaviour - when no Origin-Agent-Cluster header has been set - + changes in M111 from site-keyed to origin-keyed. + + If this policy is enabled or not set, the browser will follow this + new default from that version on. + + If this policy is disabled this change is reversed and + documents without Origin-Agent-Cluster headers will be assigned to + site-keyed agent clusters. As a consequence, the document.domain accessor + remains settable by default. This matches the legacy behaviour. + + See https://developer.chrome.com/blog/immutable-document-domain/ for + additional details. example_value: false features: dynamic_refresh: true
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/PPAPISharedImagesSwapChainAllowed.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/PPAPISharedImagesSwapChainAllowed.yaml index b5ac12ed..1fca1642 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/PPAPISharedImagesSwapChainAllowed.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/PPAPISharedImagesSwapChainAllowed.yaml
@@ -13,15 +13,25 @@ implementation is used. When the policy is set to Disabled, browser will use the old implementation until the policy is expired. + + If you must use the policy, please file a bug on crbug.com explaining your + use case. The policy is scheduled to be offered through <ph + name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 114, after which + the old implementation will be removed. + + NOTE: Only newly-started renderer processes will reflect changes to this + policy while the browser is running. + supported_on: -- chrome.*:110-114 -- chrome_os:110-114 +# TODO(crbug.com/1410109): Remove this policy on ~May 6 after 114 has branched. +- chrome.*:110- +- chrome_os:110- device_only: false supported_chrome_os_management: - google_cloud - active_directory features: - dynamic_refresh: false + dynamic_refresh: true per_profile: false type: main schema:
diff --git a/components/policy/test_support/BUILD.gn b/components/policy/test_support/BUILD.gn index 97bac12e..c8796d8 100644 --- a/components/policy/test_support/BUILD.gn +++ b/components/policy/test_support/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("//testing/test.gni") + static_library("test_support") { testonly = true @@ -34,8 +36,6 @@ "request_handler_for_device_state_retrieval.h", "request_handler_for_policy.cc", "request_handler_for_policy.h", - "request_handler_for_psm_auto_enrollment.cc", - "request_handler_for_psm_auto_enrollment.h", "request_handler_for_register_browser.cc", "request_handler_for_register_browser.h", "request_handler_for_register_cert_based.cc", @@ -60,6 +60,13 @@ ] } + if (is_chromeos_ash) { + sources += [ + "request_handler_for_psm_auto_enrollment.cc", + "request_handler_for_psm_auto_enrollment.h", + ] + } + public_deps = [ "//net:test_support" ] deps = [ "//base", @@ -73,6 +80,16 @@ "//third_party/private_membership:private_membership_proto", "//third_party/re2:re2", ] + + if (is_chromeos_ash) { + public_deps += [ "//third_party/private_membership" ] + + data = [ + # TODO(crbug/1393862): Script should create binarypb from textpb. + # Required for policy/enrollment/psm/rlwe_test_support.cc + "//third_party/private_membership/src/internal/testing/regression_test_data/test_data.binarypb", + ] + } } if (is_chromeos) { @@ -113,7 +130,6 @@ "request_handler_for_device_initial_enrollment_state_unittest.cc", "request_handler_for_device_state_retrieval_unittest.cc", "request_handler_for_policy_unittest.cc", - "request_handler_for_psm_auto_enrollment_unittest.cc", "request_handler_for_register_browser_unittest.cc", "request_handler_for_register_cert_based_unittest.cc", "request_handler_for_register_device_and_user_unittest.cc", @@ -127,6 +143,10 @@ sources += [ "fake_dmserver_unittest.cc" ] } + if (is_chromeos_ash) { + sources += [ "request_handler_for_psm_auto_enrollment_unittest.cc" ] + } + deps = [ ":test_support", "//components/policy/core/common:common_constants",
diff --git a/components/policy/test_support/DEPS b/components/policy/test_support/DEPS index 882cd295..6863782 100644 --- a/components/policy/test_support/DEPS +++ b/components/policy/test_support/DEPS
@@ -10,6 +10,7 @@ "+net", "+services/network/public/cpp", "+services/network/public/mojom", + "+third_party/private_membership", "+services/network/test", "+third_party/re2", ]
diff --git a/components/policy/test_support/embedded_policy_test_server.cc b/components/policy/test_support/embedded_policy_test_server.cc index f392013..a65aba0 100644 --- a/components/policy/test_support/embedded_policy_test_server.cc +++ b/components/policy/test_support/embedded_policy_test_server.cc
@@ -26,7 +26,9 @@ #include "components/policy/test_support/request_handler_for_device_initial_enrollment_state.h" #include "components/policy/test_support/request_handler_for_device_state_retrieval.h" #include "components/policy/test_support/request_handler_for_policy.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) #include "components/policy/test_support/request_handler_for_psm_auto_enrollment.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) #include "components/policy/test_support/request_handler_for_register_browser.h" #include "components/policy/test_support/request_handler_for_register_cert_based.h" #include "components/policy/test_support/request_handler_for_register_device_and_user.h" @@ -114,7 +116,9 @@ RegisterHandler( std::make_unique<RequestHandlerForDeviceStateRetrieval>(this)); RegisterHandler(std::make_unique<RequestHandlerForPolicy>(this)); +#if BUILDFLAG(IS_CHROMEOS_ASH) RegisterHandler(std::make_unique<RequestHandlerForPsmAutoEnrollment>(this)); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) RegisterHandler(std::make_unique<RequestHandlerForRegisterBrowser>(this)); RegisterHandler(std::make_unique<RequestHandlerForRegisterCertBased>(this)); RegisterHandler(
diff --git a/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc b/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc index 5ede0404..eff752d 100644 --- a/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc +++ b/components/policy/test_support/request_handler_for_psm_auto_enrollment.cc
@@ -4,31 +4,83 @@ #include "components/policy/test_support/request_handler_for_psm_auto_enrollment.h" -#include "base/containers/contains.h" +#include <vector> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/proto/device_management_backend.pb.h" -#include "components/policy/test_support/client_storage.h" -#include "components/policy/test_support/policy_storage.h" #include "components/policy/test_support/test_server_helpers.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "third_party/private_membership/src/internal/testing/regression_test_data/regression_test_data.pb.h" using net::test_server::HttpRequest; using net::test_server::HttpResponse; namespace em = enterprise_management; +using RlweTestData = + private_membership::rlwe::PrivateMembershipRlweClientRegressionTestData; namespace policy { - namespace { -constexpr const char* kPsmMembershipEncryptedTestIds[] = { - "54455354/111111", // Brand code "TEST" (as hex), serial number "111111". -}; +const RlweTestData::TestCase* FindOprfTestCase( + const RlweTestData& test_data, + const private_membership::rlwe::PrivateMembershipRlweOprfRequest& request) { + for (const auto& test_case : test_data.test_cases()) { + if (request.SerializeAsString() == + test_case.expected_oprf_request().SerializeAsString()) { + return &test_case; + } + } + return nullptr; +} + +const RlweTestData::TestCase* FindQueryTestCase( + const RlweTestData& test_data, + const private_membership::rlwe::PrivateMembershipRlweQueryRequest& + request) { + for (const auto& test_case : test_data.test_cases()) { + if (request.SerializeAsString() == + test_case.expected_query_request().SerializeAsString()) { + return &test_case; + } + } + return nullptr; +} } // namespace +// static +std::unique_ptr<RlweTestData> +RequestHandlerForPsmAutoEnrollment::LoadTestData() { + base::FilePath src_root_dir; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_root_dir)); + const base::FilePath path_to_test_data = + src_root_dir.AppendASCII("third_party") + .AppendASCII("private_membership") + .AppendASCII("src") + .AppendASCII("internal") + .AppendASCII("testing") + .AppendASCII("regression_test_data") + .AppendASCII("test_data.binarypb"); + + base::ScopedAllowBlockingForTesting allow_blocking; + CHECK(base::PathExists(path_to_test_data)) + << " path_to_test_data: " << path_to_test_data; + + std::string serialized_test_data; + CHECK(base::ReadFileToString(path_to_test_data, &serialized_test_data)); + + auto test_data = std::make_unique<RlweTestData>(); + CHECK(test_data->ParseFromString(serialized_test_data)); + + return test_data; +} + RequestHandlerForPsmAutoEnrollment::RequestHandlerForPsmAutoEnrollment( EmbeddedPolicyTestServer* parent) : EmbeddedPolicyTestServer::RequestHandler(parent) {} @@ -42,42 +94,35 @@ std::unique_ptr<HttpResponse> RequestHandlerForPsmAutoEnrollment::HandleRequest( const HttpRequest& request) { + if (!test_data_) { + test_data_ = LoadTestData(); + } em::DeviceManagementRequest device_management_request; device_management_request.ParseFromString(request.content); - const em::PrivateSetMembershipRequest& psm_request = - device_management_request.private_set_membership_request(); em::DeviceManagementResponse device_management_response; em::PrivateSetMembershipResponse* psm_response = device_management_response.mutable_private_set_membership_response(); - const auto& rlwe_request = psm_request.rlwe_request(); + const auto& rlwe_request = + device_management_request.private_set_membership_request().rlwe_request(); if (rlwe_request.has_oprf_request()) { - if (rlwe_request.oprf_request().encrypted_ids_size() == 0) { - return CreateHttpResponse( - net::HTTP_BAD_REQUEST, - "PSM RLWE OPRF request must contain encrypted_ids field"); + const auto* test_case = + FindOprfTestCase(*test_data_, rlwe_request.oprf_request()); + if (!test_case) { + return CreateHttpResponse(net::HTTP_BAD_REQUEST, + "PSM RLWE OPRF request not as expected"); } - psm_response->mutable_rlwe_response() - ->mutable_oprf_response() - ->add_doubly_encrypted_ids() - ->set_queried_encrypted_id( - rlwe_request.oprf_request().encrypted_ids(0)); + *psm_response->mutable_rlwe_response()->mutable_oprf_response() = + test_case->oprf_response(); } else if (rlwe_request.has_query_request()) { - if (rlwe_request.query_request().queries_size() == 0) { - return CreateHttpResponse( - net::HTTP_BAD_REQUEST, - "PSM RLWE query request must contain queries field"); + const auto* test_case = + FindQueryTestCase(*test_data_, rlwe_request.query_request()); + if (!test_case) { + return CreateHttpResponse(net::HTTP_BAD_REQUEST, + "PSM RLWE query request not as expected"); } - auto* pir_response = psm_response->mutable_rlwe_response() - ->mutable_query_response() - ->add_pir_responses(); - const auto& encrypted_id = - rlwe_request.query_request().queries(0).queried_encrypted_id(); - pir_response->set_queried_encrypted_id(encrypted_id); - pir_response->mutable_pir_response()->set_plaintext_entry_size( - base::Contains(kPsmMembershipEncryptedTestIds, encrypted_id) - ? kPirResponseHasMembership - : kPirResponseHasNoMembership); + *psm_response->mutable_rlwe_response()->mutable_query_response() = + test_case->query_response(); } else { return CreateHttpResponse( net::HTTP_BAD_REQUEST,
diff --git a/components/policy/test_support/request_handler_for_psm_auto_enrollment.h b/components/policy/test_support/request_handler_for_psm_auto_enrollment.h index 3effa4e..6e85cd6 100644 --- a/components/policy/test_support/request_handler_for_psm_auto_enrollment.h +++ b/components/policy/test_support/request_handler_for_psm_auto_enrollment.h
@@ -7,16 +7,19 @@ #include "components/policy/test_support/embedded_policy_test_server.h" +#include <memory> + +namespace private_membership::rlwe { +class PrivateMembershipRlweClientRegressionTestData; +} namespace policy { // Handler for request type `enterprise_psm_check`. class RequestHandlerForPsmAutoEnrollment : public EmbeddedPolicyTestServer::RequestHandler { public: - enum PirResponse { - kPirResponseHasMembership = 1, - kPirResponseHasNoMembership = 2, - }; + using RlweTestData = + private_membership::rlwe::PrivateMembershipRlweClientRegressionTestData; explicit RequestHandlerForPsmAutoEnrollment(EmbeddedPolicyTestServer* parent); RequestHandlerForPsmAutoEnrollment( @@ -29,6 +32,12 @@ std::string RequestType() override; std::unique_ptr<net::test_server::HttpResponse> HandleRequest( const net::test_server::HttpRequest& request) override; + + // Required for unit tests + static std::unique_ptr<RlweTestData> LoadTestData(); + + private: + std::unique_ptr<RlweTestData> test_data_; }; } // namespace policy
diff --git a/components/policy/test_support/request_handler_for_psm_auto_enrollment_unittest.cc b/components/policy/test_support/request_handler_for_psm_auto_enrollment_unittest.cc index ddf1127..885d723 100644 --- a/components/policy/test_support/request_handler_for_psm_auto_enrollment_unittest.cc +++ b/components/policy/test_support/request_handler_for_psm_auto_enrollment_unittest.cc
@@ -3,16 +3,14 @@ // found in the LICENSE file. #include "components/policy/test_support/request_handler_for_psm_auto_enrollment.h" -#include "base/strings/strcat.h" + #include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/test_support/client_storage.h" #include "components/policy/test_support/embedded_policy_test_server_test_base.h" -#include "components/policy/test_support/policy_storage.h" -#include "components/policy/test_support/request_handler_for_register_browser.h" #include "device_management_backend.pb.h" #include "net/http/http_status_code.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/private_membership/src/internal/testing/regression_test_data/regression_test_data.pb.h" namespace em = enterprise_management; @@ -21,8 +19,6 @@ namespace { constexpr char kDeviceId[] = "fake_device_id"; -constexpr char kEncryptedId1[] = "fake/ecrypted-id"; -constexpr char kEncryptedId2[] = "54455354/111111"; } // namespace @@ -42,108 +38,87 @@ } }; -TEST_F(RequestHandlerForPsmAutoEnrollmentTest, HandleRequest_OprfRequest) { +class RequestHandlerForPsmAutoEnrollmentTestWithCase + : public RequestHandlerForPsmAutoEnrollmentTest, + public testing::WithParamInterface</*test_index=*/int> {}; + +TEST_P(RequestHandlerForPsmAutoEnrollmentTestWithCase, GoodOprfRequest) { + const auto test_data = RequestHandlerForPsmAutoEnrollment::LoadTestData(); + ASSERT_TRUE(test_data); + const auto& test_case = test_data->test_cases(GetParam()); em::DeviceManagementRequest device_management_request; - em::PrivateSetMembershipRequest* request = - device_management_request.mutable_private_set_membership_request(); - request->mutable_rlwe_request()->mutable_oprf_request()->add_encrypted_ids( - kEncryptedId1); + *device_management_request.mutable_private_set_membership_request() + ->mutable_rlwe_request() + ->mutable_oprf_request() = test_case.expected_oprf_request(); SetPayload(device_management_request); StartRequestAndWait(); EXPECT_EQ(GetResponseCode(), net::HTTP_OK); ASSERT_TRUE(HasResponseBody()); - auto response = GetDeviceManagementResponse(); - ASSERT_EQ(response.private_set_membership_response() - .rlwe_response() - .oprf_response() - .doubly_encrypted_ids_size(), - 1); + const auto response = GetDeviceManagementResponse(); EXPECT_EQ(response.private_set_membership_response() .rlwe_response() .oprf_response() - .doubly_encrypted_ids(0) - .queried_encrypted_id(), - kEncryptedId1); + .SerializeAsString(), + test_case.oprf_response().SerializeAsString()); } -TEST_F(RequestHandlerForPsmAutoEnrollmentTest, - HandleRequest_QueryRequestNoMembership) { +TEST_P(RequestHandlerForPsmAutoEnrollmentTestWithCase, GoodQueryRequest) { + const auto test_data = RequestHandlerForPsmAutoEnrollment::LoadTestData(); + ASSERT_TRUE(test_data); + const auto& test_case = test_data->test_cases(GetParam()); em::DeviceManagementRequest device_management_request; - em::PrivateSetMembershipRequest* request = - device_management_request.mutable_private_set_membership_request(); - request->mutable_rlwe_request() - ->mutable_query_request() - ->add_queries() - ->set_queried_encrypted_id(kEncryptedId1); + *device_management_request.mutable_private_set_membership_request() + ->mutable_rlwe_request() + ->mutable_query_request() = test_case.expected_query_request(); SetPayload(device_management_request); StartRequestAndWait(); EXPECT_EQ(GetResponseCode(), net::HTTP_OK); ASSERT_TRUE(HasResponseBody()); - auto response = GetDeviceManagementResponse(); - ASSERT_EQ(response.private_set_membership_response() - .rlwe_response() - .query_response() - .pir_responses_size(), - 1); + const auto response = GetDeviceManagementResponse(); EXPECT_EQ(response.private_set_membership_response() .rlwe_response() .query_response() - .pir_responses(0) - .queried_encrypted_id(), - kEncryptedId1); - EXPECT_EQ(response.private_set_membership_response() - .rlwe_response() - .query_response() - .pir_responses(0) - .pir_response() - .plaintext_entry_size(), - RequestHandlerForPsmAutoEnrollment::kPirResponseHasNoMembership); + .SerializeAsString(), + test_case.query_response().SerializeAsString()); } -TEST_F(RequestHandlerForPsmAutoEnrollmentTest, - HandleRequest_QueryRequestHasMembership) { +INSTANTIATE_TEST_SUITE_P( + Each, + RequestHandlerForPsmAutoEnrollmentTestWithCase, + testing::Range( + 0, + RequestHandlerForPsmAutoEnrollment::LoadTestData()->test_cases_size())); + +TEST_F(RequestHandlerForPsmAutoEnrollmentTest, BadOprfRequest) { em::DeviceManagementRequest device_management_request; - em::PrivateSetMembershipRequest* request = - device_management_request.mutable_private_set_membership_request(); - request->mutable_rlwe_request() - ->mutable_query_request() - ->add_queries() - ->set_queried_encrypted_id(kEncryptedId2); + *device_management_request.mutable_private_set_membership_request() + ->mutable_rlwe_request() + ->mutable_oprf_request() = {}; SetPayload(device_management_request); StartRequestAndWait(); - EXPECT_EQ(GetResponseCode(), net::HTTP_OK); - ASSERT_TRUE(HasResponseBody()); - auto response = GetDeviceManagementResponse(); - ASSERT_EQ(response.private_set_membership_response() - .rlwe_response() - .query_response() - .pir_responses_size(), - 1); - EXPECT_EQ(response.private_set_membership_response() - .rlwe_response() - .query_response() - .pir_responses(0) - .queried_encrypted_id(), - kEncryptedId2); - EXPECT_EQ(response.private_set_membership_response() - .rlwe_response() - .query_response() - .pir_responses(0) - .pir_response() - .plaintext_entry_size(), - RequestHandlerForPsmAutoEnrollment::kPirResponseHasMembership); + EXPECT_EQ(GetResponseCode(), net::HTTP_BAD_REQUEST); } -TEST_F(RequestHandlerForPsmAutoEnrollmentTest, - HandleRequest_MissingRequestFields) { +TEST_F(RequestHandlerForPsmAutoEnrollmentTest, BadQueryRequest) { em::DeviceManagementRequest device_management_request; - device_management_request.mutable_private_set_membership_request(); + *device_management_request.mutable_private_set_membership_request() + ->mutable_rlwe_request() + ->mutable_oprf_request() = {}; + SetPayload(device_management_request); + + StartRequestAndWait(); + + EXPECT_EQ(GetResponseCode(), net::HTTP_BAD_REQUEST); +} + +TEST_F(RequestHandlerForPsmAutoEnrollmentTest, BadRequest) { + em::DeviceManagementRequest device_management_request; SetPayload(device_management_request); StartRequestAndWait();
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.h b/components/privacy_sandbox/privacy_sandbox_settings.h index 441a11d..d2558c9 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings.h +++ b/components/privacy_sandbox/privacy_sandbox_settings.h
@@ -55,6 +55,11 @@ // Whether the current profile is Incognito or not. For Incognito, the // privacy sandbox APIs are restricted. virtual bool IsIncognitoProfile() const = 0; + + // Whether there is an appropriate level of consent for the Topics API. + // When this returns false, access control functions for Topics will + // return as not allowed. + virtual bool HasAppropriateTopicsConsent() const = 0; }; // Returns whether the Topics API is allowed at all. If false, Topics API
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc index a6b914aa..c1c3539 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings_impl.cc +++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.cc
@@ -103,8 +103,21 @@ PrivacySandboxSettingsImpl::Status PrivacySandboxSettingsImpl::GetM1TopicAllowedStatus() const { - return GetM1PrivacySandboxApiEnabledStatus( + auto control_status = GetM1PrivacySandboxApiEnabledStatus( prefs::kPrivacySandboxM1TopicsEnabled); + auto has_appropriate_consent = delegate_->HasAppropriateTopicsConsent(); + + // If `control_status` indicates that Topics is allowed, then + // `has_appropriate_consent` should be true, as there is no pathway for a user + // to enable Topics controls without also granting consent. The inverse does + // not hold, as an extension or policy may disable Topics, without necessarily + // revoking user consent. + if (control_status == Status::kAllowed && !has_appropriate_consent) { + // This status will be recorded via UMA, and is indicative of an error. + return Status::kMismatchedConsent; + } + + return control_status; } bool PrivacySandboxSettingsImpl::IsTopicsAllowed() const {
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl.h b/components/privacy_sandbox/privacy_sandbox_settings_impl.h index 11d64a2..c1641b5 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings_impl.h +++ b/components/privacy_sandbox/privacy_sandbox_settings_impl.h
@@ -105,7 +105,8 @@ kIncognitoProfile, kApisDisabled, kSiteDataAccessBlocked, - kMaxValue = kSiteDataAccessBlocked, + kMismatchedConsent, + kMaxValue = kMismatchedConsent, }; static bool IsAllowed(Status status);
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc index 63c9987..425b89e 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc +++ b/components/privacy_sandbox/privacy_sandbox_settings_impl_unittest.cc
@@ -49,6 +49,8 @@ constexpr auto kSiteDataUserExceptions = StateKey::kSiteDataUserExceptions; constexpr auto kIsIncognito = StateKey::kIsIncognito; constexpr auto kIsRestrictedAccount = StateKey::kIsRestrictedAccount; +constexpr auto kHasAppropriateTopicsConsent = + StateKey::kHasAppropriateTopicsConsent; // using enum privacy_sandbox_test_util::InputKey; using privacy_sandbox_test_util::InputKey; @@ -152,6 +154,8 @@ mock_delegate()->SetUpIsPrivacySandboxRestrictedResponse( /*restricted=*/false); mock_delegate()->SetUpIsIncognitoProfileResponse(/*incognito=*/false); + mock_delegate()->SetUpHasAppropriateTopicsConsentResponse( + /*has_appropriate_consent=*/true); } privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate* @@ -1477,4 +1481,64 @@ TestOutput{{kIsPrivateAggregationAllowed, false}}); } +TEST_F(PrivacySandboxSettingsM1Test, NoAppropriateTopicsConsent) { + // Confirm that when appropriate Topics consent is missing, Topics is disabled + // while other APIs are unaffected. + RunTestCase( + TestState{{MultipleStateKeys{kM1TopicsEnabledUserPrefValue, + kM1FledgeEnabledUserPrefValue, + kM1AdMeasurementEnabledUserPrefValue}, + true}, + {kHasAppropriateTopicsConsent, false}}, + TestInput{ + {kTopFrameOrigin, url::Origin::Create(GURL("https://top-frame.com"))}, + {kTopicsURL, GURL("https://embedded.com")}, + {MultipleInputKeys{kFledgeAuctionPartyOrigin, + kAdMeasurementReportingOrigin, kAccessingOrigin}, + url::Origin::Create(GURL("https://embedded.com"))}, + {kAdMeasurementSourceOrigin, + url::Origin::Create(GURL("https://source-origin.com"))}, + {kAdMeasurementDestinationOrigin, + url::Origin::Create(GURL("https://dest-origin.com"))}}, + TestOutput{ + {MultipleOutputKeys{ + kIsFledgeAllowed, kIsAttributionReportingAllowed, + kMaySendAttributionReport, kIsSharedStorageAllowed, + kIsSharedStorageSelectURLAllowed, kIsPrivateAggregationAllowed}, + true}, + {MultipleOutputKeys{kIsTopicsAllowed, kIsTopicsAllowedForContext}, + false}, + {MultipleOutputKeys{ + kIsFledgeAllowedMetric, kIsAttributionReportingAllowedMetric, + kMaySendAttributionReportMetric, kIsSharedStorageAllowedMetric, + kIsSharedStorageSelectURLAllowedMetric, + kIsPrivateAggregationAllowedMetric}, + static_cast<int>(Status::kAllowed)}, + {MultipleOutputKeys{ + kIsTopicsAllowedMetric, + kIsTopicsAllowedForContextMetric, + }, + static_cast<int>(Status::kMismatchedConsent)}}); +} + +TEST_F(PrivacySandboxSettingsM1Test, TopicsConsentStatus) { + // Confirm that if Topics is already disabled, and there is no appropriate + // consent, the recorded status reflects that Topics is already disabled. + RunTestCase( + TestState{{kM1TopicsEnabledUserPrefValue, false}, + {kHasAppropriateTopicsConsent, false}}, + TestInput{ + {kTopFrameOrigin, url::Origin::Create(GURL("https://top-frame.com"))}, + {kTopicsURL, GURL("https://embedded.com")}, + }, + TestOutput{ + {MultipleOutputKeys{kIsTopicsAllowed, kIsTopicsAllowedForContext}, + false}, + {MultipleOutputKeys{ + kIsTopicsAllowedMetric, + kIsTopicsAllowedForContextMetric, + }, + static_cast<int>(Status::kApisDisabled)}}); +} + } // namespace privacy_sandbox
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util.cc b/components/privacy_sandbox/privacy_sandbox_test_util.cc index 6d1ce177..70eb423 100644 --- a/components/privacy_sandbox/privacy_sandbox_test_util.cc +++ b/components/privacy_sandbox/privacy_sandbox_test_util.cc
@@ -269,6 +269,12 @@ prefs::kPrivacySandboxM1AdMeasurementEnabled)); return; } + case (StateKey::kHasAppropriateTopicsConsent): { + SCOPED_TRACE("State Setup: Appropriate Topics Consent"); + mock_delegate->SetUpHasAppropriateTopicsConsentResponse( + GetItemValue<bool>(value)); + return; + } default: NOTREACHED(); }
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util.h b/components/privacy_sandbox/privacy_sandbox_test_util.h index e94ffd8c..f38f3d1 100644 --- a/components/privacy_sandbox/privacy_sandbox_test_util.h +++ b/components/privacy_sandbox/privacy_sandbox_test_util.h
@@ -68,8 +68,15 @@ }); } + void SetUpHasAppropriateTopicsConsentResponse(bool has_appropriate_consent) { + ON_CALL(*this, HasAppropriateTopicsConsent).WillByDefault([=]() { + return has_appropriate_consent; + }); + } + MOCK_METHOD(bool, IsPrivacySandboxRestricted, (), (const, override)); MOCK_METHOD(bool, IsIncognitoProfile, (), (const, override)); + MOCK_METHOD(bool, HasAppropriateTopicsConsent, (), (const, override)); }; // A declarative test case is a collection of key value pairs, which each define @@ -100,6 +107,7 @@ kM1TopicsDisabledByPolicy = 21, kM1FledgeDisabledByPolicy = 22, kM1AdMesaurementDisabledByPolicy = 23, + kHasAppropriateTopicsConsent = 24, }; // Defines the input to the functions under test.
diff --git a/components/privacy_sandbox_strings.grdp b/components/privacy_sandbox_strings.grdp index bd321382..c778b41 100644 --- a/components/privacy_sandbox_strings.grdp +++ b/components/privacy_sandbox_strings.grdp
@@ -237,41 +237,41 @@ <message name="IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3" desc="Paragraph 3 of 3 on the Learn more about ad topics page. * 'auto-deletes': this could also read 'Chrome deletes...' We included the 'auto' to reinforce that this is part of a system and the deletion is done regularly." formatter_data="android_java"> Chrome auto-deletes topics that are older than 4 weeks. As you keep browsing, a topic might reappear on the list. Or you can block topics you don’t want Chrome to share with sites. </message> - <message name="IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL" translateable="false" desc="Footer for the Topics preference page."> - Topics footer. Quisque eu auctor purus, id tempus nulla. Pellentesque porta orci purus. Donec dictum, fledge settings, cookie settings, sit amet molestie quam arcu id urna. Donec vulputate dui ut lorem egestas, ac sollicitudin metus fermentum. + <message name="IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL" desc="This footer helps the user understand that this setting is just one signal among others that affect whether this user sees personalized ads on a site. We define 'personalize' as 'when Google provides recommendations and other content for users based on their data'. At a high level, there are 4 things that affect whether an ad is personalized in this context: * 'this setting' refers to the 'Ad topics' setting. The user is on this page. * 'Site-suggested ads': this is a link to the other new ad setting Chrome is launching and that sites can use to personalize ads a user sees. * 'cookie settings': this is a link to the cookies control section in Chrome settings. The Privacy Sandbox project deprecates third-party cookies, but it's a process, and we're launching new functionality that will replace important functionality of cookies. Until third-party cookies are deprecated, the two systems remain active in Chrome. * 'site you're viewing personalizes ads': When a user engages with a site, Chrome has no control over whether that site shows the user personalized ads. Imagine you visit www.interesting-site.com and they know a lot about you already based on previous visits. They can personalize content and ads to you if they like. They can use an ad-serving product, like Facebook or Google Ads to deliver personalized ads. They can also use the new Privacy Sandbox APIs (if they so choose) in order to get more information about the user that could be helpful to them in order to personalize ads. Those 2 APIs (settings, from the user's perspective), are 'Ad topics' and 'Site-suggested ads'."> + As you browse, whether an ad you see is personalized depends on this setting, Site-suggested ads, your cookie settings, and if the site you’re viewing personalizes ads </message> <!-- Privacy Sandbox v4 - Topics Consent Details --> <!-- TODO(crbug.com/1378703) - Update and mark translateable. --> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL" translateable="false"> - Consent Status: + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL" desc="Label for the text which displays the state of the user's Topics consent"> + Consent status: </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL" translateable="false"> - Consent Last Update Time: + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL" desc="Label for the text which displays the time the user's Topics consent was last updated"> + Consent last updated: </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL" translateable="false"> - Consent Last Update Source: + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL" desc="Label for the text which displays the source of the last update to the users topics consent"> + Source of last consent update: </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL" translateable="false"> - Consent Last Update Text: + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL" desc="Label for the text which captures what was presented to the user during their last consent decision"> + Text presented to user: </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS" translateable="false"> - Chrome Settings + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS" desc="Text presented when the user's last Topics consent location was Chrome settings"> + Chrome settings </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT" translateable="false"> - Default Value + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT" desc="Text presented when the user hasn't made a consent descision"> + No consent decision </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION" translateable="false"> - Blocking Confirmation Moment + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION" desc="Text presented when the user's last Topics consent location was a confirmation dialog"> + Confirmation dialog </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE" desc="Text presented when a user has a currently active Topics consent"> Active </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE" desc="Text presented when a user has a currently inactive Topics consent"> Inactive </message> - <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED" translateable="false"> - Not Required + <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED" desc="Text presented when a user does not require a consent for Topics"> + Not required </message>
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE.png.sha1 new file mode 100644 index 0000000..08da55988 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE.png.sha1
@@ -0,0 +1 @@ +0d8aa25c42a00cc1f385ae3eff2cbb9bb4d0896a \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED.png.sha1 new file mode 100644 index 0000000..b995a7d --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED.png.sha1
@@ -0,0 +1 @@ +82dbc17c1e11b2ac348d4f799f9a9336050d9c07 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION.png.sha1 new file mode 100644 index 0000000..08da55988 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION.png.sha1
@@ -0,0 +1 @@ +0d8aa25c42a00cc1f385ae3eff2cbb9bb4d0896a \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT.png.sha1 new file mode 100644 index 0000000..b995a7d --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT.png.sha1
@@ -0,0 +1 @@ +82dbc17c1e11b2ac348d4f799f9a9336050d9c07 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS.png.sha1 new file mode 100644 index 0000000..6754264 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS.png.sha1
@@ -0,0 +1 @@ +2438c5f92971d339fc679e7ef1525e5ee90ed8c0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grdp/IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL.png.sha1 b/components/privacy_sandbox_strings_grdp/IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL.png.sha1 new file mode 100644 index 0000000..195ac90 --- /dev/null +++ b/components/privacy_sandbox_strings_grdp/IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL.png.sha1
@@ -0,0 +1 @@ +86b8ff6621343b6eacf8f294ae9e8ba1751218fd \ No newline at end of file
diff --git a/components/remote_cocoa/app_shim/BUILD.gn b/components/remote_cocoa/app_shim/BUILD.gn index 1adfddd..7f9176a 100644 --- a/components/remote_cocoa/app_shim/BUILD.gn +++ b/components/remote_cocoa/app_shim/BUILD.gn
@@ -55,8 +55,6 @@ "views_nswindow_delegate.mm", "views_scrollbar_bridge.h", "views_scrollbar_bridge.mm", - "window_controls_overlay_nsview.h", - "window_controls_overlay_nsview.mm", "window_move_loop.h", "window_move_loop.mm", "window_touch_bar_delegate.h",
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h index b07e4751..64c67f26 100644 --- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h +++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
@@ -38,7 +38,6 @@ @class ModalShowAnimationWithLayer; @class NativeWidgetMacNSWindow; @class ViewsNSWindowDelegate; -@class WindowControlsOverlayNSView; namespace views { namespace test { @@ -277,13 +276,6 @@ void RedispatchKeyEvent( const std::vector<uint8_t>& native_event_data) override; void SetLocalEventMonitorEnabled(bool enable) override; - void CreateWindowControlsOverlayNSView( - const mojom::WindowControlsOverlayNSViewType overlay_type) override; - void UpdateWindowControlsOverlayNSView( - const gfx::Rect& bounds, - const mojom::WindowControlsOverlayNSViewType overlay_type) override; - void RemoveWindowControlsOverlayNSView( - const mojom::WindowControlsOverlayNSViewType overlay_type) override; void SetCursor(const ui::Cursor& cursor) override; void EnableImmersiveFullscreen( uint64_t fullscreen_overlay_widget_id, @@ -371,14 +363,6 @@ bool is_translucent_window_ = false; id key_down_event_monitor_ = nil; - // Intended for PWAs with window controls overlay display override. These two - // NSViews are added on top of the non client area to route events to the - // BridgedContentView instead of the RenderWidgetHostView. - base::scoped_nsobject<WindowControlsOverlayNSView> - caption_buttons_overlay_nsview_; - base::scoped_nsobject<WindowControlsOverlayNSView> - web_app_frame_toolbar_overlay_nsview_; - raw_ptr<NativeWidgetNSWindowBridge> parent_ = nullptr; // Weak. If non-null, owns this. std::vector<NativeWidgetNSWindowBridge*> child_windows_;
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm index bb0bb337..8206a7f 100644 --- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm +++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -32,7 +32,6 @@ #import "components/remote_cocoa/app_shim/native_widget_ns_window_host_helper.h" #include "components/remote_cocoa/app_shim/select_file_dialog_bridge.h" #import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" -#import "components/remote_cocoa/app_shim/window_controls_overlay_nsview.h" #import "components/remote_cocoa/app_shim/window_move_loop.h" #include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -1161,49 +1160,6 @@ return [[window_ commandDispatcher] redispatchKeyEvent:event]; } -void NativeWidgetNSWindowBridge::CreateWindowControlsOverlayNSView( - const mojom::WindowControlsOverlayNSViewType overlay_type) { - switch (overlay_type) { - case mojom::WindowControlsOverlayNSViewType::kCaptionButtonContainer: - caption_buttons_overlay_nsview_.reset( - [[WindowControlsOverlayNSView alloc] initWithBridge:this]); - [bridged_view_ addSubview:caption_buttons_overlay_nsview_]; - break; - case mojom::WindowControlsOverlayNSViewType::kWebAppFrameToolbar: - web_app_frame_toolbar_overlay_nsview_.reset( - [[WindowControlsOverlayNSView alloc] initWithBridge:this]); - [bridged_view_ addSubview:web_app_frame_toolbar_overlay_nsview_]; - break; - } -} - -void NativeWidgetNSWindowBridge::UpdateWindowControlsOverlayNSView( - const gfx::Rect& bounds, - const mojom::WindowControlsOverlayNSViewType overlay_type) { - switch (overlay_type) { - case mojom::WindowControlsOverlayNSViewType::kCaptionButtonContainer: - [caption_buttons_overlay_nsview_ updateBounds:bounds]; - break; - case mojom::WindowControlsOverlayNSViewType::kWebAppFrameToolbar: - [web_app_frame_toolbar_overlay_nsview_ updateBounds:bounds]; - break; - } -} - -void NativeWidgetNSWindowBridge::RemoveWindowControlsOverlayNSView( - const mojom::WindowControlsOverlayNSViewType overlay_type) { - switch (overlay_type) { - case mojom::WindowControlsOverlayNSViewType::kCaptionButtonContainer: - [caption_buttons_overlay_nsview_ removeFromSuperview]; - caption_buttons_overlay_nsview_.reset(); - break; - case mojom::WindowControlsOverlayNSViewType::kWebAppFrameToolbar: - [web_app_frame_toolbar_overlay_nsview_ removeFromSuperview]; - web_app_frame_toolbar_overlay_nsview_.reset(); - break; - } -} - NSWindow* NativeWidgetNSWindowBridge::ns_window() { return window_.get(); }
diff --git a/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h b/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h deleted file mode 100644 index 1d62f8a..0000000 --- a/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h +++ /dev/null
@@ -1,31 +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 COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_ -#define COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_ - -#import <Cocoa/Cocoa.h> - -#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" -#include "ui/gfx/geometry/rect.h" - -namespace remote_cocoa { -class NativeWidgetNSWindowBridge; -} // namespace remote_cocoa - -REMOTE_COCOA_APP_SHIM_EXPORT -@interface WindowControlsOverlayNSView : NSView { - @private - // Weak. - remote_cocoa::NativeWidgetNSWindowBridge* _bridge; -} -@property(readonly, nonatomic) remote_cocoa::NativeWidgetNSWindowBridge* bridge; - -- (instancetype)initWithBridge: - (remote_cocoa::NativeWidgetNSWindowBridge*)bridge; - -- (void)updateBounds:(gfx::Rect)bounds; -@end - -#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_
diff --git a/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm b/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm deleted file mode 100644 index e125614..0000000 --- a/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm +++ /dev/null
@@ -1,36 +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. - -#import "components/remote_cocoa/app_shim/window_controls_overlay_nsview.h" - -@implementation WindowControlsOverlayNSView - -@synthesize bridge = _bridge; - -- (instancetype)initWithBridge: - (remote_cocoa::NativeWidgetNSWindowBridge*)bridge { - if ((self = [super initWithFrame:NSZeroRect])) { - _bridge = bridge; - } - return self; -} - -- (NSView*)hitTest:(NSPoint)point { - NSPoint pointInView = [self convertPoint:point fromView:self.superview]; - // This NSView is directly above NonClientView. We want to route events - // to BridgedContentView so the right view in NonClientArea can consume them - // instead of going to RenderWidgetHostView. - if (NSPointInRect(pointInView, self.visibleRect)) - return self.superview; - return [super hitTest:point]; -} - -- (void)updateBounds:(gfx::Rect)bounds { - NSRect frameRect = bounds.ToCGRect(); - frameRect.origin.y = NSHeight(self.superview.bounds) - frameRect.origin.y - - NSHeight(frameRect); - [self setFrame:frameRect]; -} - -@end
diff --git a/components/remote_cocoa/common/native_widget_ns_window.mojom b/components/remote_cocoa/common/native_widget_ns_window.mojom index 07016bb..93a6230 100644 --- a/components/remote_cocoa/common/native_widget_ns_window.mojom +++ b/components/remote_cocoa/common/native_widget_ns_window.mojom
@@ -86,11 +86,6 @@ bool is_tooltip; }; -enum WindowControlsOverlayNSViewType { - kCaptionButtonContainer, - kWebAppFrameToolbar, -}; - // The visibility style of the toolbar in immersive fullscreen. enum ToolbarVisibilityStyle { // No toolbar. Used for content fullscreen. @@ -256,21 +251,6 @@ // Enable or disable this widget's local event monitor. SetLocalEventMonitorEnabled(bool enabled); - // Add the overlay NSView for a PWA with window controls overlay - // display override given a |overlay_type|. - CreateWindowControlsOverlayNSView( - WindowControlsOverlayNSViewType overlay_type); - - // Update the overlay NSView with |bounds| for a PWA with window controls - // overlay display override for a |overlay_type|. - UpdateWindowControlsOverlayNSView( - gfx.mojom.Rect bounds, WindowControlsOverlayNSViewType overlay_type); - - // Remove the overlay NSView with |bounds| for a PWA with window controls - // overlay display override for a |overlay_type|. - RemoveWindowControlsOverlayNSView( - WindowControlsOverlayNSViewType overlay_type); - // Set the cursor type to display. SetCursor(ui.mojom.Cursor cursor);
diff --git a/components/reporting/health/health_module.h b/components/reporting/health/health_module.h index c8c1b34..8d98b6a 100644 --- a/components/reporting/health/health_module.h +++ b/components/reporting/health/health_module.h
@@ -65,7 +65,7 @@ void PostHealthRecord(HealthDataHistory history); // Gets health data and send to |cb|. - void GetHealthData(base::OnceCallback<void(const ERPHealthData)> cb); + void GetHealthData(base::OnceCallback<void(ERPHealthData)> cb); protected: // Constructor can only be called by |Create| factory method.
diff --git a/components/safe_browsing/content/browser/BUILD.gn b/components/safe_browsing/content/browser/BUILD.gn index fcb8363..7c9ed1b8 100644 --- a/components/safe_browsing/content/browser/BUILD.gn +++ b/components/safe_browsing/content/browser/BUILD.gn
@@ -96,6 +96,7 @@ "//components/safe_browsing/core/browser:referrer_chain_provider", "//components/safe_browsing/core/browser:verdict_cache_manager", "//components/safe_browsing/core/browser/db:database_manager", + "//components/safe_browsing/core/browser/hashprefix_realtime:hash_realtime_service", "//components/safe_browsing/core/browser/realtime:policy_engine", "//components/safe_browsing/core/browser/realtime:url_lookup_service_base", "//components/safe_browsing/core/common:common",
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc index 983cafe..611c45e 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle.cc +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.cc
@@ -7,17 +7,22 @@ #include "base/check_op.h" #include "base/functional/bind.h" #include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" #include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h" +#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" #include "components/safe_browsing/core/browser/realtime/policy_engine.h" #include "components/safe_browsing/core/browser/realtime/url_lookup_service_base.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h" #include "components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h" #include "components/safe_browsing/core/browser/url_checker_delegate.h" +#include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/safebrowsing_constants.h" #include "components/safe_browsing/core/common/utils.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/web_contents.h" +#include "net/base/load_flags.h" #include "net/log/net_log_event_type.h" #include "net/url_request/redirect_info.h" #include "services/network/public/cpp/resource_request.h" @@ -63,7 +68,9 @@ bool can_check_db, bool can_check_high_confidence_allowlist, std::string url_lookup_service_metric_suffix, - base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service) + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, + base::WeakPtr<HashRealTimeService> hash_realtime_service, + bool is_mechanism_experiment_allowed) : delegate_getter_(std::move(delegate_getter)), frame_tree_node_id_(frame_tree_node_id), web_contents_getter_(web_contents_getter), @@ -75,6 +82,8 @@ can_check_high_confidence_allowlist), url_lookup_service_metric_suffix_(url_lookup_service_metric_suffix), url_lookup_service_(url_lookup_service), + hash_realtime_service_(hash_realtime_service), + is_mechanism_experiment_allowed_(is_mechanism_experiment_allowed), creation_time_(base::TimeTicks::Now()) { content::WebContents* contents = web_contents_getter_.Run(); if (!!contents) { @@ -86,6 +95,10 @@ base::UmaHistogramMediumTimes( "SafeBrowsing.BrowserThrottle.CheckerOnIOLifetime", base::TimeTicks::Now() - creation_time_); + if (mechanism_experimenter_) { + mechanism_experimenter_ + ->OnBrowserUrlLoaderThrottleCheckerOnIODestructed(); + } } // Starts the initial safe browsing check. This check and future checks may be @@ -114,6 +127,12 @@ return; } + if (is_mechanism_experiment_allowed_ && + request_destination == network::mojom::RequestDestination::kDocument && + !(load_flags & net::LOAD_PREFETCH)) { + mechanism_experimenter_ = + base::MakeRefCounted<SafeBrowsingLookupMechanismExperimenter>(); + } url_checker_ = std::make_unique<SafeBrowsingUrlCheckerImpl>( headers, load_flags, request_destination, has_user_gesture, url_checker_delegate, web_contents_getter_, @@ -122,7 +141,8 @@ can_rt_check_subresource_url_, can_check_db_, can_check_high_confidence_allowlist_, url_lookup_service_metric_suffix_, last_committed_url_, content::GetUIThreadTaskRunner({}), - url_lookup_service_, WebUIInfoSingleton::GetInstance()); + url_lookup_service_, WebUIInfoSingleton::GetInstance(), + hash_realtime_service_, mechanism_experimenter_); CheckUrl(url, method); } @@ -144,6 +164,12 @@ base::Unretained(this))); } + void LogWillProcessResponseTime(base::TimeTicks reached_time) { + if (mechanism_experimenter_) { + mechanism_experimenter_->OnWillProcessResponseReached(reached_time); + } + } + private: // If |slow_check_notifier| is non-null, it indicates that a "slow check" is // ongoing, i.e., the URL may be unsafe and a more time-consuming process is @@ -191,6 +217,8 @@ std::unique_ptr<SafeBrowsingUrlCheckerImpl> url_checker_; int frame_tree_node_id_; + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter_; base::RepeatingCallback<content::WebContents*()> web_contents_getter_; bool skip_checks_ = false; base::WeakPtr<BrowserURLLoaderThrottle> throttle_; @@ -201,6 +229,8 @@ std::string url_lookup_service_metric_suffix_; GURL last_committed_url_; base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_; + base::WeakPtr<HashRealTimeService> hash_realtime_service_; + bool is_mechanism_experiment_allowed_ = false; base::TimeTicks creation_time_; }; @@ -209,18 +239,20 @@ GetDelegateCallback delegate_getter, const base::RepeatingCallback<content::WebContents*()>& web_contents_getter, int frame_tree_node_id, - base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service) { + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, + base::WeakPtr<HashRealTimeService> hash_realtime_service) { return base::WrapUnique<BrowserURLLoaderThrottle>( new BrowserURLLoaderThrottle(std::move(delegate_getter), web_contents_getter, frame_tree_node_id, - url_lookup_service)); + url_lookup_service, hash_realtime_service)); } BrowserURLLoaderThrottle::BrowserURLLoaderThrottle( GetDelegateCallback delegate_getter, const base::RepeatingCallback<content::WebContents*()>& web_contents_getter, int frame_tree_node_id, - base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service) { + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, + base::WeakPtr<HashRealTimeService> hash_realtime_service) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Decide whether to do real time URL lookups or not. @@ -231,6 +263,18 @@ bool can_rt_check_subresource_url = url_lookup_service && url_lookup_service->CanCheckSubresourceURL(); +// This BUILDFLAG check is not strictly necessary because the feature should +// only be enabled for Desktop. This check is included only as a precaution and +// for clarity. +#if BUILDFLAG(FULL_SAFE_BROWSING) + bool is_mechanism_experiment_allowed = + hash_realtime_service && + hash_realtime_service->IsEnhancedProtectionEnabled() && + base::FeatureList::IsEnabled(kSafeBrowsingLookupMechanismExperiment); +#else + bool is_mechanism_experiment_allowed = false; +#endif + // Decide whether safe browsing database can be checked. // If url_lookup_service is null, safe browsing database should be checked by // default. @@ -250,7 +294,8 @@ weak_factory_.GetWeakPtr(), real_time_lookup_enabled_, can_rt_check_subresource_url, can_check_db, can_check_high_confidence_allowlist, url_lookup_service_metric_suffix_, - url_lookup_service); + url_lookup_service, hash_realtime_service, + is_mechanism_experiment_allowed); } BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() { @@ -307,8 +352,9 @@ return; } - if (skip_checks_) + if (skip_checks_) { return; + } pending_checks_++; content::GetIOThreadTaskRunner({})->PostTask( @@ -328,6 +374,12 @@ "SafeBrowsing.BrowserThrottle.WillProcessResponseCount", will_process_response_count_); + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + &BrowserURLLoaderThrottle::CheckerOnIO::LogWillProcessResponseTime, + io_checker_->AsWeakPtr(), base::TimeTicks::Now())); + if (blocked_) { // OnCheckUrlResult() has set |blocked_| to true and called // |delegate_->CancelWithError|, but this method is called before the @@ -347,8 +399,9 @@ is_start_request_called_ = false; } - if (check_completed) + if (check_completed) { return; + } DCHECK(!deferred_); deferred_ = true; @@ -384,8 +437,9 @@ // resumed), record the total delay. if (!proceed || pending_checks_ == 0) { // If the resource load is currently deferred, there is a delay. - if (deferred_) + if (deferred_) { total_delay_ = base::TimeTicks::Now() - defer_start_time_; + } std::string url_check_type = (did_perform_real_time_check) ? base::StrCat({url_lookup_service_metric_suffix_, kFullURLLookup}) @@ -394,8 +448,9 @@ } if (proceed) { - if (pending_slow_checks_ == 0 && slow_check) + if (pending_slow_checks_ == 0 && slow_check) { delegate_->ResumeReadingBodyFromNet(); + } if (pending_checks_ == 0 && deferred_) { deferred_ = false; @@ -425,8 +480,9 @@ skip_checks_ = true; pending_checks_--; - if (pending_checks_ == 0 && deferred_) + if (pending_checks_ == 0 && deferred_) { delegate_->Resume(); + } } void BrowserURLLoaderThrottle::NotifySlowCheck() { @@ -441,8 +497,9 @@ // For real time Safe Browsing checks, we continue reading the response body // but, similar to hash-based checks, do not process it until we know it is // SAFE. - if (pending_slow_checks_ == 1) + if (pending_slow_checks_ == 1) { delegate_->PauseReadingBodyFromNet(); + } } void BrowserURLLoaderThrottle::DeleteCheckerOnIO() {
diff --git a/components/safe_browsing/content/browser/browser_url_loader_throttle.h b/components/safe_browsing/content/browser/browser_url_loader_throttle.h index 15bb26e33..f6b48c1f 100644 --- a/components/safe_browsing/content/browser/browser_url_loader_throttle.h +++ b/components/safe_browsing/content/browser/browser_url_loader_throttle.h
@@ -28,6 +28,7 @@ class UrlCheckerDelegate; class RealTimeUrlLookupServiceBase; +class HashRealTimeService; // BrowserURLLoaderThrottle is used in the browser process to query // SafeBrowsing to determine whether a URL and also its redirect URLs are safe @@ -48,7 +49,8 @@ const base::RepeatingCallback<content::WebContents*()>& web_contents_getter, int frame_tree_node_id, - base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service); + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, + base::WeakPtr<HashRealTimeService> hash_realtime_service); BrowserURLLoaderThrottle(const BrowserURLLoaderThrottle&) = delete; BrowserURLLoaderThrottle& operator=(const BrowserURLLoaderThrottle&) = delete; @@ -91,7 +93,8 @@ const base::RepeatingCallback<content::WebContents*()>& web_contents_getter, int frame_tree_node_id, - base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service); + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, + base::WeakPtr<HashRealTimeService> hash_realtime_service); // |slow_check| indicates whether it reports the result of a slow check. // (Please see comments of CheckerOnIO::OnCheckUrlResult() for what slow check
diff --git a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc index 30788d4..2f7d481bb 100644 --- a/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc +++ b/components/safe_browsing/content/browser/mojo_safe_browsing_impl.cc
@@ -27,8 +27,9 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RenderFrameHost* render_frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); - if (!render_frame_host) + if (!render_frame_host) { return nullptr; + } return content::WebContents::FromRenderFrameHost(render_frame_host); } @@ -47,8 +48,9 @@ explicit CheckUrlCallbackWrapper(Callback callback) : callback_(std::move(callback)) {} ~CheckUrlCallbackWrapper() { - if (callback_) + if (callback_) { Run(mojo::NullReceiver(), true, false, false, false); + } } void Run(mojo::PendingReceiver<mojom::UrlCheckNotifier> slow_check_notifier, @@ -115,8 +117,9 @@ scoped_refptr<UrlCheckerDelegate> delegate = delegate_getter.Run(); - if (!resource_context || !delegate) + if (!resource_context || !delegate) { return; + } std::unique_ptr<MojoSafeBrowsingImpl> impl(new MojoSafeBrowsingImpl( std::move(delegate), render_process_id, resource_context)); @@ -161,7 +164,9 @@ // This is not called for frame resources, and real time URL checks currently // only support main frame resources. If we extend real time URL checks to // support non-main frames, we will need to provide the user preferences, - // url_lookup_service regarding real time lookup here. + // url_lookup_service regarding real time lookup here. If we extend + // hash-prefix real-time checks to support non-main frames, we will need to + // provide the hash_realtime_service_on_ui here. auto checker_impl = std::make_unique<SafeBrowsingUrlCheckerImpl>( headers, static_cast<int>(load_flags), request_destination, has_user_gesture, delegate_, @@ -174,7 +179,9 @@ /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/".None", /*last_committed_url=*/GURL(), content::GetUIThreadTaskRunner({}), - /*url_lookup_service=*/nullptr, WebUIInfoSingleton::GetInstance()); + /*url_lookup_service=*/nullptr, WebUIInfoSingleton::GetInstance(), + /*hash_realtime_service_on_ui=*/nullptr, + /*mechanism_experimenter=*/nullptr); checker_impl->CheckUrl( url, method,
diff --git a/components/safe_browsing/content/browser/web_api_handshake_checker.cc b/components/safe_browsing/content/browser/web_api_handshake_checker.cc index ade5c6e..938dd6e 100644 --- a/components/safe_browsing/content/browser/web_api_handshake_checker.cc +++ b/components/safe_browsing/content/browser/web_api_handshake_checker.cc
@@ -69,7 +69,9 @@ /*can_check_db=*/true, /*can_check_high_confidence_allowlist=*/true, /*url_lookup_service_metric_suffix=*/".None", last_committed_url_, content::GetUIThreadTaskRunner({}), - /*url_lookup_service=*/nullptr, WebUIInfoSingleton::GetInstance()); + /*url_lookup_service=*/nullptr, WebUIInfoSingleton::GetInstance(), + /*hash_realtime_service_on_ui=*/nullptr, + /*mechanism_experimenter=*/nullptr); url_checker_->CheckUrl( url, "GET", base::BindOnce(&WebApiHandshakeChecker::CheckerOnIO::OnCheckUrlResult,
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn index 5383e936..f8174fe6 100644 --- a/components/safe_browsing/core/browser/BUILD.gn +++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -14,6 +14,8 @@ "ping_manager.h", "safe_browsing_lookup_mechanism.cc", "safe_browsing_lookup_mechanism.h", + "safe_browsing_lookup_mechanism_experimenter.cc", + "safe_browsing_lookup_mechanism_experimenter.h", "safe_browsing_lookup_mechanism_runner.cc", "safe_browsing_lookup_mechanism_runner.h", "safe_browsing_url_checker_impl.cc", @@ -91,6 +93,18 @@ ] } +source_set("safe_browsing_lookup_mechanism_experimenter_unittest") { + testonly = true + sources = [ "safe_browsing_lookup_mechanism_experimenter_unittest.cc" ] + + deps = [ + ":browser", + "//base/test:test_support", + "//components/safe_browsing/core/browser/db:v4_protocol_manager_util", + "//testing/gtest", + ] +} + # NOTE: This target is separated from :browser as # //components/safe_browsing/core/browser/realtime:url_lookup_service_base, # which :browser depends on, depends on this.
diff --git a/components/safe_browsing/core/browser/hash_realtime_mechanism.cc b/components/safe_browsing/core/browser/hash_realtime_mechanism.cc index cf6aff3b..4143e17f 100644 --- a/components/safe_browsing/core/browser/hash_realtime_mechanism.cc +++ b/components/safe_browsing/core/browser/hash_realtime_mechanism.cc
@@ -10,6 +10,7 @@ #include "components/safe_browsing/core/browser/db/util.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism.h" +#include "components/safe_browsing/core/common/utils.h" namespace safe_browsing { @@ -31,6 +32,14 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } +// static +bool HashRealTimeMechanism::CanCheckUrl( + const GURL& url, + network::mojom::RequestDestination request_destination) { + return request_destination == network::mojom::RequestDestination::kDocument && + CanGetReputationOfUrl(url); +} + SafeBrowsingLookupMechanism::StartCheckResult HashRealTimeMechanism::StartCheckInternal() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/safe_browsing/core/browser/hash_realtime_mechanism.h b/components/safe_browsing/core/browser/hash_realtime_mechanism.h index 12147b9..e71bd5f8 100644 --- a/components/safe_browsing/core/browser/hash_realtime_mechanism.h +++ b/components/safe_browsing/core/browser/hash_realtime_mechanism.h
@@ -29,6 +29,12 @@ HashRealTimeMechanism& operator=(const HashRealTimeMechanism&) = delete; ~HashRealTimeMechanism() override; + // Returns whether the |url| is eligible for hash-prefix real-time checks. + // It's never eligible if the |request_destination| is not mainframe. + static bool CanCheckUrl( + const GURL& url, + network::mojom::RequestDestination request_destination); + private: // SafeBrowsingLookupMechanism implementation: StartCheckResult StartCheckInternal() override;
diff --git a/components/safe_browsing/core/browser/hash_realtime_mechanism_unittest.cc b/components/safe_browsing/core/browser/hash_realtime_mechanism_unittest.cc index 585918f..8d064fc 100644 --- a/components/safe_browsing/core/browser/hash_realtime_mechanism_unittest.cc +++ b/components/safe_browsing/core/browser/hash_realtime_mechanism_unittest.cc
@@ -31,7 +31,8 @@ MockHashRealTimeService() : HashRealTimeService( /*url_loader_factory=*/nullptr, - /*cache_manager=*/nullptr) {} + /*cache_manager=*/nullptr, + /*get_is_enhanced_protection_enabled=*/base::NullCallback()) {} base::WeakPtr<MockHashRealTimeService> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -245,6 +246,36 @@ arg->url_real_time_lookup_response == nullptr; } +TEST_F(HashRealTimeMechanismTest, CanCheckUrl_HashRealTime) { + auto can_check_url = + [](std::string url, + network::mojom::RequestDestination request_destination = + network::mojom::RequestDestination::kDocument) { + EXPECT_TRUE(GURL(url).is_valid()); + return HashRealTimeMechanism::CanCheckUrl(GURL(url), + request_destination); + }; + // Yes: HTTPS and main-frame URL. + EXPECT_TRUE(can_check_url("https://example.test/path")); + // Yes: HTTP and main-frame URL. + EXPECT_TRUE(can_check_url("http://example.test/path")); + // No: It's not a mainframe URL. + EXPECT_FALSE(can_check_url("https://example.test/path", + network::mojom::RequestDestination::kFrame)); + // No: The URL scheme is not HTTP/HTTPS. + EXPECT_FALSE(can_check_url("ftp://example.test/path")); + // No: It's localhost. + EXPECT_FALSE(can_check_url("http://localhost/path")); + // No: The host is an IP address, but is not publicly routable. + EXPECT_FALSE(can_check_url("http://0.0.0.0")); + // Yes: The host is an IP address and is publicly routable. + EXPECT_TRUE(can_check_url("http://1.0.0.0")); + // No: Hostname does not have at least 1 dot. + EXPECT_FALSE(can_check_url("https://example/path")); + // No: Hostname does not have at least 3 characters. + EXPECT_FALSE(can_check_url("https://e./path")); +} + TEST_F(HashRealTimeMechanismTest, CheckUrl_HashRealTime_CantCheckDb) { GURL url("https://example.test/"); auto mechanism = CreateHashRealTimeMechanism(url, /*can_check_db=*/false);
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.cc b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.cc index 3fdb4670..256e487 100644 --- a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.cc +++ b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.cc
@@ -66,7 +66,8 @@ HashRealTimeService::HashRealTimeService( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - VerdictCacheManager* cache_manager) + VerdictCacheManager* cache_manager, + base::RepeatingCallback<bool()> get_is_enhanced_protection_enabled) : url_loader_factory_(url_loader_factory), cache_manager_(cache_manager), backoff_operator_(std::make_unique<BackoffOperator>( @@ -74,17 +75,16 @@ /*min_backoff_reset_duration_in_seconds=*/ kMinBackOffResetDurationInSeconds, /*max_backoff_reset_duration_in_seconds=*/ - kMaxBackOffResetDurationInSeconds)) {} + kMaxBackOffResetDurationInSeconds)), + get_is_enhanced_protection_enabled_(get_is_enhanced_protection_enabled) {} HashRealTimeService::~HashRealTimeService() = default; -// static -bool HashRealTimeService::CanCheckUrl( - const GURL& url, - network::mojom::RequestDestination request_destination) { - return request_destination == network::mojom::RequestDestination::kDocument && - CanGetReputationOfUrl(url); +bool HashRealTimeService::IsEnhancedProtectionEnabled() { + return get_is_enhanced_protection_enabled_.Run(); } + +// static SBThreatType HashRealTimeService::DetermineSBThreatType( const GURL& url, const std::vector<V5::FullHash>& result_full_hashes) { @@ -433,6 +433,10 @@ cache_manager_ = nullptr; } +base::WeakPtr<HashRealTimeService> HashRealTimeService::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + void HashRealTimeService::LogOperationResult( OperationResult operation_result) const { base::UmaHistogramEnumeration("SafeBrowsing.HPRT.OperationResult",
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h index 785340f0..299a38b1 100644 --- a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h +++ b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h
@@ -46,7 +46,8 @@ public: explicit HashRealTimeService( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - VerdictCacheManager* cache_manager); + VerdictCacheManager* cache_manager, + base::RepeatingCallback<bool()> get_is_enhanced_protection_enabled); HashRealTimeService(const HashRealTimeService&) = delete; HashRealTimeService& operator=(const HashRealTimeService&) = delete; @@ -75,11 +76,10 @@ kMaxValue = kNotReached, }; - // Returns whether the |url| is eligible for hash-prefix real-time checks. - // It's never eligible if the |request_destination| is not mainframe. - static bool CanCheckUrl( - const GURL& url, - network::mojom::RequestDestination request_destination); + // This function is only currently used for the hash-prefix real-time lookup + // experiment. Once the experiment is complete, it will be deprecated. + // TODO(1410253): Deprecate this (including the factory populating it). + bool IsEnhancedProtectionEnabled(); // Returns true if the lookups are currently in backoff mode due to too many // prior errors. If this happens, the checking falls back to hash-based @@ -97,6 +97,9 @@ // Called before the actual deletion of the object. void Shutdown() override; + // Helper function to return a weak pointer. + base::WeakPtr<HashRealTimeService> GetWeakPtr(); + private: friend class HashRealTimeServiceTest; constexpr static int kLeastSeverity = std::numeric_limits<int>::max(); @@ -225,6 +228,9 @@ // early. bool is_shutdown_ = false; + // Pulls whether enhanced protection is currently enabled. + base::RepeatingCallback<bool()> get_is_enhanced_protection_enabled_; + base::WeakPtrFactory<HashRealTimeService> weak_factory_{this}; };
diff --git a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service_unittest.cc b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service_unittest.cc index a8ff91f..cc6d6746 100644 --- a/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service_unittest.cc +++ b/components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service_unittest.cc
@@ -56,7 +56,7 @@ cache_manager_ptr = cache_manager_.get(); } service_ = std::make_unique<HashRealTimeService>( - test_shared_loader_factory_, cache_manager_ptr); + test_shared_loader_factory_, cache_manager_ptr, base::NullCallback()); } void SetUp() override { PlatformTest::SetUp(); @@ -391,35 +391,6 @@ HashRealTimeServiceNoCacheManagerTest() { include_cache_manager_ = false; } }; -TEST_F(HashRealTimeServiceTest, TestCanCheckUrl) { - auto can_check_url = - [](std::string url, - network::mojom::RequestDestination request_destination = - network::mojom::RequestDestination::kDocument) { - EXPECT_TRUE(GURL(url).is_valid()); - return HashRealTimeService::CanCheckUrl(GURL(url), request_destination); - }; - // Yes: HTTPS and main-frame URL. - EXPECT_TRUE(can_check_url("https://example.test/path")); - // Yes: HTTP and main-frame URL. - EXPECT_TRUE(can_check_url("http://example.test/path")); - // No: It's not a mainframe URL. - EXPECT_FALSE(can_check_url("https://example.test/path", - network::mojom::RequestDestination::kFrame)); - // No: The URL scheme is not HTTP/HTTPS. - EXPECT_FALSE(can_check_url("ftp://example.test/path")); - // No: It's localhost. - EXPECT_FALSE(can_check_url("http://localhost/path")); - // No: The host is an IP address, but is not publicly routable. - EXPECT_FALSE(can_check_url("http://0.0.0.0")); - // Yes: The host is an IP address and is publicly routable. - EXPECT_TRUE(can_check_url("http://1.0.0.0")); - // No: Hostname does not have at least 1 dot. - EXPECT_FALSE(can_check_url("https://example/path")); - // No: Hostname does not have at least 3 characters. - EXPECT_FALSE(can_check_url("https://e./path")); -} - TEST_F(HashRealTimeServiceTest, TestLookup_OneHash_Safe) { GURL url = GURL("https://example.test"); RunRequestSuccessTest(
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc new file mode 100644 index 0000000..d8c6070 --- /dev/null +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc
@@ -0,0 +1,555 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h" + +#include "base/containers/contains.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" +#include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" +#include "components/safe_browsing/core/browser/hash_database_mechanism.h" +#include "components/safe_browsing/core/browser/hash_realtime_mechanism.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" +#include "components/safe_browsing/core/browser/url_realtime_mechanism.h" + +namespace safe_browsing { +SafeBrowsingLookupMechanismExperimenter:: + SafeBrowsingLookupMechanismExperimenter() = default; +SafeBrowsingLookupMechanismExperimenter:: + ~SafeBrowsingLookupMechanismExperimenter() = default; + +SafeBrowsingLookupMechanism::StartCheckResult +SafeBrowsingLookupMechanismExperimenter::RunChecks( + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback, + const GURL& url, + const SBThreatTypeSet& threat_types, + network::mojom::RequestDestination request_destination, + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + bool can_check_db, + bool can_check_high_confidence_allowlist, + std::string url_lookup_service_metric_suffix, + const GURL& last_committed_url, + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, + UrlRealTimeMechanism::WebUIDelegate* webui_delegate, + base::WeakPtr<HashRealTimeService> hash_real_time_service_on_ui) { + auto url_real_time_mechanism = std::make_unique<UrlRealTimeMechanism>( + url, threat_types, request_destination, database_manager, can_check_db, + can_check_high_confidence_allowlist, url_lookup_service_metric_suffix, + last_committed_url, ui_task_runner, url_lookup_service_on_ui, + webui_delegate); + auto hash_database_mechanism = std::make_unique<HashDatabaseMechanism>( + url, threat_types, database_manager, can_check_db); + auto hash_real_time_mechanism = std::make_unique<HashRealTimeMechanism>( + url, threat_types, database_manager, can_check_db, ui_task_runner, + hash_real_time_service_on_ui); + + return RunChecksInternal(std::move(url_real_time_mechanism), + std::move(hash_database_mechanism), + std::move(hash_real_time_mechanism), + std::move(url_real_time_result_callback)); +} + +SafeBrowsingLookupMechanism::StartCheckResult +SafeBrowsingLookupMechanismExperimenter::RunChecksInternal( + std::unique_ptr<SafeBrowsingLookupMechanism> url_real_time_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_database_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_real_time_mechanism, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback) { + // Create the mechanism runners and give them a reference to this object. + // UrlRealTimeMechanism + auto url_real_time_runner = std::make_unique< + SafeBrowsingLookupMechanismRunner>( + std::move(url_real_time_mechanism), + base::BindOnce( + &SafeBrowsingLookupMechanismExperimenter::OnUrlRealTimeCheckComplete, + weak_factory_.GetWeakPtr())); + url_real_time_runner->SetLookupMechanismExperimenter( + base::WrapRefCounted(this)); + // HashDatabaseMechanism + auto hash_database_runner = std::make_unique< + SafeBrowsingLookupMechanismRunner>( + std::move(hash_database_mechanism), + base::BindOnce( + &SafeBrowsingLookupMechanismExperimenter::OnHashDatabaseCheckComplete, + weak_factory_.GetWeakPtr())); + hash_database_runner->SetLookupMechanismExperimenter( + base::WrapRefCounted(this)); + // HashRealTimeMechanism + auto hash_real_time_runner = std::make_unique< + SafeBrowsingLookupMechanismRunner>( + std::move(hash_real_time_mechanism), + base::BindOnce( + &SafeBrowsingLookupMechanismExperimenter::OnHashRealTimeCheckComplete, + weak_factory_.GetWeakPtr())); + hash_real_time_runner->SetLookupMechanismExperimenter( + base::WrapRefCounted(this)); + // Start tracking this check + checks_to_run_.push_back(std::make_unique<CheckToRun>( + std::move(url_real_time_runner), std::move(hash_database_runner), + std::move(hash_real_time_runner), + std::move(url_real_time_result_callback))); + // Always run the URL real-time lookup, since we need to return its results. + auto url_real_time_result = + checks_to_run_.back()->url_real_time_details.runner->Run(); + if (!first_check_start_time_.has_value()) { + first_check_start_time_ = base::TimeTicks::Now(); + } + DCHECK(!url_real_time_result.is_safe_synchronously); + // Kick off running the hash-prefix database lookup if one is not already + // running. + if (hash_database_check_index_ == checks_to_run_.size() - 1) { + // Normally it can be dangerous to run code after a call to + // |RunNextHashDatabaseCheck| due to the possible synchronous destruction of + // this object, but in this case it is impossible because the experiment is + // still waiting on the results of the latest hash real-time check. + RunNextHashDatabaseCheck(); + } + // Kick off running the hash-prefix real-time lookup if one is not already + // running. + if (hash_real_time_check_index_ == checks_to_run_.size() - 1) { + RunNextHashRealTimeCheck(); + } + return url_real_time_result; +} + +void SafeBrowsingLookupMechanismExperimenter::RunNextHashDatabaseCheck() { + auto result = checks_to_run_[hash_database_check_index_] + ->hash_database_details.runner->Run(); + if (result.is_safe_synchronously) { + OnHashDatabaseCheckCompleteInternal(/*timed_out=*/false, + SB_THREAT_TYPE_SAFE); + return; + // NOTE: Calling |OnHashDatabaseCheckCompleteInternal| may result in the + // synchronous destruction of this object, so there is nothing safe to do + // here but return. + } +} +void SafeBrowsingLookupMechanismExperimenter::RunNextHashRealTimeCheck() { + auto result = checks_to_run_[hash_real_time_check_index_] + ->hash_real_time_details.runner->Run(); + DCHECK(!result.is_safe_synchronously); +} +void SafeBrowsingLookupMechanismExperimenter::OnWillProcessResponseReached( + base::TimeTicks reached_time) { + will_process_response_reached_time_ = reached_time; + MaybeCompleteExperiment(); + // Normally it can be dangerous to run code after a call to + // |MaybeCompleteExperiment| due to the possible synchronous destruction of + // this object, but in this case it would be safe, because the caller + // (BrowserUrlLoaderThrottle::CheckerOnIO) must still have a reference to + // *this* if it was able to call |OnWillProcessResponseReached|, and the + // experimenter does not influence the lifetime of CheckerOnIO. +} +void SafeBrowsingLookupMechanismExperimenter::OnUrlRealTimeCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result) { + auto& check = checks_to_run_.back(); + auto threat_type = result.has_value() ? result.value()->threat_type + : absl::optional<SBThreatType>(); + auto& run_details = check->url_real_time_details; + std::move(check->url_real_time_details.url_result_callback) + .Run(timed_out, std::move(result)); + StoreCheckResults(timed_out, threat_type, run_details); + // NOTE: Calling |StoreCheckResults| may result in the synchronous + // destruction of this object, so there is nothing safe to do here but return. +} +void SafeBrowsingLookupMechanismExperimenter::OnHashDatabaseCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result) { + OnHashDatabaseCheckCompleteInternal( + timed_out, result.has_value() ? result.value()->threat_type + : absl::optional<SBThreatType>()); + // NOTE: Calling |OnHashDatabaseCheckCompleteInternal| may result in the + // synchronous destruction of this object, so there is nothing safe to do here + // but return. +} +void SafeBrowsingLookupMechanismExperimenter:: + OnHashDatabaseCheckCompleteInternal( + bool timed_out, + absl::optional<SBThreatType> threat_type) { + auto weak_self = weak_factory_.GetWeakPtr(); + StoreCheckResults( + timed_out, threat_type, + checks_to_run_[hash_database_check_index_]->hash_database_details); + // NOTE: Calling |StoreCheckResults| may result in the synchronous + // destruction of this object, so we confirm *this* still exists before + // proceeding. + if (!!weak_self) { + hash_database_check_index_++; + if (hash_database_check_index_ < checks_to_run_.size()) { + RunNextHashDatabaseCheck(); + return; + // NOTE: Calling |RunNextHashDatabaseCheck| may result in the synchronous + // destruction of this object, so there is nothing safe to do here but + // return. + } + } +} +void SafeBrowsingLookupMechanismExperimenter::OnHashRealTimeCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result) { + auto weak_self = weak_factory_.GetWeakPtr(); + StoreCheckResults( + timed_out, + result.has_value() ? result.value()->threat_type + : absl::optional<SBThreatType>(), + checks_to_run_[hash_real_time_check_index_]->hash_real_time_details); + // NOTE: Calling |StoreCheckResults| may result in the synchronous + // destruction of this object, so we confirm *this* still exists before + // proceeding. + if (!!weak_self) { + hash_real_time_check_index_++; + if (hash_real_time_check_index_ < checks_to_run_.size()) { + RunNextHashRealTimeCheck(); + } + } +} +void SafeBrowsingLookupMechanismExperimenter::StoreCheckResults( + bool timed_out, + absl::optional<SBThreatType> threat_type, + CheckToRun::RunDetails& runner_and_results) { + DCHECK_EQ(timed_out, !threat_type.has_value()); + base::TimeDelta time_taken = runner_and_results.runner->GetRunDuration(); + bool had_warning = + !timed_out && (threat_type == SBThreatType::SB_THREAT_TYPE_URL_PHISHING || + threat_type == SBThreatType::SB_THREAT_TYPE_URL_MALWARE || + threat_type == SBThreatType::SB_THREAT_TYPE_URL_UNWANTED || + threat_type == SBThreatType::SB_THREAT_TYPE_BILLING); + runner_and_results.results = + MechanismResults(time_taken, had_warning, timed_out); + MaybeCompleteExperiment(); + // NOTE: Calling |MaybeCompleteExperiment| may result in the synchronous + // destruction of this object, so there is nothing safe to do here but return. +} +void SafeBrowsingLookupMechanismExperimenter::MaybeCompleteExperiment() { + if (checks_to_run_.empty()) { + // This can happen if the experiment was canceled, in which case we don't + // want to log any results. It can also happen if the experiment wasn't run + // at all. + return; + } + auto& latest_check = checks_to_run_.back(); + if (!latest_check->hash_database_details.results.has_value() || + !latest_check->hash_real_time_details.results.has_value() || + !latest_check->url_real_time_details.results.has_value() || + (!will_process_response_reached_time_.has_value() && + !is_browser_url_loader_throttle_checker_on_io_destructed_)) { + // The results are not yet complete. + return; + } +#if DCHECK_IS_ON() + DCHECK(!is_experiment_complete_); + is_experiment_complete_ = true; +#endif + LogExperimentResults(); + EndExperiment(); + // NOTE: Calling |EndExperiment| may result in the synchronous destruction + // of this object, so there is nothing safe to do here but return. +} + +void SafeBrowsingLookupMechanismExperimenter::LogExperimentResults() { + if (checks_to_run_.size() == 1) { + auto& single_check = checks_to_run_.back(); + LogAggregatedResults("", + single_check->url_real_time_details.results.value(), + single_check->hash_database_details.results.value(), + single_check->hash_real_time_details.results.value()); + } else { + auto url_real_time_results = AggregateRedirectInfo(base::BindRepeating( + [](std::unique_ptr<CheckToRun>& check) -> MechanismResults& { + return check->url_real_time_details.results.value(); + })); + auto hash_database_results = AggregateRedirectInfo(base::BindRepeating( + [](std::unique_ptr<CheckToRun>& check) -> MechanismResults& { + return check->hash_database_details.results.value(); + })); + auto hash_real_time_results = AggregateRedirectInfo(base::BindRepeating( + [](std::unique_ptr<CheckToRun>& check) -> MechanismResults& { + return check->hash_real_time_details.results.value(); + })); + LogAggregatedResults("Redirects.", url_real_time_results, + hash_database_results, hash_real_time_results); + } +} +void SafeBrowsingLookupMechanismExperimenter::LogAggregatedResults( + const std::string& redirects_qualifier, + MechanismResults& url_real_time_results, + MechanismResults& hash_database_results, + MechanismResults& hash_real_time_results) const { + LogCombinedResults(redirects_qualifier, url_real_time_results, + hash_database_results, hash_real_time_results); + + LogPairedResults(redirects_qualifier, url_real_time_results, + hash_database_results, "URT", "HPD"); + LogPairedResults(redirects_qualifier, url_real_time_results, + hash_real_time_results, "URT", "HPRT"); + LogPairedResults(redirects_qualifier, hash_database_results, + hash_real_time_results, "HPD", "HPRT"); + + LogIndividualMechanismResult(redirects_qualifier, url_real_time_results, + "URT"); + LogIndividualMechanismResult(redirects_qualifier, hash_database_results, + "HPD"); + LogIndividualMechanismResult(redirects_qualifier, hash_real_time_results, + "HPRT"); +} +void SafeBrowsingLookupMechanismExperimenter::LogPairedResults( + const std::string& redirects_qualifier, + MechanismResults& results1, + MechanismResults& results2, + const std::string& acronym1, + const std::string& acronym2) const { + // Possible logs: + // - SafeBrowsing.HPRTExperiment[.Redirects].URTFasterThanHPDAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPDFasterThanURTAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].URTFasterThanHPRTAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRTFasterThanURTAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPDFasterThanHPRTAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRTFasterThanHPDAmount + if (results1.time_taken < results2.time_taken) { + auto histogram_name = + base::StrCat({"SafeBrowsing.HPRTExperiment.", redirects_qualifier, + acronym1, "FasterThan", acronym2, "Amount"}); + base::UmaHistogramTimes(histogram_name, + results2.time_taken - results1.time_taken); + + } else { + auto histogram_name = + base::StrCat({"SafeBrowsing.HPRTExperiment.", redirects_qualifier, + acronym2, "FasterThan", acronym1, "Amount"}); + base::UmaHistogramTimes(histogram_name, + results1.time_taken - results2.time_taken); + } +} +void SafeBrowsingLookupMechanismExperimenter::LogCombinedResults( + const std::string& redirects_qualifier, + MechanismResults& url_real_time_results, + MechanismResults& hash_database_results, + MechanismResults& hash_real_time_results) const { + // Possible logs: + // - SafeBrowsing.HPRTExperiment[.Redirects].WarningsResult + // - SafeBrowsing.HPRTExperiment[.Redirects].TimedOutResult + // - SafeBrowsing.HPRTExperiment[.Redirects].DelayedResponseResult + + // Warnings + base::UmaHistogramEnumeration( + base::StrCat({"SafeBrowsing.HPRTExperiment.", redirects_qualifier, + "WarningsResult"}), + CombineBoolResults(url_real_time_results.had_warning, + hash_database_results.had_warning, + hash_real_time_results.had_warning)); + // Timed out + base::UmaHistogramEnumeration( + base::StrCat({"SafeBrowsing.HPRTExperiment.", redirects_qualifier, + "TimedOutResult"}), + CombineBoolResults(url_real_time_results.timed_out, + hash_database_results.timed_out, + hash_real_time_results.timed_out)); + // Caused delay + auto url_real_time_delay_info = GetDelayInformation(url_real_time_results); + auto hash_database_delay_info = GetDelayInformation(hash_database_results); + auto hash_real_time_delay_info = GetDelayInformation(hash_real_time_results); + if (url_real_time_delay_info.delayed_response != + ExperimentUnknownNoYesResult::kUnknown) { + base::UmaHistogramEnumeration( + base::StrCat({"SafeBrowsing.HPRTExperiment.", redirects_qualifier, + "DelayedResponseResult"}), + CombineBoolResults(url_real_time_delay_info.delayed_response == + ExperimentUnknownNoYesResult::kYes, + hash_database_delay_info.delayed_response == + ExperimentUnknownNoYesResult::kYes, + hash_real_time_delay_info.delayed_response == + ExperimentUnknownNoYesResult::kYes)); + } +} +void SafeBrowsingLookupMechanismExperimenter::LogIndividualMechanismResult( + const std::string& redirects_qualifier, + MechanismResults& results, + const std::string& acronym) const { + // Possible logs: + // - SafeBrowsing.HPRTExperiment[.Redirects].URT.TimeTaken + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRT.TimeTaken + // - SafeBrowsing.HPRTExperiment[.Redirects].HPD.TimeTaken + // - SafeBrowsing.HPRTExperiment[.Redirects].URT.TimedOut + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRT.TimedOut + // - SafeBrowsing.HPRTExperiment[.Redirects].HPD.TimedOut + // - SafeBrowsing.HPRTExperiment[.Redirects].URT.DelayedResponse + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRT.DelayedResponse + // - SafeBrowsing.HPRTExperiment[.Redirects].HPD.DelayedResponse + // - SafeBrowsing.HPRTExperiment[.Redirects].URT.DelayedResponseAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPRT.DelayedResponseAmount + // - SafeBrowsing.HPRTExperiment[.Redirects].HPD.DelayedResponseAmount + auto histogram_prefix = base::StrCat( + {"SafeBrowsing.HPRTExperiment.", redirects_qualifier, acronym}); + base::UmaHistogramTimes(base::StrCat({histogram_prefix, ".TimeTaken"}), + results.time_taken); + base::UmaHistogramBoolean(base::StrCat({histogram_prefix, ".TimedOut"}), + results.timed_out); + + auto delay_information = GetDelayInformation(results); + base::UmaHistogramEnumeration( + base::StrCat({histogram_prefix, ".DelayedResponse"}), + delay_information.delayed_response); + if (delay_information.delayed_response_amount.has_value()) { + base::UmaHistogramTimes( + base::StrCat({histogram_prefix, ".DelayedResponseAmount"}), + delay_information.delayed_response_amount.value()); + } +} +SafeBrowsingLookupMechanismExperimenter::DelayInformation +SafeBrowsingLookupMechanismExperimenter::GetDelayInformation( + MechanismResults& results) const { + DelayInformation delay_information; + if (will_process_response_reached_time_.has_value()) { + DCHECK(first_check_start_time_.has_value()); + bool delayed_response = + first_check_start_time_.value() + results.time_taken > + will_process_response_reached_time_.value(); + delay_information.delayed_response = + delayed_response ? ExperimentUnknownNoYesResult::kYes + : ExperimentUnknownNoYesResult::kNo; + delay_information.delayed_response_amount = + delayed_response + ? (will_process_response_reached_time_.value() - + (first_check_start_time_.value() + results.time_taken)) + : base::TimeDelta(); + } else { + // If the URL real-time check results in a warning, there might never + // be a call to WillProcessResponse. In these cases, we log "Unknown" + // because we don't know if the other mechanisms would have delayed + // the response time. We could log this fewer times either (1) for URL + // real-time checks generally, since we know they didn't delay the + // response, or (2) for other checks if they were faster than the URL + // real-time check since that check didn't delay the response. + // However, we avoid doing either so that we don't skew the results. + // This might also happen if something upstream decides to destruct + // BrowserUrlLoaderThrottle before the page has loaded, but after the + // lookups have completed. + delay_information.delayed_response = ExperimentUnknownNoYesResult::kUnknown; + } + return delay_information; +} +SafeBrowsingLookupMechanismExperimenter::MechanismResults +SafeBrowsingLookupMechanismExperimenter::AggregateRedirectInfo( + base::RepeatingCallback<MechanismResults&(std::unique_ptr<CheckToRun>&)> + get_results) { + bool had_warning = false; + bool timed_out = false; + base::TimeDelta time_taken = base::TimeDelta(); + for (auto& check : checks_to_run_) { + if (get_results.Run(check).had_warning) { + had_warning = true; + } + if (get_results.Run(check).timed_out) { + timed_out = true; + } + time_taken += get_results.Run(check).time_taken; + } + return MechanismResults(time_taken, had_warning, timed_out); +} +// static +SafeBrowsingLookupMechanismExperimenter::ExperimentAllInOneResult +SafeBrowsingLookupMechanismExperimenter::CombineBoolResults( + bool url_real_time_result, + bool hash_database_result, + bool hash_real_time_result) { + return hash_database_result && url_real_time_result && hash_real_time_result + ? ExperimentAllInOneResult::kAllMechanisms + : hash_database_result && url_real_time_result + ? ExperimentAllInOneResult::kUrlRealTimeAndHashDatabase + : hash_database_result && hash_real_time_result + ? ExperimentAllInOneResult::kHashDatabaseAndHashRealTime + : hash_real_time_result && url_real_time_result + ? ExperimentAllInOneResult::kUrlRealTimeAndHashRealTime + : hash_database_result ? ExperimentAllInOneResult::kHashDatabaseOnly + : hash_real_time_result ? ExperimentAllInOneResult::kHashRealTimeOnly + : url_real_time_result ? ExperimentAllInOneResult::kUrlRealTimeOnly + : ExperimentAllInOneResult::kNoMechanism; +} + +void SafeBrowsingLookupMechanismExperimenter:: + OnBrowserUrlLoaderThrottleCheckerOnIODestructed() { + is_browser_url_loader_throttle_checker_on_io_destructed_ = true; + if (!will_process_response_reached_time_.has_value()) { + MaybeCompleteExperiment(); + // Normally it can be dangerous to run code after a call to + // |MaybeCompleteExperiment| due to the possible synchronous destruction of + // this object, but in this case it would be safe. This is because the + // caller (BrowserUrlLoaderThrottle::CheckerOnIO) is calling into this + // function from its destructor, meaning at least until this method ends it + // still has a reference to the experimenter. + } +} +void SafeBrowsingLookupMechanismExperimenter:: + OnSafeBrowsingUrlCheckerImplDestructed() { + if (checks_to_run_.empty()) { + // The experiment already ended or never started. + return; + } + auto& latest_check = checks_to_run_.back(); + if (!latest_check->url_real_time_details.results.has_value()) { + // Cancel the experiment if SBUCI is destructed but the URL real-time lookup + // results haven't completed. + EndExperiment(); + // Normally it can be dangerous to run code after a call to + // |EndExperiment| due to the possible synchronous destruction of this + // object, but in this case it would be safe. This is because the caller + // (SafeBrowsingUrlCheckerImpl) is calling into this function from its + // destructor, meaning at least until this method ends it still has a + // reference to the experimenter. + } +} + +void SafeBrowsingLookupMechanismExperimenter::EndExperiment() { + weak_factory_.InvalidateWeakPtrs(); + // Can't use |checks_to_run_.clear()| because that implementation might + // use *this* after it has been freed. + std::vector<std::unique_ptr<CheckToRun>>().swap(checks_to_run_); + // NOTE: Resetting the checks may result in the synchronous destruction of + // this object, so there is nothing safe to do here but return. +} + +SafeBrowsingLookupMechanismExperimenter::CheckToRun::CheckToRun( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> url_real_time_runner, + std::unique_ptr<SafeBrowsingLookupMechanismRunner> hash_database_runner, + std::unique_ptr<SafeBrowsingLookupMechanismRunner> hash_real_time_runner, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback) + : hash_database_details(RunDetails(std::move(hash_database_runner))), + hash_real_time_details(RunDetails(std::move(hash_real_time_runner))), + url_real_time_details( + UrlRealTimeRunDetails(std::move(url_real_time_runner), + std::move(url_real_time_result_callback))) {} +SafeBrowsingLookupMechanismExperimenter::CheckToRun::~CheckToRun() = default; +SafeBrowsingLookupMechanismExperimenter::MechanismResults::MechanismResults( + base::TimeDelta time_taken, + bool had_warning, + bool timed_out) + : time_taken(time_taken), had_warning(had_warning), timed_out(timed_out) {} +SafeBrowsingLookupMechanismExperimenter::MechanismResults::~MechanismResults() = + default; +SafeBrowsingLookupMechanismExperimenter::CheckToRun::RunDetails::RunDetails( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> runner) + : runner(std::move(runner)) {} +SafeBrowsingLookupMechanismExperimenter::CheckToRun::RunDetails::~RunDetails() = + default; +SafeBrowsingLookupMechanismExperimenter::CheckToRun::UrlRealTimeRunDetails:: + UrlRealTimeRunDetails( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> runner, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_result_callback) + : RunDetails(std::move(runner)), + url_result_callback(std::move(url_result_callback)) {} +SafeBrowsingLookupMechanismExperimenter::CheckToRun::UrlRealTimeRunDetails:: + ~UrlRealTimeRunDetails() = default; +} // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h new file mode 100644 index 0000000..fada4ff8 --- /dev/null +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h
@@ -0,0 +1,299 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SAFE_BROWSING_LOOKUP_MECHANISM_EXPERIMENTER_H_ +#define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SAFE_BROWSING_LOOKUP_MECHANISM_EXPERIMENTER_H_ + +#include "components/safe_browsing/core/browser/db/database_manager.h" +#include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" +#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" +#include "components/safe_browsing/core/browser/realtime/url_lookup_service_base.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" +#include "components/safe_browsing/core/browser/url_realtime_mechanism.h" +#include "url/gurl.h" + +namespace safe_browsing { + +// When eligible, this class kicks off all three lookup mechanisms (hash-prefix +// database lookup, hash-prefix real-time lookup, URL real-time lookup) instead +// of solely the URL real-time lookup. The two other mechanisms are performed in +// the background and do not influence the main URL real-time lookup result. +// Once all three lookups complete, this class logs their combined results. +// Since a lookup can have redirects, the consumer of RunChecks is responsible +// for calling RunChecks for every redirect, which will kick off another lookup +// for each mechanism. This class will wait until all redirects have completed +// before ending the experiment and logging the results. +// This class should only be used on the IO thread. +// TODO(1410253): Delete this class once the temporary experiment is complete. +class SafeBrowsingLookupMechanismExperimenter + : public base::RefCounted<SafeBrowsingLookupMechanismExperimenter> { + public: + SafeBrowsingLookupMechanismExperimenter(); + SafeBrowsingLookupMechanismExperimenter( + const SafeBrowsingLookupMechanismExperimenter&) = delete; + SafeBrowsingLookupMechanismExperimenter& operator=( + const SafeBrowsingLookupMechanismExperimenter&) = delete; + + // Kicks off the experiment. This creates three separate runners (one per + // mechanism), so it requires the union of the parameters required for each + // SafeBrowsingLookupMechanism. See the constructors of the individual + // mechanisms for more details on individual parameters. + // While this function kicks off all three lookups, the only one that matters + // from the consumer's perspective is the URL real-time lookup, since that is + // what will be used to determine whether to display a warning. Therefore, the + // only callback passed through is |url_real_time_result_callback|, which is + // called when the URL real-time check completes. + SafeBrowsingLookupMechanism::StartCheckResult RunChecks( + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback, + const GURL& url, + const SBThreatTypeSet& threat_types, + network::mojom::RequestDestination request_destination, + scoped_refptr<SafeBrowsingDatabaseManager> database_manager, + bool can_check_db, + bool can_check_high_confidence_allowlist, + std::string url_lookup_service_metric_suffix, + const GURL& last_committed_url, + scoped_refptr<base::SequencedTaskRunner> ui_task_runner, + base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, + UrlRealTimeMechanism::WebUIDelegate* webui_delegate, + base::WeakPtr<HashRealTimeService> hash_real_time_service_on_ui); + + // This records the time that WillProcessResponse was called by + // BrowserURLLoaderThrottle, which is used for logs when the experiment + // completes. If this is the last piece of data the experiment was waiting on, + // the experiment will end. + void OnWillProcessResponseReached(base::TimeTicks reached_time); + + // The BrowserUrlLoaderThrottle's CheckerOnIO can be destructed before + // WillProcessResponse is reached. If this is the case, if the time + // WillProcessResponse was reached was the last piece of data the experiment + // was waiting on, the experiment will end. + void OnBrowserUrlLoaderThrottleCheckerOnIODestructed(); + + // If SafeBrowsingUrlCheckerImpl is destructed before the latest URL real-time + // check has completed, the experiment end with the results being thrown away. + void OnSafeBrowsingUrlCheckerImplDestructed(); + + private: + friend class base::RefCounted<SafeBrowsingLookupMechanismExperimenter>; + friend class SafeBrowsingLookupMechanismExperimenterTest; + + // Private destructor since the class is ref counted. We only want RefCounted + // to be able to destruct this object. + ~SafeBrowsingLookupMechanismExperimenter(); + + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class ExperimentAllInOneResult { + kNoMechanism = 0, + kUrlRealTimeOnly = 1, + kHashDatabaseOnly = 2, + kHashRealTimeOnly = 3, + kUrlRealTimeAndHashDatabase = 4, + kUrlRealTimeAndHashRealTime = 5, + kHashDatabaseAndHashRealTime = 6, + kAllMechanisms = 7, + kMaxValue = kAllMechanisms + }; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class ExperimentUnknownNoYesResult { + kUnknown = 0, + kNo = 1, + kYes = 2, + kMaxValue = kYes + }; + // Contains the results of a particular mechanism's run. + struct MechanismResults { + MechanismResults(base::TimeDelta time_taken, + bool had_warning, + bool timed_out); + ~MechanismResults(); + // How long the run took. + base::TimeDelta time_taken; + // Whether the run resulted in a warning. + bool had_warning; + // Whether the run did not complete in time. + bool timed_out; + }; + // This represents all the information necessary to run a specific check + // (across all 3 relevant mechanisms) as well as the results of each + // individual lookup once it completes. + struct CheckToRun { + CheckToRun( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> url_real_time_runner, + std::unique_ptr<SafeBrowsingLookupMechanismRunner> hash_database_runner, + std::unique_ptr<SafeBrowsingLookupMechanismRunner> + hash_real_time_runner, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback); + ~CheckToRun(); + // Represents a specific mechanism lookup's inputs and outputs. + struct RunDetails { + std::unique_ptr<SafeBrowsingLookupMechanismRunner> runner; + absl::optional<MechanismResults> results; + explicit RunDetails( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> runner); + ~RunDetails(); + }; + // For URL real-time checks specifically, one of the outputs is also the + // callback that should be triggered once the lookup completes. + struct UrlRealTimeRunDetails : RunDetails { + UrlRealTimeRunDetails( + std::unique_ptr<SafeBrowsingLookupMechanismRunner> runner, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_result_callback); + ~UrlRealTimeRunDetails(); + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_result_callback; + }; + // The following three are the RunDetails corresponding to each mechanism + // lookup. + RunDetails hash_database_details; + RunDetails hash_real_time_details; + UrlRealTimeRunDetails url_real_time_details; + }; + + struct DelayInformation { + // Whether the response was delayed because of this mechanism. + ExperimentUnknownNoYesResult delayed_response; + // The amount the response was delayed. If it wasn't delayed, it's the + // default base::TimeDelta(). If it's unknown whether the response was + // delayed, this is not populated. + absl::optional<base::TimeDelta> delayed_response_amount; + }; + + // Helper function that does everything |RunChecks| does after the lookup + // mechanism objects have been created. + SafeBrowsingLookupMechanism::StartCheckResult RunChecksInternal( + std::unique_ptr<SafeBrowsingLookupMechanism> url_real_time_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_database_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_real_time_mechanism, + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout + url_real_time_result_callback); + // Called once the URL real-time lookup completes. It will store the + // results of the lookup and then possibly end the experiment if this was + // the last thing it was waiting on. It will also trigger informing the + // original caller on the results of the URL real-time check. + void OnUrlRealTimeCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result); + // Called once the hash-prefix database check completes. It will store the + // results of the lookup and then possibly end the experiment if this was the + // last thing it was waiting on. + void OnHashDatabaseCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result); + void OnHashDatabaseCheckCompleteInternal( + bool timed_out, + absl::optional<SBThreatType> threat_type); + // Kicks off the next hash-prefix database lookup available from the + // |checks_to_run_| vector. + void RunNextHashDatabaseCheck(); + // Called once the hash-prefix real-time check completes. It will store the + // results of the lookup and then possibly end the experiment if this was the + // last thing it was waiting on. + void OnHashRealTimeCheckComplete( + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result); + // Kicks off the next hash-prefix real-time lookup available from the + // |checks_to_run_| vector. + void RunNextHashRealTimeCheck(); + + // If all individual results are in, this will mark the experiment as + // complete, aggregate the results, and log them. It will then clear out + // |checks_to_run_| within the |EndExperiment| helper function, which can + // delete the entire experimenter object if there are no remaining consumer + // pointers to it. + void MaybeCompleteExperiment(); + // Combines the results of all the lookups and logs them. + void LogExperimentResults(); + // Once this is called, this object will be cleaned up either immediately or + // shortly afterwards once other objects (SafeBrowsingUrlCheckerImpl or + // BrowserUrlLoaderThrottle) with pointers to it have also been destructed. + void EndExperiment(); + // Stores derived information from |timed_out| and |threat_type| on + // |run_details|. It can also trigger ending the experiment if this result was + // the last piece of information the experiment was waiting on. + void StoreCheckResults(bool timed_out, + absl::optional<SBThreatType> threat_type, + CheckToRun::RunDetails& run_details); + + // Helper function to combine boolean results from each of the three + // mechanisms into a single enum for logging. + static ExperimentAllInOneResult CombineBoolResults( + bool url_real_time_result, + bool hash_database_result, + bool hash_real_time_result); + // Returns details on whether the result caused a delay, and if so, by how + // much. + DelayInformation GetDelayInformation(MechanismResults& results) const; + // Combines the mechanism redirect results all into a single result. + MechanismResults AggregateRedirectInfo( + base::RepeatingCallback<MechanismResults&(std::unique_ptr<CheckToRun>&)> + get_results); + // Kicks off combined, paired, and individual logs for the results. + void LogAggregatedResults(const std::string& redirects_qualifier, + MechanismResults& url_real_time_results, + MechanismResults& hash_database_results, + MechanismResults& hash_real_time_results) const; + // Combines the results of the 3 mechanisms into one log (and logs it). + void LogCombinedResults(const std::string& redirects_qualifier, + MechanismResults& url_real_time_results, + MechanismResults& hash_database_results, + MechanismResults& hash_real_time_results) const; + // Combines the results of 2 mechanisms into one log (and logs it). + void LogPairedResults(const std::string& redirects_qualifier, + MechanismResults& results1, + MechanismResults& results2, + const std::string& acronym1, + const std::string& acronym2) const; + // Logs details on the elapsed time, timeout status, and delay response + // status for an individual mechanism result. + void LogIndividualMechanismResult(const std::string& redirects_qualifier, + MechanismResults& results, + const std::string& acronym) const; + + // This represents the checks that the experiment will or already did run. + // Each |CheckToRun| has the inputs that all 3 mechanism lookups need to be + // run, and eventually it stores the outputs of all 3 mechanism lookups. + std::vector<std::unique_ptr<CheckToRun>> checks_to_run_; + // If there is an active hash-prefix database lookup being run, this + // represents its index within |checks_to_run|. If not, then it's equal to the + // size of |checks_to_run|. + size_t hash_database_check_index_ = 0; + // If there is an active hash-prefix real-time lookup being run, this + // represents its index within |checks_to_run|. If not, then it's equal to the + // size of |checks_to_run|. + size_t hash_real_time_check_index_ = 0; + // Represents the time WillProcessResponse was called in + // BrowserUrlLoaderThrottle. It's not populated until that result is + // available. + absl::optional<base::TimeTicks> will_process_response_reached_time_; + // Set to true when BrowserUrlLoaderThrottle::CheckerOnIO gets destructed. + // If the check results in a warning, WillProcessResponse might never get + // called, so this property being set ensures that the experiment doesn't keep + // waiting for a call that will not come. + bool is_browser_url_loader_throttle_checker_on_io_destructed_ = false; +#if DCHECK_IS_ON() + // Used only for a DCHECK to confirm that the experiment is only completed + // once. + bool is_experiment_complete_ = false; +#endif + // Set to the current time when the first check starts being run. This is used + // to decide how long it took before WillProcessResponse was called. + absl::optional<base::TimeTicks> first_check_start_time_; + base::WeakPtrFactory<SafeBrowsingLookupMechanismExperimenter> weak_factory_{ + this}; +}; +} // namespace safe_browsing +#endif // COMPONENTS_SAFE_BROWSING_CORE_BROWSER_SAFE_BROWSING_LOOKUP_MECHANISM_EXPERIMENTER_H_
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc new file mode 100644 index 0000000..595ccc61 --- /dev/null +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc
@@ -0,0 +1,919 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h" +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace safe_browsing { + +using Experimenter = SafeBrowsingLookupMechanismExperimenter; +using CompleteCheckCallbackWithTimeout = + SafeBrowsingLookupMechanismRunner::CompleteCheckCallbackWithTimeout; + +MATCHER_P(Matches, threat_type, "") { + return arg.value()->threat_type == threat_type && + arg.value()->is_from_url_real_time_check; +} + +class MockSafeBrowsingLookupMechanism : public SafeBrowsingLookupMechanism { + public: + explicit MockSafeBrowsingLookupMechanism(bool is_safe_synchronously, + SBThreatType threat_type, + base::TimeDelta time_to_completion, + bool is_url_real_time) + : SafeBrowsingLookupMechanism(GURL(), + SBThreatTypeSet({}), + /*database_manager=*/nullptr, + /*can_check_db=*/true), + is_safe_synchronously_(is_safe_synchronously), + time_to_completion_(time_to_completion), + threat_type_(threat_type), + is_url_real_time_(is_url_real_time) {} + + private: + StartCheckResult StartCheckInternal() override { + if (!is_safe_synchronously_) { + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&MockSafeBrowsingLookupMechanism::CompleteCheck, + weak_factory_.GetWeakPtr(), + std::make_unique<CompleteCheckResult>( + url_, threat_type_, ThreatMetadata(), + /*is_from_url_real_time_check=*/is_url_real_time_, + /*url_real_time_lookup_response=*/nullptr)), + time_to_completion_); + } + return StartCheckResult(is_safe_synchronously_, + /*did_check_url_real_time_allowlist=*/false); + } + + // StartCheckInternal will return this value. Also, if it is true, the + // callback won't be called. + bool is_safe_synchronously_; + // How long until the callback is called. (If greater than 5 seconds, the + // runner should destruct this object before it had the chance to call the + // callback.) If |is_safe_synchronously_| is true, this value will be ignored. + base::TimeDelta time_to_completion_; + // This is the resulting threat type that the mechanism will return. If + // |is_safe_synchronously_| is true, this value will be ignored. + SBThreatType threat_type_; + // Whether this is the URL real-time mechanism. Used for the |CompleteCheck| + // callback. + bool is_url_real_time_; + + base::WeakPtrFactory<MockSafeBrowsingLookupMechanism> weak_factory_{this}; +}; + +// This class is meant to simulate how the SafeBrowsingUrlCheckerImpl interacts +// with the experimenter. +class PretendSafeBrowsingUrlCheckerImpl { + public: + explicit PretendSafeBrowsingUrlCheckerImpl( + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter) { + mechanism_experimenter_ = mechanism_experimenter; + } + ~PretendSafeBrowsingUrlCheckerImpl() { + mechanism_experimenter_->OnSafeBrowsingUrlCheckerImplDestructed(); + } + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter_; +}; + +// This class is meant to simulate how the BrowserUrlLoaderThrottle interacts +// with the experimenter. +class PretendCheckerOnIO { + public: + explicit PretendCheckerOnIO(base::TimeDelta time_to_will_process_response, + base::TimeDelta time_to_self_destruct) { + safe_browsing_url_checker_impl_ = + std::make_unique<PretendSafeBrowsingUrlCheckerImpl>( + mechanism_experimenter_); + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PretendCheckerOnIO::CallWillProcessResponse, + weak_factory_.GetWeakPtr()), + time_to_will_process_response); + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PretendCheckerOnIO::SelfDestruct, + weak_factory_.GetWeakPtr()), + time_to_self_destruct); + } + ~PretendCheckerOnIO() { + mechanism_experimenter_->OnBrowserUrlLoaderThrottleCheckerOnIODestructed(); + } + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> GetExperimenter() { + return mechanism_experimenter_; + } + + private: + void CallWillProcessResponse() { + mechanism_experimenter_->OnWillProcessResponseReached( + base::TimeTicks::Now()); + } + void SelfDestruct() { delete this; } + + std::unique_ptr<PretendSafeBrowsingUrlCheckerImpl> + safe_browsing_url_checker_impl_; + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter_ = + base::MakeRefCounted<SafeBrowsingLookupMechanismExperimenter>(); + base::WeakPtrFactory<PretendCheckerOnIO> weak_factory_{this}; +}; + +class SafeBrowsingLookupMechanismExperimenterTest : public PlatformTest { + protected: + using UnknownNoYesResult = Experimenter::ExperimentUnknownNoYesResult; + using AllInOneResult = Experimenter::ExperimentAllInOneResult; + + struct DelayedResponseInfo { + std::vector<UnknownNoYesResult> urt_hpd_hprt_delayed_responses; + absl::optional<AllInOneResult> delayed_response_result; + }; + + void ResetMetrics() { + histogram_tester_ = std::make_unique<base::HistogramTester>(); + } + + AllInOneResult CombineBoolResults(bool url_real_time_result, + bool hash_database_result, + bool hash_real_time_result) { + return Experimenter::CombineBoolResults( + url_real_time_result, hash_database_result, hash_real_time_result); + } + + void RunChecks( + scoped_refptr<Experimenter> mechanism_experimenter, + std::unique_ptr<SafeBrowsingLookupMechanism> url_real_time_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_database_mechanism, + std::unique_ptr<SafeBrowsingLookupMechanism> hash_real_time_mechanism, + CompleteCheckCallbackWithTimeout url_real_time_result_callback) { + mechanism_experimenter->RunChecksInternal( + std::move(url_real_time_mechanism), std::move(hash_database_mechanism), + std::move(hash_real_time_mechanism), + std::move(url_real_time_result_callback)); + } + void CreateAndRunChecks( + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter, + std::vector<base::TimeDelta> urt_hpd_hprt_times_taken, + std::vector<SBThreatType> urt_hpd_hprt_threat_types, + CompleteCheckCallbackWithTimeout url_real_time_result_callback) { + DCHECK(urt_hpd_hprt_times_taken[1] != base::Seconds(0) || + urt_hpd_hprt_threat_types[1] == SB_THREAT_TYPE_SAFE); + RunChecks( + mechanism_experimenter, + CreateUrlRealTimeMechanism(urt_hpd_hprt_threat_types[0], + urt_hpd_hprt_times_taken[0]), + urt_hpd_hprt_times_taken[1] == base::Seconds(0) + ? CreateSyncHashDatabaseMechanism() + : CreateAsyncHashDatabaseMechanism(urt_hpd_hprt_threat_types[1], + urt_hpd_hprt_times_taken[1]), + CreateHashRealTimeMechanism(urt_hpd_hprt_threat_types[2], + urt_hpd_hprt_times_taken[2]), + std::move(url_real_time_result_callback)); + } + + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> SetUpExperimenter( + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + // Created with 'new' so that it can live on past the end of this method but + // also control its own lifetime via |time_to_self_destruct|. + auto* checker_on_io = new PretendCheckerOnIO( + /*time_to_will_process_response=*/will_process_response_time_taken, + /*time_to_self_destruct=*/checker_on_io_self_destruct_time); + return checker_on_io->GetExperimenter(); + } + + // Creates a parent PretendCheckerOnIO that creates the experimenter. Then + // creates the three lookup mechanisms to be tied to the experimenter, and + // kicks off RunChecks. If the input HPD time taken (through + // |urt_hpd_hprt_times_taken|) equals 0, the hash-database mechanism completes + // as safe synchronously. + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + SetUpExperimenterAndChecks( + std::vector<base::TimeDelta> urt_hpd_hprt_times_taken, + std::vector<SBThreatType> urt_hpd_hprt_threat_types, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time, + CompleteCheckCallbackWithTimeout url_real_time_result_callback) { + auto mechanism_experimenter = SetUpExperimenter( + will_process_response_time_taken, checker_on_io_self_destruct_time); + CreateAndRunChecks(mechanism_experimenter, urt_hpd_hprt_times_taken, + urt_hpd_hprt_threat_types, + std::move(url_real_time_result_callback)); + return mechanism_experimenter; + } + + std::unique_ptr<MockSafeBrowsingLookupMechanism> CreateUrlRealTimeMechanism( + SBThreatType threat_type, + base::TimeDelta time_to_completion) { + return std::make_unique<MockSafeBrowsingLookupMechanism>( + /*is_safe_synchronously=*/false, /*threat_type=*/threat_type, + /*time_to_completion=*/time_to_completion, /*is_url_real_time=*/true); + } + std::unique_ptr<MockSafeBrowsingLookupMechanism> CreateHashRealTimeMechanism( + SBThreatType threat_type, + base::TimeDelta time_to_completion) { + return std::make_unique<MockSafeBrowsingLookupMechanism>( + /*is_safe_synchronously=*/false, /*threat_type=*/threat_type, + /*time_to_completion=*/time_to_completion, /*is_url_real_time=*/false); + } + std::unique_ptr<MockSafeBrowsingLookupMechanism> + CreateSyncHashDatabaseMechanism() { + return std::make_unique<MockSafeBrowsingLookupMechanism>( + /*is_safe_synchronously=*/true, + /*threat_type=*/SB_THREAT_TYPE_SAFE, // not used + /*time_to_completion=*/base::TimeDelta(), // not used + /*is_url_real_time=*/false); + } + std::unique_ptr<MockSafeBrowsingLookupMechanism> + CreateAsyncHashDatabaseMechanism(SBThreatType threat_type, + base::TimeDelta time_to_completion) { + return std::make_unique<MockSafeBrowsingLookupMechanism>( + /*is_safe_synchronously=*/false, + /*threat_type=*/threat_type, + /*time_to_completion=*/time_to_completion, + /*is_url_real_time=*/false); + } + + void VerifyLogs( + std::vector<base::TimeDelta> expected_urt_hpd_hprt_times_taken, + std::vector<bool> expected_urt_hpd_hprt_had_warnings, + AllInOneResult expected_warnings_result, + AllInOneResult expected_timed_out_result, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + VerifyLogsAllowingRedirects( + expected_urt_hpd_hprt_times_taken, expected_urt_hpd_hprt_times_taken, + expected_urt_hpd_hprt_had_warnings, /*expected_had_redirects=*/false, + expected_warnings_result, expected_timed_out_result, + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + void VerifyLogsAllowingRedirects( + std::vector<base::TimeDelta> expected_summed_urt_hpd_hprt_times_taken, + std::vector<base::TimeDelta> expected_max_urt_hpd_hprt_times_taken, + std::vector<bool> expected_urt_hpd_hprt_had_warnings, + bool expected_had_redirects, + AllInOneResult expected_warnings_result, + AllInOneResult expected_timed_out_result, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + auto expected_delayed_response_info = GetExpectedDelayedResponseInfo( + expected_summed_urt_hpd_hprt_times_taken, + will_process_response_time_taken, checker_on_io_self_destruct_time); + auto expected_urt_hpd_hprt_delayed_responses = + expected_delayed_response_info.urt_hpd_hprt_delayed_responses; + auto expected_delayed_response_result = + expected_delayed_response_info.delayed_response_result; + + DCHECK(expected_summed_urt_hpd_hprt_times_taken.size() == 3); + DCHECK(expected_max_urt_hpd_hprt_times_taken.size() == 3); + DCHECK(expected_urt_hpd_hprt_delayed_responses.size() == 3); + DCHECK(expected_urt_hpd_hprt_had_warnings.size() == 3); + std::string histogram_prefix = + expected_had_redirects ? "SafeBrowsing.HPRTExperiment.Redirects." + : "SafeBrowsing.HPRTExperiment."; + std::vector<std::string> mechanisms = {"URT", "HPD", "HPRT"}; + + for (auto i = 0; i < 3; i++) { + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + mechanisms[i] + ".TimeTaken", + /*expected_count=*/1); + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + mechanisms[i] + ".TimedOut", + /*sample=*/expected_max_urt_hpd_hprt_times_taken[i] > + base::Seconds(5), + /*expected_bucket_count=*/1); + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + mechanisms[i] + ".DelayedResponse", + /*sample=*/expected_urt_hpd_hprt_delayed_responses[i], + /*expected_bucket_count=*/1); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + mechanisms[i] + ".DelayedResponseAmount", + /*expected_count=*/expected_urt_hpd_hprt_delayed_responses[i] == + UnknownNoYesResult::kUnknown + ? 0 + : 1); + if (expected_urt_hpd_hprt_delayed_responses[i] == + UnknownNoYesResult::kNo) { + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + mechanisms[i] + + ".DelayedResponseAmount", + /*sample=*/0, + /*expected_bucket_count=*/1); + } + } + + bool urt_faster_than_hpd = expected_summed_urt_hpd_hprt_times_taken[0] < + expected_summed_urt_hpd_hprt_times_taken[1]; + bool urt_faster_than_hprt = expected_summed_urt_hpd_hprt_times_taken[0] < + expected_summed_urt_hpd_hprt_times_taken[2]; + bool hpd_faster_than_hprt = expected_summed_urt_hpd_hprt_times_taken[1] < + expected_summed_urt_hpd_hprt_times_taken[2]; + + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "URTFasterThanHPDAmount", + /*expected_count=*/urt_faster_than_hpd ? 1 : 0); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "HPDFasterThanURTAmount", + /*expected_count=*/urt_faster_than_hpd ? 0 : 1); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "URTFasterThanHPRTAmount", + /*expected_count=*/urt_faster_than_hprt ? 1 : 0); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "HPRTFasterThanURTAmount", + /*expected_count=*/urt_faster_than_hprt ? 0 : 1); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "HPDFasterThanHPRTAmount", + /*expected_count=*/hpd_faster_than_hprt ? 1 : 0); + histogram_tester_->ExpectTotalCount( + /*name=*/histogram_prefix + "HPRTFasterThanHPDAmount", + /*expected_count=*/hpd_faster_than_hprt ? 0 : 1); + + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + "WarningsResult", + /*sample=*/expected_warnings_result, + /*expected_bucket_count=*/1); + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + "TimedOutResult", + /*sample=*/expected_timed_out_result, + /*expected_bucket_count=*/1); + if (expected_delayed_response_result.has_value()) { + histogram_tester_->ExpectUniqueSample( + /*name=*/histogram_prefix + "DelayedResponseResult", + /*sample=*/expected_delayed_response_result.value(), + /*expected_bucket_count=*/1); + } + } + + UnknownNoYesResult ToUnknownNoYesResult(bool input, + bool should_be_unknown = false) { + if (should_be_unknown) { + return UnknownNoYesResult::kUnknown; + } + return input ? UnknownNoYesResult::kYes : UnknownNoYesResult::kNo; + } + + DelayedResponseInfo GetExpectedDelayedResponseInfo( + std::vector<base::TimeDelta> expected_urt_hpd_hprt_times_taken, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + auto will_process_response_completes = + will_process_response_time_taken < checker_on_io_self_destruct_time; + auto urt_delayed_response = + expected_urt_hpd_hprt_times_taken[0] > will_process_response_time_taken; + auto hpd_delayed_response = + expected_urt_hpd_hprt_times_taken[1] > will_process_response_time_taken; + auto hprt_delayed_response = + expected_urt_hpd_hprt_times_taken[2] > will_process_response_time_taken; + auto expected_delayed_response_result = + will_process_response_completes + ? absl::optional<AllInOneResult>(Experimenter::CombineBoolResults( + urt_delayed_response, hpd_delayed_response, + hprt_delayed_response)) + : absl::nullopt; + + auto expected_urt_hpd_hprt_delayed_responses = { + ToUnknownNoYesResult( + urt_delayed_response, + /*should_be_unknown=*/!will_process_response_completes), + ToUnknownNoYesResult( + hpd_delayed_response, + /*should_be_unknown=*/!will_process_response_completes), + ToUnknownNoYesResult( + hprt_delayed_response, + /*should_be_unknown=*/!will_process_response_completes)}; + + DelayedResponseInfo info; + info.delayed_response_result = expected_delayed_response_result; + info.urt_hpd_hprt_delayed_responses = + expected_urt_hpd_hprt_delayed_responses; + return info; + } + + // Helper function for that runs different orderings of mechanism completions + // / WillProcessResponse reached / CheckerOnIO destruction. The goal of this + // is to ensure that the lifetime of the experimenter is handled correctly, as + // well as to ensure that all results are included in the final logs. + void RunLifetimesTest(std::vector<base::TimeDelta> urt_hpd_hprt_times_taken, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time, + bool will_be_canceled) { + base::MockCallback<CompleteCheckCallbackWithTimeout> + url_real_time_result_callback; + EXPECT_CALL(url_real_time_result_callback, + Run(false, Matches(SB_THREAT_TYPE_SAFE))) + .Times(will_be_canceled ? 0 : 1); + SetUpExperimenterAndChecks( + urt_hpd_hprt_times_taken, + /*urt_hpd_hprt_threat_types=*/ + {SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE}, + will_process_response_time_taken, checker_on_io_self_destruct_time, + url_real_time_result_callback.Get()); + + task_environment_.FastForwardUntilNoTasksRemain(); + + if (will_be_canceled) { + EXPECT_EQ(histogram_tester_->GetAllHistogramsRecorded().size(), 0u); + } else { + VerifyLogs( + /*expected_urt_hpd_hprt_times_taken=*/urt_hpd_hprt_times_taken, + /*expected_urt_hpd_hprt_had_warnings=*/{false, false, false}, + /*expected_warnings_result=*/AllInOneResult::kNoMechanism, + /*expected_timed_out_result=*/AllInOneResult::kNoMechanism, + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + } + + // Similar to RunLifetimesTest except that |RunChecks| is called a total of 3 + // times on the same experimenter. + void RunLifetimesWithTwoRedirectsTest( + std::vector<std::vector<base::TimeDelta>> urt_hpd_hprt_times_taken, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + DCHECK(urt_hpd_hprt_times_taken.size() == 3u); + std::vector<SBThreatType> all_safe = { + SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE}; + std::vector<bool> all_in_time = {false, false, false}; + RunRedirectsTestBase( + {all_safe, all_safe, all_safe}, urt_hpd_hprt_times_taken, + {all_in_time, all_in_time, all_in_time}, + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + + // Similar to RunWarningsTest except that |RunChecks| is called a total of 3 + // times on the same experimenter. + void RunWarningsWithTwoRedirectsTest( + std::vector<std::vector<SBThreatType>> urt_hpd_hprt_threat_types) { + auto urt_hpd_hprt_times_taken = {base::Seconds(2), base::Seconds(1), + base::Seconds(3)}; + auto will_process_response_time_taken = base::Seconds(12); + auto checker_on_io_self_destruct_time = base::Seconds(15); + std::vector<bool> all_in_time = {false, false, false}; + RunRedirectsTestBase(urt_hpd_hprt_threat_types, + {urt_hpd_hprt_times_taken, urt_hpd_hprt_times_taken, + urt_hpd_hprt_times_taken}, + {all_in_time, all_in_time, all_in_time}, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + } + + // Similar to RunTimeoutTest except that |RunChecks| is called a total of 3 + // times on the same experimenter. + void RunTimeoutWithTwoRedirectsTest( + std::vector<std::vector<bool>> urt_hpd_hprt_time_outs) { + std::vector<std::vector<base::TimeDelta>> urt_hpd_hprt_times_taken = { + {urt_hpd_hprt_time_outs[0][0] ? base::Seconds(6) : base::Seconds(0.1), + urt_hpd_hprt_time_outs[0][1] ? base::Seconds(6) : base::Seconds(0.2), + urt_hpd_hprt_time_outs[0][2] ? base::Seconds(6) : base::Seconds(0.3)}, + {urt_hpd_hprt_time_outs[1][0] ? base::Seconds(6) : base::Seconds(1.1), + urt_hpd_hprt_time_outs[1][1] ? base::Seconds(6) : base::Seconds(1.2), + urt_hpd_hprt_time_outs[1][2] ? base::Seconds(6) : base::Seconds(1.3)}, + {urt_hpd_hprt_time_outs[2][0] ? base::Seconds(6) : base::Seconds(2.1), + urt_hpd_hprt_time_outs[2][1] ? base::Seconds(6) : base::Seconds(2.2), + urt_hpd_hprt_time_outs[2][2] ? base::Seconds(6) : base::Seconds(2.3)}}; + auto will_process_response_time_taken = base::Seconds(20); + auto checker_on_io_self_destruct_time = base::Seconds(25); + std::vector<SBThreatType> all_safe = { + SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_SAFE}; + RunRedirectsTestBase({all_safe, all_safe, all_safe}, + urt_hpd_hprt_times_taken, urt_hpd_hprt_time_outs, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + } + + // Used by the RunRedirectsTestBase function to add 2 redirect checks. + void CallbackForRedirects( + scoped_refptr<Experimenter> experimenter, + std::vector<std::vector<base::TimeDelta>> urt_hpd_hprt_times_taken, + std::vector<std::vector<SBThreatType>> urt_hpd_hprt_threat_types, + int index, + bool timed_out, + absl::optional< + std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult>> + result) { + if (index == 3) { + // Only do 2 subsequent redirects. + return; + } + CreateAndRunChecks( + experimenter, + urt_hpd_hprt_times_taken[index], /*urt_hpd_hprt_threat_types=*/ + urt_hpd_hprt_threat_types[index], + base::BindOnce( + &SafeBrowsingLookupMechanismExperimenterTest::CallbackForRedirects, + base::Unretained(this), experimenter, urt_hpd_hprt_times_taken, + urt_hpd_hprt_threat_types, index + 1)); + } + + void RunRedirectsTestBase( + std::vector<std::vector<SBThreatType>> urt_hpd_hprt_threat_types, + std::vector<std::vector<base::TimeDelta>> urt_hpd_hprt_times_taken, + std::vector<std::vector<bool>> urt_hpd_hprt_time_outs, + base::TimeDelta will_process_response_time_taken, + base::TimeDelta checker_on_io_self_destruct_time) { + // Used for deciding which mechanism was faster and for deciding if a + // mechanism finished slower than WillProcessResponse. + std::vector<base::TimeDelta> summed_urt_hpd_hprt_times_taken = { + urt_hpd_hprt_times_taken[0][0] + urt_hpd_hprt_times_taken[1][0] + + urt_hpd_hprt_times_taken[2][0], + urt_hpd_hprt_times_taken[0][1] + urt_hpd_hprt_times_taken[1][1] + + urt_hpd_hprt_times_taken[2][1], + urt_hpd_hprt_times_taken[0][2] + urt_hpd_hprt_times_taken[1][2] + + urt_hpd_hprt_times_taken[2][2], + }; + // Used for deciding if a specific lookup timed out. + std::vector<base::TimeDelta> max_urt_hpd_hprt_times_taken = { + std::max({urt_hpd_hprt_times_taken[0][0], + urt_hpd_hprt_times_taken[1][0], + urt_hpd_hprt_times_taken[2][0]}), + std::max({urt_hpd_hprt_times_taken[0][1], + urt_hpd_hprt_times_taken[1][1], + urt_hpd_hprt_times_taken[2][1]}), + std::max({urt_hpd_hprt_times_taken[0][2], + urt_hpd_hprt_times_taken[1][2], + urt_hpd_hprt_times_taken[2][2]}), + }; + // Run within a block to avoid this function having a reference to + // the experimenter keeping it alive. + { + scoped_refptr<Experimenter> experimenter = SetUpExperimenter( + will_process_response_time_taken, checker_on_io_self_destruct_time); + CreateAndRunChecks( + experimenter, urt_hpd_hprt_times_taken[0], + /*urt_hpd_hprt_threat_types=*/urt_hpd_hprt_threat_types[0], + base::BindOnce(&SafeBrowsingLookupMechanismExperimenterTest:: + CallbackForRedirects, + base::Unretained(this), experimenter, + urt_hpd_hprt_times_taken, urt_hpd_hprt_threat_types, + /*index=*/1)); + } + task_environment_.FastForwardUntilNoTasksRemain(); + + std::vector<bool> expected_urt_hpd_hprt_had_warnings = { + urt_hpd_hprt_threat_types[0][0] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[1][0] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[2][0] == SB_THREAT_TYPE_URL_PHISHING, + urt_hpd_hprt_threat_types[0][1] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[1][1] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[2][1] == SB_THREAT_TYPE_URL_PHISHING, + urt_hpd_hprt_threat_types[0][2] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[1][2] == SB_THREAT_TYPE_URL_PHISHING || + urt_hpd_hprt_threat_types[2][2] == SB_THREAT_TYPE_URL_PHISHING}; + std::vector<bool> expected_urt_hpd_hprt_time_outs = { + urt_hpd_hprt_time_outs[0][0] || urt_hpd_hprt_time_outs[1][0] || + urt_hpd_hprt_time_outs[2][0], + urt_hpd_hprt_time_outs[0][1] || urt_hpd_hprt_time_outs[1][1] || + urt_hpd_hprt_time_outs[2][1], + urt_hpd_hprt_time_outs[0][2] || urt_hpd_hprt_time_outs[1][2] || + urt_hpd_hprt_time_outs[2][2], + }; + VerifyLogsAllowingRedirects( + summed_urt_hpd_hprt_times_taken, max_urt_hpd_hprt_times_taken, + /*expected_urt_hpd_hprt_had_warnings=*/ + expected_urt_hpd_hprt_had_warnings, + /*expected_had_redirects=*/true, + /*expected_warnings_result=*/ + CombineBoolResults(expected_urt_hpd_hprt_had_warnings[0], + expected_urt_hpd_hprt_had_warnings[1], + expected_urt_hpd_hprt_had_warnings[2]), + /*expected_timed_out_result=*/ + CombineBoolResults(expected_urt_hpd_hprt_time_outs[0], + expected_urt_hpd_hprt_time_outs[1], + expected_urt_hpd_hprt_time_outs[2]), + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + + // Should be used to test different combinations of mechanisms resulting in + // warnings. + void RunWarningsTest(std::vector<SBThreatType> urt_hpd_hprt_threat_types) { + base::MockCallback<CompleteCheckCallbackWithTimeout> + url_real_time_result_callback; + EXPECT_CALL(url_real_time_result_callback, + Run(false, Matches(urt_hpd_hprt_threat_types[0]))) + .Times(1); + auto urt_hpd_hprt_times_taken = {base::Seconds(2), base::Seconds(1), + base::Seconds(3)}; + auto will_process_response_time_taken = base::Seconds(4); + auto checker_on_io_self_destruct_time = base::Seconds(4.5); + SetUpExperimenterAndChecks( + urt_hpd_hprt_times_taken, urt_hpd_hprt_threat_types, + will_process_response_time_taken, checker_on_io_self_destruct_time, + url_real_time_result_callback.Get()); + task_environment_.FastForwardUntilNoTasksRemain(); + auto warning_threat_types = { + SB_THREAT_TYPE_URL_PHISHING, SB_THREAT_TYPE_URL_MALWARE, + SB_THREAT_TYPE_URL_UNWANTED, SB_THREAT_TYPE_BILLING}; + std::vector<bool> expected_urt_hpd_hprt_had_warnings = { + base::Contains(warning_threat_types, urt_hpd_hprt_threat_types[0]), + base::Contains(warning_threat_types, urt_hpd_hprt_threat_types[1]), + base::Contains(warning_threat_types, urt_hpd_hprt_threat_types[2])}; + VerifyLogs( + /*expected_urt_hpd_hprt_times_taken=*/urt_hpd_hprt_times_taken, + expected_urt_hpd_hprt_had_warnings, + /*expected_warnings_result=*/ + Experimenter::CombineBoolResults(expected_urt_hpd_hprt_had_warnings[0], + expected_urt_hpd_hprt_had_warnings[1], + expected_urt_hpd_hprt_had_warnings[2]), + /*expected_timed_out_result=*/AllInOneResult::kNoMechanism, + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + + // Should be used to test different combinations of mechanisms resulting in + // timeouts. + void RunTimeoutTest(std::vector<bool> urt_hpd_hprt_time_out) { + base::MockCallback<CompleteCheckCallbackWithTimeout> + url_real_time_result_callback; + if (urt_hpd_hprt_time_out[0]) { + EXPECT_CALL(url_real_time_result_callback, + Run(true, testing::Eq(absl::nullopt))) + .Times(1); + } else { + EXPECT_CALL(url_real_time_result_callback, + Run(false, Matches((SB_THREAT_TYPE_URL_PHISHING)))) + .Times(1); + } + auto urt_hpd_hprt_times_taken = { + urt_hpd_hprt_time_out[0] ? base::Seconds(6) : base::Seconds(2), + urt_hpd_hprt_time_out[1] ? base::Seconds(6) : base::Seconds(1), + urt_hpd_hprt_time_out[2] ? base::Seconds(6) : base::Seconds(3)}; + auto will_process_response_time_taken = base::Seconds(4); + auto checker_on_io_self_destruct_time = base::Seconds(8); + SetUpExperimenterAndChecks( + urt_hpd_hprt_times_taken, /*urt_hpd_hprt_threat_types=*/ + {SB_THREAT_TYPE_URL_PHISHING, SB_THREAT_TYPE_URL_PHISHING, + SB_THREAT_TYPE_URL_PHISHING}, + will_process_response_time_taken, checker_on_io_self_destruct_time, + url_real_time_result_callback.Get()); + task_environment_.FastForwardUntilNoTasksRemain(); + std::vector<bool> expected_urt_hpd_hprt_had_warnings = { + !urt_hpd_hprt_time_out[0], !urt_hpd_hprt_time_out[1], + !urt_hpd_hprt_time_out[2]}; + VerifyLogs( + /*expected_urt_hpd_hprt_times_taken=*/urt_hpd_hprt_times_taken, + expected_urt_hpd_hprt_had_warnings, + /*expected_warnings_result=*/ + Experimenter::CombineBoolResults(expected_urt_hpd_hprt_had_warnings[0], + expected_urt_hpd_hprt_had_warnings[1], + expected_urt_hpd_hprt_had_warnings[2]), + /*expected_timed_out_result=*/ + Experimenter::CombineBoolResults(urt_hpd_hprt_time_out[0], + urt_hpd_hprt_time_out[1], + urt_hpd_hprt_time_out[2]), + will_process_response_time_taken, checker_on_io_self_destruct_time); + } + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + std::unique_ptr<base::HistogramTester> histogram_tester_ = + std::make_unique<base::HistogramTester>(); +}; + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestLifetimes) { + // Test that all the different permutations of time_taken for the 5 different + // MaybeCompleteExperiment events succeed. + // Intentionally include base::Seconds(0) as an option to test synchronous + // hash-prefix database lookups as well as async ones (see the description + // above |SetUpExperimenterAndChecks|). + // This excludes test cases that might cancel the check, which could cause the + // test to be flaky due to race conditions. + std::vector<base::TimeDelta> times = {base::Seconds(0), base::Seconds(1), + base::Seconds(2), base::Seconds(3), + base::Seconds(4)}; + do { + std::vector<base::TimeDelta> urt_hpd_hprt_times_taken = {times[0], times[1], + times[2]}; + base::TimeDelta will_process_response_time_taken = times[3]; + base::TimeDelta checker_on_io_self_destruct_time = times[4]; + if (urt_hpd_hprt_times_taken[0] < checker_on_io_self_destruct_time) { + RunLifetimesTest( + urt_hpd_hprt_times_taken, will_process_response_time_taken, + checker_on_io_self_destruct_time, /*will_be_canceled=*/false); + ResetMetrics(); + } + } while (std::next_permutation(times.begin(), times.end())); +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestLifetimes_Canceled) { + std::vector<base::TimeDelta> urt_hpd_hprt_times_taken = { + base::Seconds(4), base::Seconds(3), base::Seconds(2)}; + base::TimeDelta will_process_response_time_taken = base::Seconds(5); + base::TimeDelta checker_on_io_self_destruct_time = base::Seconds(0); + RunLifetimesTest(urt_hpd_hprt_times_taken, will_process_response_time_taken, + checker_on_io_self_destruct_time, + /*will_be_canceled=*/true); + ResetMetrics(); +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestWarnings) { + std::vector<SBThreatType> threat_types = { + SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_URL_PHISHING, + SB_THREAT_TYPE_URL_MALWARE, SB_THREAT_TYPE_URL_UNWANTED, + SB_THREAT_TYPE_BILLING, SB_THREAT_TYPE_SUSPICIOUS_SITE}; + for (SBThreatType urt_threat_type : threat_types) { + for (SBThreatType hpd_threat_type : threat_types) { + for (SBThreatType hprt_threat_type : threat_types) { + RunWarningsTest({urt_threat_type, hpd_threat_type, hprt_threat_type}); + ResetMetrics(); + } + } + } +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestTimeouts) { + std::vector<bool> options = {false, true}; + for (bool urt_timeout : options) { + for (bool hpd_timeout : options) { + for (bool hprt_timeout : options) { + RunTimeoutTest({urt_timeout, hpd_timeout, hprt_timeout}); + ResetMetrics(); + } + } + } +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestEmptyExperiment) { + // After one second, calls into mechanism_experimenter's + // |OnBrowserUrlLoaderThrottleCheckerOnIODestructed|, which ends the + // experiment. + new PretendCheckerOnIO( + /*time_to_will_process_response=*/base::Seconds(3), + /*time_to_self_destruct=*/base::Seconds(1)); + task_environment_.FastForwardUntilNoTasksRemain(); + EXPECT_EQ(histogram_tester_->GetAllHistogramsRecorded().size(), 0u); +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestCombineBoolResults) { + struct TestCase { + bool url_real_time; + bool hash_database; + bool hash_real_time; + AllInOneResult expected_result; + } test_cases[] = { + {/*url_real_time=*/false, /*hash_database=*/false, + /*hash_real_time=*/false, + /*expected_result=*/AllInOneResult::kNoMechanism}, + {/*url_real_time=*/false, /*hash_database=*/false, + /*hash_real_time=*/true, + /*expected_result=*/AllInOneResult::kHashRealTimeOnly}, + {/*url_real_time=*/false, /*hash_database=*/true, + /*hash_real_time=*/false, + /*expected_result=*/AllInOneResult::kHashDatabaseOnly}, + {/*url_real_time=*/false, /*hash_database=*/true, /*hash_real_time=*/true, + /*expected_result=*/AllInOneResult::kHashDatabaseAndHashRealTime}, + {/*url_real_time=*/true, /*hash_database=*/false, + /*hash_real_time=*/false, + /*expected_result=*/AllInOneResult::kUrlRealTimeOnly}, + {/*url_real_time=*/true, /*hash_database=*/false, /*hash_real_time=*/true, + /*expected_result=*/AllInOneResult::kUrlRealTimeAndHashRealTime}, + {/*url_real_time=*/true, /*hash_database=*/true, /*hash_real_time=*/false, + /*expected_result=*/AllInOneResult::kUrlRealTimeAndHashDatabase}, + {/*url_real_time=*/true, /*hash_database=*/true, /*hash_real_time=*/true, + /*expected_result=*/AllInOneResult::kAllMechanisms}, + }; + for (const auto& test_case : test_cases) { + EXPECT_EQ( + CombineBoolResults(test_case.url_real_time, test_case.hash_database, + test_case.hash_real_time), + test_case.expected_result); + } +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestRedirectLifetimes) { + auto get_initial_times = []() { + std::vector<base::TimeDelta> times = {base::Seconds(0), base::Seconds(1), + base::Seconds(2)}; + return times; + }; + auto get_urt_hpd_hprt_times_taken = [](std::vector<base::TimeDelta> times) { + // The times have small increases on them to avoid ties between mechanisms + // for the total amount of time taken. + std::vector<base::TimeDelta> urt_hpd_hprt_times_taken = { + times[0] + base::Seconds(0.2), times[1], times[2] + base::Seconds(0.1)}; + return urt_hpd_hprt_times_taken; + }; + // Each test case kicks off a lookup with two subsequent redirects. The test + // cases consist of all permutations of time_taken for the 3 main mechanisms, + // with the WillProcessResponse and CheckerOnIO destruct times interspersed. + auto times = get_initial_times(); + do { + auto times2 = get_initial_times(); + do { + auto times3 = get_initial_times(); + do { + auto urt_hpd_hprt_times_taken = get_urt_hpd_hprt_times_taken(times); + auto urt_hpd_hprt_times_taken2 = get_urt_hpd_hprt_times_taken(times2); + auto urt_hpd_hprt_times_taken3 = get_urt_hpd_hprt_times_taken(times3); + auto urt_first_check_end_time = urt_hpd_hprt_times_taken[0]; + auto urt_last_check_begin_time = + urt_first_check_end_time + urt_hpd_hprt_times_taken2[0]; + auto urt_last_check_end_time = + urt_last_check_begin_time + urt_hpd_hprt_times_taken3[0]; + // WillProcessResponse after 2nd URT check + { + base::TimeDelta will_process_response_time_taken = + urt_last_check_begin_time + base::Seconds(0.5); + base::TimeDelta checker_on_io_self_destruct_time = base::Seconds(15); + RunLifetimesWithTwoRedirectsTest( + {urt_hpd_hprt_times_taken, urt_hpd_hprt_times_taken2, + urt_hpd_hprt_times_taken3}, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + ResetMetrics(); + } + // WillProcessResponse after 3rd URT check + { + base::TimeDelta will_process_response_time_taken = + urt_last_check_end_time + base::Seconds(0.5); + base::TimeDelta checker_on_io_self_destruct_time = base::Seconds(15); + RunLifetimesWithTwoRedirectsTest( + {urt_hpd_hprt_times_taken, urt_hpd_hprt_times_taken2, + urt_hpd_hprt_times_taken3}, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + ResetMetrics(); + } + // WillProcessResponse after all checks done + { + base::TimeDelta will_process_response_time_taken = base::Seconds(10); + base::TimeDelta checker_on_io_self_destruct_time = base::Seconds(15); + RunLifetimesWithTwoRedirectsTest( + {urt_hpd_hprt_times_taken, urt_hpd_hprt_times_taken2, + urt_hpd_hprt_times_taken3}, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + ResetMetrics(); + } + // CheckerOnIO destruct before WillProcessResponse has completed + { + base::TimeDelta will_process_response_time_taken = base::Seconds(15); + base::TimeDelta checker_on_io_self_destruct_time = + urt_last_check_end_time + base::Seconds(0.5); + RunLifetimesWithTwoRedirectsTest( + {urt_hpd_hprt_times_taken, urt_hpd_hprt_times_taken2, + urt_hpd_hprt_times_taken3}, + will_process_response_time_taken, + checker_on_io_self_destruct_time); + ResetMetrics(); + } + } while (std::next_permutation(times3.begin(), times3.end())); + } while (std::next_permutation(times2.begin(), times2.end())); + } while (std::next_permutation(times.begin(), times.end())); +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestRedirectWarnings) { + auto safe = SB_THREAT_TYPE_SAFE; + auto unsafe = SB_THREAT_TYPE_URL_PHISHING; + std::vector<std::vector<std::vector<SBThreatType>>> test_cases = { + // Each mechanism returns unsafe once (different lookups). + {{safe, safe, unsafe}, {safe, unsafe, safe}, {unsafe, safe, safe}}, + // Each mechanism returns unsafe once (same lookup). + {{safe, safe, safe}, {safe, safe, safe}, {unsafe, unsafe, unsafe}}, + // Only URL real-time is unsafe. + {{safe, safe, safe}, {safe, safe, safe}, {unsafe, safe, safe}}, + // Only hash-prefix database is unsafe. + {{safe, safe, safe}, {safe, safe, safe}, {safe, unsafe, safe}}, + // Only hash-prefix real-time is unsafe. + {{safe, safe, safe}, {safe, safe, safe}, {safe, safe, unsafe}}, + // Mechanisms return unsafe multiple times. + {{safe, unsafe, unsafe}, {safe, unsafe, safe}, {unsafe, safe, unsafe}}}; + for (const auto& test_case : test_cases) { + RunWarningsWithTwoRedirectsTest(test_case); + ResetMetrics(); + } +} + +TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestRedirectTimeouts) { + std::vector<std::vector<std::vector<bool>>> test_cases = { + // Each mechanism times out once (different lookups). + {{false, false, true}, {false, true, false}, {true, false, false}}, + // Each mechanism times out once (same lookup). + {{false, false, false}, {false, false, false}, {true, true, true}}, + // Only URL real-time times out. + {{false, false, false}, {false, false, false}, {true, false, false}}, + // Only hash-prefix database times out. + {{false, false, false}, {false, false, false}, {false, true, false}}, + // Only hash-prefix real-time times out. + {{false, false, false}, {false, false, false}, {false, false, true}}, + // Mechanisms time out multiple times. + {{false, true, true}, {false, true, false}, {true, false, true}}}; + for (const auto& test_case : test_cases) { + RunTimeoutWithTwoRedirectsTest(test_case); + ResetMetrics(); + } +} + +} // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.cc b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.cc index 4ca0e878..0c7bca7b 100644 --- a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.cc +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h" namespace safe_browsing { @@ -27,6 +28,7 @@ // Start a timer to abort the check if it takes too long. timer_->Start(FROM_HERE, base::Milliseconds(kCheckUrlTimeoutMs), this, &SafeBrowsingLookupMechanismRunner::OnTimeout); + start_lookup_time_ = base::TimeTicks::Now(); SafeBrowsingLookupMechanism::StartCheckResult result = lookup_mechanism_->StartCheck(base::BindOnce( @@ -38,6 +40,14 @@ return result; } +base::TimeDelta SafeBrowsingLookupMechanismRunner::GetRunDuration() { +#if DCHECK_IS_ON() + DCHECK(is_check_complete_); +#endif + DCHECK(!timer_->IsRunning()); + return end_lookup_time_ - start_lookup_time_; +} + void SafeBrowsingLookupMechanismRunner::OnCompleteCheckResult( std::unique_ptr<SafeBrowsingLookupMechanism::CompleteCheckResult> result) { OnCheckComplete(); @@ -60,8 +70,14 @@ is_check_complete_ = true; #endif timer_->Stop(); + end_lookup_time_ = base::TimeTicks::Now(); weak_factory_.InvalidateWeakPtrs(); lookup_mechanism_.reset(); } +void SafeBrowsingLookupMechanismRunner::SetLookupMechanismExperimenter( + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> experimenter) { + experimenter_ = experimenter; +} + } // namespace safe_browsing
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h index 11ab15ee..d516ef3 100644 --- a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h
@@ -10,6 +10,7 @@ #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism.h" namespace safe_browsing { +class SafeBrowsingLookupMechanismExperimenter; // This class is responsible for handling timeouts for running a specific Safe // Browsing mechanism lookup. It keeps a timer while the mechanism runs and @@ -37,6 +38,13 @@ // synchronously and was found to be safe. In that case, the callback passed // through the constructor will not be called. SafeBrowsingLookupMechanism::StartCheckResult Run(); + // Adds a reference from this object to the lookup mechanism experimenter so + // that the experimenter does not get destructed until after this object does. + void SetLookupMechanismExperimenter( + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> experimenter); + // Returns how long the run took. Should not be called until after the run has + // completed. + base::TimeDelta GetRunDuration(); private: // The function that the lookup mechanism calls into when its run completes. @@ -68,6 +76,14 @@ bool is_check_complete_ = false; #endif + // The time the run began. + base::TimeTicks start_lookup_time_; + // The time the run ended. + base::TimeTicks end_lookup_time_; + // Keep reference to experimenter to avoid it becoming destructed before the + // mechanism has completed. + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> experimenter_; + base::WeakPtrFactory<SafeBrowsingLookupMechanismRunner> weak_factory_{this}; };
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc index 805b2e8..93ba970b 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.cc
@@ -14,6 +14,7 @@ #include "components/safe_browsing/core/browser/db/database_manager.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/browser/hash_database_mechanism.h" +#include "components/safe_browsing/core/browser/hash_realtime_mechanism.h" #include "components/safe_browsing/core/browser/realtime/policy_engine.h" #include "components/safe_browsing/core/browser/realtime/url_lookup_service_base.h" #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism.h" @@ -127,7 +128,10 @@ GURL last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, - UrlRealTimeMechanism::WebUIDelegate* webui_delegate) + UrlRealTimeMechanism::WebUIDelegate* webui_delegate, + base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui, + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter) : headers_(headers), load_flags_(load_flags), request_destination_(request_destination), @@ -146,7 +150,9 @@ last_committed_url_(last_committed_url), ui_task_runner_(ui_task_runner), url_lookup_service_on_ui_(url_lookup_service_on_ui), - webui_delegate_(webui_delegate) { + webui_delegate_(webui_delegate), + hash_realtime_service_on_ui_(hash_realtime_service_on_ui), + mechanism_experimenter_(mechanism_experimenter) { DCHECK(!web_contents_getter_.is_null()); DCHECK(!can_rt_check_subresource_url_ || real_time_lookup_enabled_); DCHECK(real_time_lookup_enabled_ || can_check_db_); @@ -190,6 +196,10 @@ TRACE_EVENT_NESTABLE_ASYNC_END1("safe_browsing", "CheckUrl", TRACE_ID_LOCAL(this), "url", url.spec()); } + + if (mechanism_experimenter_) { + mechanism_experimenter_->OnSafeBrowsingUrlCheckerImplDestructed(); + } } void SafeBrowsingUrlCheckerImpl::CheckUrl(const GURL& url, @@ -347,6 +357,7 @@ std::move(rt_lookup_response)); state_ = STATE_DISPLAYING_BLOCKING_PAGE; + url_checker_delegate_->StartDisplayingBlockingPageHelper( resource, urls_[next_index_].method, headers_, request_destination_ == network::mojom::RequestDestination::kDocument, @@ -426,30 +437,8 @@ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("safe_browsing", "CheckUrl", TRACE_ID_LOCAL(this), "url", url.spec()); bool can_perform_full_url_lookup = CanPerformFullURLLookup(url); - base::UmaHistogramBoolean("SafeBrowsing.RT.CanCheckDatabase", - can_check_db_); - std::unique_ptr<SafeBrowsingLookupMechanism> lookup_mechanism; - if (can_perform_full_url_lookup) { - urls_[next_index_].did_perform_real_time_check = true; - lookup_mechanism = std::make_unique<UrlRealTimeMechanism>( - url, url_checker_delegate_->GetThreatTypes(), request_destination_, - database_manager_, can_check_db_, - can_check_high_confidence_allowlist_, - url_lookup_service_metric_suffix_, last_committed_url_, - ui_task_runner_, url_lookup_service_on_ui_, webui_delegate_); - } else { - lookup_mechanism = std::make_unique<HashDatabaseMechanism>( - url, url_checker_delegate_->GetThreatTypes(), database_manager_, - can_check_db_); - } - DCHECK(!lookup_mechanism_runner_); - lookup_mechanism_runner_ = - std::make_unique<SafeBrowsingLookupMechanismRunner>( - std::move(lookup_mechanism), - base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnUrlResult, - weak_factory_.GetWeakPtr())); SafeBrowsingLookupMechanism::StartCheckResult start_check_result = - lookup_mechanism_runner_->Run(); + KickOffLookupMechanism(url, can_perform_full_url_lookup); urls_[next_index_].did_check_allowlist = start_check_result.did_check_url_real_time_allowlist; @@ -488,6 +477,47 @@ } } +SafeBrowsingLookupMechanism::StartCheckResult +SafeBrowsingUrlCheckerImpl::KickOffLookupMechanism( + const GURL& url, + bool can_perform_full_url_lookup) { + base::UmaHistogramBoolean("SafeBrowsing.RT.CanCheckDatabase", can_check_db_); + std::unique_ptr<SafeBrowsingLookupMechanism> lookup_mechanism; + DCHECK(!lookup_mechanism_runner_); + if (can_perform_full_url_lookup) { + urls_[next_index_].did_perform_real_time_check = true; + if (can_check_db_ && mechanism_experimenter_ && + HashRealTimeMechanism::CanCheckUrl(url, request_destination_)) { + return mechanism_experimenter_->RunChecks( + base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnUrlResult, + weak_factory_.GetWeakPtr()), + url, url_checker_delegate_->GetThreatTypes(), request_destination_, + database_manager_, can_check_db_, + can_check_high_confidence_allowlist_, + url_lookup_service_metric_suffix_, last_committed_url_, + ui_task_runner_, url_lookup_service_on_ui_, webui_delegate_, + hash_realtime_service_on_ui_); + } else { + lookup_mechanism = std::make_unique<UrlRealTimeMechanism>( + url, url_checker_delegate_->GetThreatTypes(), request_destination_, + database_manager_, can_check_db_, + can_check_high_confidence_allowlist_, + url_lookup_service_metric_suffix_, last_committed_url_, + ui_task_runner_, url_lookup_service_on_ui_, webui_delegate_); + } + } else { + lookup_mechanism = std::make_unique<HashDatabaseMechanism>( + url, url_checker_delegate_->GetThreatTypes(), database_manager_, + can_check_db_); + } + lookup_mechanism_runner_ = + std::make_unique<SafeBrowsingLookupMechanismRunner>( + std::move(lookup_mechanism), + base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnUrlResult, + weak_factory_.GetWeakPtr())); + return lookup_mechanism_runner_->Run(); +} + void SafeBrowsingUrlCheckerImpl::BlockAndProcessUrls(bool showed_interstitial) { DVLOG(1) << "SafeBrowsingUrlCheckerImpl blocks URL: " << urls_[next_index_].url;
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h index cebc99c..ab1d899 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h
@@ -13,6 +13,8 @@ #include "base/sequence_checker.h" #include "base/task/sequenced_task_runner.h" #include "components/safe_browsing/core/browser/db/database_manager.h" +#include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" +#include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.h" #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" #include "components/safe_browsing/core/browser/url_realtime_mechanism.h" #include "components/safe_browsing/core/common/proto/realtimeapi.pb.h" @@ -99,7 +101,10 @@ GURL last_committed_url, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service_on_ui, - UrlRealTimeMechanism::WebUIDelegate* webui_delegate); + UrlRealTimeMechanism::WebUIDelegate* webui_delegate, + base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui, + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter); // Constructor that takes only a RequestDestination, a UrlCheckerDelegate, and // real-time lookup-related arguments, omitting other arguments that never @@ -202,6 +207,13 @@ // real time lookups. bool CanPerformFullURLLookup(const GURL& url); + // This will decide which mechanism to use for a lookup and then perform it. + // This may include running a SafeBrowsingLookupMechanism experiment if + // eligible. + SafeBrowsingLookupMechanism::StartCheckResult KickOffLookupMechanism( + const GURL& url, + bool can_perform_full_url_lookup); + SBThreatType CheckWebUIUrls(const GURL& url); // Returns false if this object has been destroyed by the callback. In that @@ -213,7 +225,7 @@ SBThreatType threat_type, const ThreatMetadata& metadata, bool is_from_real_time_check, - std::unique_ptr<RTLookupResponse> response); + std::unique_ptr<RTLookupResponse> rt_lookup_response); enum State { // Haven't started checking or checking is complete. @@ -318,6 +330,16 @@ // contract. raw_ptr<UrlRealTimeMechanism::WebUIDelegate> webui_delegate_ = nullptr; + // This object is used to perform the hash-prefix real-time lookup. It can + // only be accessed on the UI thread. + base::WeakPtr<HashRealTimeService> hash_realtime_service_on_ui_; + + // If eligible, this class will run a SafeBrowsingLookupMechanism experiment + // instead of just running a real-time URL check. It will check if the + // experiment is eligible and then perform it through this object. + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter_; + base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_{this}; };
diff --git a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc index dcfe411..53eee5f 100644 --- a/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc +++ b/components/safe_browsing/core/browser/safe_browsing_url_checker_impl_unittest.cc
@@ -308,6 +308,55 @@ bool is_cached_response_ = false; }; +class MockHashRealTimeService : public HashRealTimeService { + public: + MockHashRealTimeService() + : HashRealTimeService( + /*url_loader_factory=*/nullptr, + /*cache_manager=*/nullptr, + /*get_is_enhanced_protection_enabled=*/base::NullCallback()) {} + base::WeakPtr<MockHashRealTimeService> GetWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + struct UrlDetail { + absl::optional<SBThreatType> threat_type; + bool should_fail_lookup; + }; + + // |should_complete_lookup| should generally be true, unless you specifically + // want to test time-sensitive things like timeouts. Setting it to false will + // avoid calling into |response_callback| in |StartLookup|. + void SetThreatTypeForUrl(const GURL& gurl, + absl::optional<SBThreatType> threat_type, + bool should_fail_lookup) { + url_details_[gurl.spec()].threat_type = threat_type; + url_details_[gurl.spec()].should_fail_lookup = should_fail_lookup; + } + + void StartLookup( + const GURL& gurl, + HPRTLookupResponseCallback response_callback, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner) override { + std::string url = gurl.spec(); + ASSERT_TRUE(base::Contains(url_details_, url)); + callback_task_runner->PostTask( + FROM_HERE, + base::BindOnce( + std::move(response_callback), + /*is_lookup_successful=*/!url_details_[url].should_fail_lookup, + /*threat_type=*/url_details_[url].threat_type)); + } + + bool IsInBackoffMode() const override { return is_in_backoff_mode_; } + void EnableBackoffMode() { is_in_backoff_mode_ = true; } + + private: + base::flat_map<std::string, UrlDetail> url_details_; + bool is_in_backoff_mode_ = false; + base::WeakPtrFactory<MockHashRealTimeService> weak_factory_{this}; +}; + } // namespace class SafeBrowsingUrlCheckerTest : public PlatformTest { @@ -319,13 +368,26 @@ database_manager_ = new MockSafeBrowsingDatabaseManager(); url_checker_delegate_ = new MockUrlCheckerDelegate(database_manager_.get()); url_lookup_service_ = std::make_unique<MockRealTimeUrlLookupService>(); + hash_realtime_service_ = std::make_unique<MockHashRealTimeService>(); } std::unique_ptr<SafeBrowsingUrlCheckerImpl> CreateSafeBrowsingUrlChecker( bool real_time_lookup_enabled, - bool can_check_safe_browsing_db) { + bool can_check_safe_browsing_db, + bool is_lookup_mechanism_experiment_enabled = false) { base::MockCallback<base::RepeatingCallback<content::WebContents*()>> mock_web_contents_getter; + scoped_refptr<SafeBrowsingLookupMechanismExperimenter> + mechanism_experimenter = nullptr; + if (is_lookup_mechanism_experiment_enabled) { + mechanism_experimenter = + base::MakeRefCounted<SafeBrowsingLookupMechanismExperimenter>(); + // Tell the experimenter that WillProcessResponse has been reached so that + // once the mechanisms complete, the experiment concludes and all memory + // is cleaned up. Otherwise, this will cause memory leaks in the test. + mechanism_experimenter->OnWillProcessResponseReached( + base::TimeTicks::Now()); + } return std::make_unique<SafeBrowsingUrlCheckerImpl>( net::HttpRequestHeaders(), /*load_flags=*/0, network::mojom::RequestDestination::kDocument, @@ -340,7 +402,9 @@ /*last_committed_url=*/GURL(), base::SequencedTaskRunner::GetCurrentDefault(), real_time_lookup_enabled ? url_lookup_service_->GetWeakPtr() : nullptr, - /*webui_delegate_=*/nullptr); + /*webui_delegate_=*/nullptr, + /*hash_realtime_service=*/hash_realtime_service_->GetWeakPtr(), + /*mechanism_experimenter=*/mechanism_experimenter); } // This can be used as the CheckUrl callback in cases where it's a local check @@ -363,6 +427,7 @@ scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_; scoped_refptr<MockUrlCheckerDelegate> url_checker_delegate_; std::unique_ptr<MockRealTimeUrlLookupService> url_lookup_service_; + std::unique_ptr<MockHashRealTimeService> hash_realtime_service_; base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeUrlCheckNotifier> slow_check_notifier_callback_; base::test::ScopedFeatureList scoped_feature_list_; @@ -541,7 +606,7 @@ // The false positive metric should not be logged, because the // verdict is not from cache. histograms.ExpectTotalCount("SafeBrowsing.RT.GetCache.FallbackThreatType", - /*count=*/0); + /*expected_count=*/0); } TEST_F(SafeBrowsingUrlCheckerTest, CheckUrl_RealTimeEnabledSafeUrlFromCache) { @@ -743,6 +808,44 @@ task_environment_.RunUntilIdle(); } +TEST_F(SafeBrowsingUrlCheckerTest, CheckUrl_RealTimeEnabledRedirectUrlsSafe) { + auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( + /*real_time_lookup_enabled=*/true, + /*can_check_safe_browsing_db=*/true); + + GURL origin_url("https://example.test/"); + database_manager_->SetAllowlistResultForUrl(origin_url, false); + url_lookup_service_->SetThreatTypeForUrl(origin_url, SB_THREAT_TYPE_SAFE, + /*should_complete_lookup=*/true); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + origin_callback; + EXPECT_CALL(origin_callback, + Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/true, + /*did_check_allowlist=*/true)); + EXPECT_CALL(*url_checker_delegate_, + StartDisplayingBlockingPageHelper(_, _, _, _, _)) + .Times(0); + safe_browsing_url_checker->CheckUrl(origin_url, "GET", origin_callback.Get()); + + GURL redirect_url("https://example.redirect.test/"); + database_manager_->SetAllowlistResultForUrl(redirect_url, false); + url_lookup_service_->SetThreatTypeForUrl(redirect_url, SB_THREAT_TYPE_SAFE, + /*should_complete_lookup=*/true); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + redirect_callback; + EXPECT_CALL(redirect_callback, + Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/true, + /*did_check_allowlist=*/true)); + safe_browsing_url_checker->CheckUrl(redirect_url, "GET", + redirect_callback.Get()); + + task_environment_.RunUntilIdle(); +} + TEST_F(SafeBrowsingUrlCheckerTest, CheckUrl_CancelCheckOnDestruct) { // Do not cancel check for real-time checks. { @@ -841,4 +944,158 @@ } } +// Same as CheckUrl_SafeUrl but with the lookup mechanism experiment enabled. +TEST_F(SafeBrowsingUrlCheckerTest, CheckUrl_SafeUrl_LookupMechanismExperiment) { + base::HistogramTester histograms; + auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( + /*real_time_lookup_enabled=*/false, /*can_check_safe_browsing_db=*/true, + /*is_lookup_mechanism_experiment_enabled=*/true); + + GURL url("https://example.test/"); + database_manager_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_SAFE, + /*delayed_callback=*/false); + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + callback; + EXPECT_CALL(callback, + Run(nullptr, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/false, + /*did_check_allowlist=*/false)); + EXPECT_CALL(*url_checker_delegate_, + StartDisplayingBlockingPageHelper(_, _, _, _, _)) + .Times(0); + + safe_browsing_url_checker->CheckUrl(url, "GET", callback.Get()); + task_environment_.RunUntilIdle(); + histograms.ExpectUniqueSample("SafeBrowsing.CheckUrl.Timeout", + /*sample=*/false, + /*expected_bucket_count=*/1); +} + +// Same as CheckUrl_RealTimeEnabledAllowlistMatch but with the lookup mechanism +// experiment enabled. +TEST_F(SafeBrowsingUrlCheckerTest, + CheckUrl_RealTimeEnabledAllowlistMatch_LookupMechanismExperiment) { + auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( + /*real_time_lookup_enabled=*/true, /*can_check_safe_browsing_db=*/true, + /*is_lookup_mechanism_experiment_enabled=*/true); + + GURL url("https://example.test/"); + database_manager_->SetAllowlistResultForUrl(url, true); + // To make sure hash based check is not skipped when the URL is in the + // allowlist, set threat type to phishing for hash based check. + database_manager_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_URL_PHISHING, + /*delayed_callback=*/false); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + callback; + // Note that the callback is not called, because resource fetch is not blocked + // while we perform a real time URL check. + EXPECT_CALL(callback, Run(_, _, _, _, _)).Times(0); + EXPECT_CALL(*url_checker_delegate_, + StartDisplayingBlockingPageHelper( + IsSameThreatSource(ThreatSource::UNKNOWN), _, _, _, _)) + .Times(1); + + safe_browsing_url_checker->CheckUrl(url, "GET", callback.Get()); + + task_environment_.RunUntilIdle(); +} + +// Same as CheckUrl_RealTimeEnabledSafeUrl but with the lookup mechanism +// experiment enabled. +TEST_F(SafeBrowsingUrlCheckerTest, + CheckUrl_RealTimeEnabledSafeUrl_LookupMechanismExperiment) { + base::HistogramTester histograms; + auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( + /*real_time_lookup_enabled=*/true, /*can_check_safe_browsing_db=*/true, + /*is_lookup_mechanism_experiment_enabled=*/true); + + GURL url("https://example.test/"); + database_manager_->SetAllowlistResultForUrl(url, false); + url_lookup_service_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_SAFE, + /*should_complete_lookup=*/true); + database_manager_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_URL_PHISHING, + /*delayed_callback=*/false); + hash_realtime_service_->SetThreatTypeForUrl(url, SB_THREAT_TYPE_URL_PHISHING, + /*should_fail_lookup=*/false); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + callback; + EXPECT_CALL(callback, Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/true, + /*did_check_allowlist=*/true)); + EXPECT_CALL(*url_checker_delegate_, + StartDisplayingBlockingPageHelper(_, _, _, _, _)) + .Times(0); + safe_browsing_url_checker->CheckUrl(url, "GET", callback.Get()); + + task_environment_.RunUntilIdle(); + histograms.ExpectUniqueSample("SafeBrowsing.CheckUrl.Timeout", + /*sample=*/false, + /*expected_bucket_count=*/1); + + // The false positive metric should not be logged, because the + // verdict is not from cache. + histograms.ExpectTotalCount("SafeBrowsing.RT.GetCache.FallbackThreatType", + /*expected_count=*/0); +} + +// Same as CheckUrl_RealTimeEnabledRedirectUrlsSafe but with the lookup +// mechanism experiment enabled. +TEST_F(SafeBrowsingUrlCheckerTest, + CheckUrl_RealTimeEnabledRedirectUrlsSafe_LookupMechanismExperiment) { + auto safe_browsing_url_checker = CreateSafeBrowsingUrlChecker( + /*real_time_lookup_enabled=*/true, + /*can_check_safe_browsing_db=*/true, + /*is_lookup_mechanism_experiment_enabled=*/true); + + GURL origin_url("https://example.test/"); + // Sanity check only the URL real-time result is used by setting the other + // mechanism responses to phishing. + database_manager_->SetThreatTypeForUrl(origin_url, + SB_THREAT_TYPE_URL_PHISHING, + /*delayed_callback=*/false); + url_lookup_service_->SetThreatTypeForUrl(origin_url, SB_THREAT_TYPE_SAFE, + /*should_complete_lookup=*/true); + hash_realtime_service_->SetThreatTypeForUrl(origin_url, + SB_THREAT_TYPE_URL_PHISHING, + /*should_fail_lookup=*/false); + database_manager_->SetAllowlistResultForUrl(origin_url, false); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + origin_callback; + EXPECT_CALL(origin_callback, + Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/true, + /*did_check_allowlist=*/true)); + EXPECT_CALL(*url_checker_delegate_, + StartDisplayingBlockingPageHelper(_, _, _, _, _)) + .Times(0); + safe_browsing_url_checker->CheckUrl(origin_url, "GET", origin_callback.Get()); + + GURL redirect_url("https://example.redirect.test/"); + // Sanity check only the URL real-time result is used by setting the other + // mechanism responses to phishing. + database_manager_->SetThreatTypeForUrl(redirect_url, + SB_THREAT_TYPE_URL_PHISHING, + /*delayed_callback=*/false); + url_lookup_service_->SetThreatTypeForUrl(redirect_url, SB_THREAT_TYPE_SAFE, + /*should_complete_lookup=*/true); + hash_realtime_service_->SetThreatTypeForUrl(redirect_url, + SB_THREAT_TYPE_URL_PHISHING, + /*should_fail_lookup=*/false); + database_manager_->SetAllowlistResultForUrl(redirect_url, false); + + base::MockCallback<SafeBrowsingUrlCheckerImpl::NativeCheckUrlCallback> + redirect_callback; + EXPECT_CALL(redirect_callback, + Run(_, /*proceed=*/true, /*showed_interstitial=*/false, + /*did_perform_real_time_check=*/true, + /*did_check_allowlist=*/true)); + safe_browsing_url_checker->CheckUrl(redirect_url, "GET", + redirect_callback.Get()); + + task_environment_.RunUntilIdle(); +} + } // namespace safe_browsing
diff --git a/components/safe_browsing/core/common/fbs/client_model.fbs b/components/safe_browsing/core/common/fbs/client_model.fbs index c1c009c..813f132 100644 --- a/components/safe_browsing/core/common/fbs/client_model.fbs +++ b/components/safe_browsing/core/common/fbs/client_model.fbs
@@ -70,6 +70,7 @@ table Threshold { label:string; threshold:float; + esb_threshold:float; } namespace safe_browsing.flat;
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc index 95931100..f40431b 100644 --- a/components/safe_browsing/core/common/features.cc +++ b/components/safe_browsing/core/common/features.cc
@@ -172,6 +172,10 @@ "SafeBrowsingEnterpriseCsd", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kSafeBrowsingLookupMechanismExperiment, + "SafeBrowsingLookupMechanismExperiment", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kSafeBrowsingRemoveCookiesInAuthRequests, "SafeBrowsingRemoveCookiesInAuthRequests", base::FEATURE_DISABLED_BY_DEFAULT); @@ -253,6 +257,7 @@ {&kSafeBrowsingCsbrrWithToken, true}, {&kSafeBrowsingDisableConsumerCsdForEnterprise, true}, {&kSafeBrowsingEnterpriseCsd, true}, + {&kSafeBrowsingLookupMechanismExperiment, true}, {&kSafeBrowsingRemoveCookiesInAuthRequests, true}, {&kSevenZipEvaluationEnabled, true}, {&kSimplifiedUrlDisplay, true}, @@ -281,8 +286,9 @@ base::Value::List GetFeatureStatusList() { base::Value::List param_list; for (const auto& feature_status : kExperimentalFeatures) { - if (feature_status.show_state) + if (feature_status.show_state) { AddFeatureAndAvailability(feature_status.feature, ¶m_list); + } } // Manually add experimental features that we want param values for.
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h index 529afc1c..ddad43b 100644 --- a/components/safe_browsing/core/common/features.h +++ b/components/safe_browsing/core/common/features.h
@@ -166,6 +166,14 @@ // with the appropriate policies enabled. BASE_DECLARE_FEATURE(kSafeBrowsingEnterpriseCsd); +// Controls whether the lookup mechanism experiment is enabled, which runs all +// three lookup mechanisms instead of just real-time URL lookups for ESB users. +// The other two lookup mechanisms are run in the background, and the results +// of the three are logged for comparison purposes. This experiment is also +// known as the hash-prefix real-time lookup experiment, since that mechanism is +// the main comparison anchor. +BASE_DECLARE_FEATURE(kSafeBrowsingLookupMechanismExperiment); + // Controls whether cookies are removed when the access token is present. BASE_DECLARE_FEATURE(kSafeBrowsingRemoveCookiesInAuthRequests);
diff --git a/components/safe_browsing/core/common/proto/client_model.proto b/components/safe_browsing/core/common/proto/client_model.proto index d5521afd..81e94e1c 100644 --- a/components/safe_browsing/core/common/proto/client_model.proto +++ b/components/safe_browsing/core/common/proto/client_model.proto
@@ -122,6 +122,9 @@ // The threshold value optional float threshold = 2; + + // The threshold value for ESB users + optional float esb_threshold = 3; } // The list of threshold values for each category in the TFLite model. Pages
diff --git a/components/security_interstitials/core/https_only_mode_allowlist.cc b/components/security_interstitials/core/https_only_mode_allowlist.cc index 43d13b8..625a3ec 100644 --- a/components/security_interstitials/core/https_only_mode_allowlist.cc +++ b/components/security_interstitials/core/https_only_mode_allowlist.cc
@@ -7,6 +7,7 @@ #include "base/containers/contains.h" #include "base/json/values_util.h" #include "base/time/clock.h" +#include "base/values.h" namespace { @@ -76,8 +77,8 @@ return false; } - auto* decision_expiration_value = - value.FindKey(kHTTPAllowlistExpirationTimeKey); + const base::Value* decision_expiration_value = + value.GetDict().Find(kHTTPAllowlistExpirationTimeKey); auto decision_expiration = base::ValueToTime(decision_expiration_value); if (decision_expiration <= clock_->Now()) { // Allowlist entry has expired.
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp index e9a50e7..51efa0d2 100644 --- a/components/security_interstitials_strings.grdp +++ b/components/security_interstitials_strings.grdp
@@ -104,7 +104,7 @@ The site ahead is blocked by your organization </message> <message name="IDS_ENTERPRISE_BLOCK_PRIMARY_PARAGRAPH" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL doesn't pass the filtering rules set by the admin."> - Your organization has blocked <ph name="BEGIN_BOLD"><strong></ph><ph name="DOMAIN">$1<ex>example.com</ex></ph><ph name="END_BOLD"></strong></ph> because it violates a policy. <ph name="BEGIN_LEARN_MORE_LINK"><a href="https://support.google.com/chrome/a/?p=block_warn" id="learn-more-link"></ph>Learn more<ph name="END_LEARN_MORE_LINK"></a></ph> + Your organization has blocked <ph name="BEGIN_BOLD"><strong></ph><ph name="DOMAIN">$1<ex>example.com</ex></ph><ph name="END_BOLD"></strong></ph> because it violates a policy. <ph name="BEGIN_LEARN_MORE_LINK"><a href="#" id="learn-more-link"></ph>Learn more<ph name="END_LEARN_MORE_LINK"></a></ph> </message> <message name="IDS_ENTERPRISE_BLOCK_GO_BACK" desc="The text for the button that takes the user back to safety."> Go back @@ -118,7 +118,7 @@ The site ahead is flagged by your organization </message> <message name="IDS_ENTERPRISE_WARN_PRIMARY_PARAGRAPH" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL doesn't pass the filtering rules set by the admin."> - Your organization has identified <ph name="BEGIN_BOLD"><strong></ph><ph name="DOMAIN">$1<ex>example.com</ex></ph><ph name="END_BOLD"></strong></ph> as a site that might violate a policy. <ph name="BEGIN_LEARN_MORE_LINK"><a href="https://support.google.com/chrome/a/?p=block_warn" id="learn-more-link"></ph>Learn more<ph name="END_LEARN_MORE_LINK"></a></ph> + Your organization has identified <ph name="BEGIN_BOLD"><strong></ph><ph name="DOMAIN">$1<ex>example.com</ex></ph><ph name="END_BOLD"></strong></ph> as a site that might violate a policy. <ph name="BEGIN_LEARN_MORE_LINK"><a href="#" id="learn-more-link"></ph>Learn more<ph name="END_LEARN_MORE_LINK"></a></ph> </message> <message name="IDS_ENTERPRISE_WARN_GO_BACK" desc="The text for the button that takes the user back to safety."> Go back
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn index 8871182..56b593d 100644 --- a/components/segmentation_platform/internal/BUILD.gn +++ b/components/segmentation_platform/internal/BUILD.gn
@@ -88,6 +88,8 @@ "execution/processing/query_processor.h", "execution/processing/sql_feature_processor.cc", "execution/processing/sql_feature_processor.h", + "execution/processing/sync_device_info_observer.cc", + "execution/processing/sync_device_info_observer.h", "execution/processing/uma_feature_processor.cc", "execution/processing/uma_feature_processor.h", "local_state_helper_impl.cc", @@ -152,8 +154,6 @@ "signals/user_action_signal_handler.h", "stats.cc", "stats.h", - "sync_device_info_observer.cc", - "sync_device_info_observer.h", "ukm_data_manager.h", "ukm_data_manager_impl.cc", "ukm_data_manager_impl.h", @@ -254,6 +254,7 @@ "execution/processing/mock_feature_list_query_processor.h", "execution/processing/query_processor.h", "execution/processing/sql_feature_processor_unittest.cc", + "execution/processing/sync_device_info_observer_unittest.cc", "metadata/metadata_utils_unittest.cc", "mock_ukm_data_manager.cc", "mock_ukm_data_manager.h", @@ -282,7 +283,6 @@ "signals/url_signal_handler_unittest.cc", "signals/user_action_signal_handler_unittest.cc", "stats_unittest.cc", - "sync_device_info_observer_unittest.cc", "ukm_data_manager_impl_unittest.cc", ]
diff --git a/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.cc b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.cc new file mode 100644 index 0000000..70cf176 --- /dev/null +++ b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.cc
@@ -0,0 +1,253 @@ +// 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 "components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h" + +#include "base/feature_list.h" +#include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/stringprintf.h" +#include "base/task/sequenced_task_runner.h" +#include "base/time/time.h" +#include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" +#include "components/segmentation_platform/public/types/processed_value.h" +#include "components/sync_device_info/device_info.h" +#include "components/sync_device_info/device_info_tracker.h" + +namespace segmentation_platform::processing { + +using OsType = syncer::DeviceInfo::OsType; +using FormFactor = syncer ::DeviceInfo::FormFactor; + +namespace { + +constexpr int kDefaultActiveDaysThreshold = 14; + +#define AS_FLOAT_VAL(x) ProcessedValue(static_cast<float>(x)) + +base::TimeDelta GetActivePeriodForMetrics() { + return base::Days(base::GetFieldTrialParamByFeatureAsInt( + kSegmentationDeviceCountByOsType, "active_days_threshold", + kDefaultActiveDaysThreshold)); +} + +base::TimeDelta Age(base::Time last_update, base::Time now) { + // Don't allow negative age for things somehow updated in the future. + return std::max(base::TimeDelta(), now - last_update); +} + +// Determines if a device with |last_update| timestamp should be considered +// active, given the current time. +bool IsDeviceActive(base::Time last_update, + base::Time now, + base::TimeDelta active_threshold) { + base::TimeDelta active_days_threshold = GetActivePeriodForMetrics(); + return Age(last_update, now) < active_days_threshold; +} + +// Keep the following in sync with variants in +// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml. +const char* ConvertOsTypeToString(OsType os_type) { + switch (os_type) { + case OsType::kWindows: + return "Windows"; + case OsType::kMac: + return "Mac"; + case OsType::kLinux: + return "Linux"; + case OsType::kIOS: + return "iOS"; + case OsType::kAndroid: + return "Android"; + case OsType::kChromeOsAsh: + return "ChromeOsAsh"; + case OsType::kChromeOsLacros: + return "ChromeOsLacros"; + case OsType::kFuchsia: + return "Fuchsia"; + case OsType::kUnknown: + return "Unknown"; + } +} + +} // namespace + +BASE_FEATURE(kSegmentationDeviceCountByOsType, + "SegmentationDeviceCountByOsType", + base::FEATURE_ENABLED_BY_DEFAULT); + +SyncDeviceInfoObserver::SyncDeviceInfoObserver( + syncer::DeviceInfoTracker* device_info_tracker) + : device_info_tracker_(device_info_tracker) { + DCHECK(device_info_tracker_); + device_info_tracker_->AddObserver(this); +} + +SyncDeviceInfoObserver::~SyncDeviceInfoObserver() { + device_info_tracker_->RemoveObserver(this); +} + +// Count device by os types and record them in UMA only if not recorded yet. +void SyncDeviceInfoObserver::OnDeviceInfoChange() { + if (!device_info_tracker_->IsSyncing() || + device_info_status_ == DeviceInfoStatus::INFO_AVAILABLE) { + return; + } + + device_info_status_ = DeviceInfoStatus::INFO_AVAILABLE; + + // Run any method calls that were received during initialization. + while (!pending_actions_.empty()) { + auto callback = std::move(pending_actions_.front()); + pending_actions_.pop_front(); + device_info_status_ = DeviceInfoStatus::INFO_AVAILABLE; + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), true)); + } + + // Record device count by OS types. + std::map<OsType, int> count_by_os_type = + CountActiveDevicesByOsType(GetActivePeriodForMetrics()); + + // Record UMA metrics of device counts by OS types. + // Record 0 when there are no devices associated with one OS type. + for (int os_type_idx = static_cast<int>(OsType::kUnknown); + os_type_idx <= static_cast<int>(OsType::kFuchsia); ++os_type_idx) { + OsType os_type = static_cast<OsType>(os_type_idx); + int count = count_by_os_type[os_type]; + base::UmaHistogramSparse( + base::StringPrintf("SegmentationPlatform.DeviceCountByOsType.%s", + ConvertOsTypeToString(os_type)), + std::min(count, 100)); + } +} + +std::map<OsType, int> SyncDeviceInfoObserver::CountActiveDevicesByOsType( + base::TimeDelta active_threshold) const { + std::map<OsType, int> count_by_os_type; + const base::Time now = base::Time::Now(); + for (const auto& device_info : device_info_tracker_->GetAllDeviceInfo()) { + if (!IsDeviceActive(device_info->last_updated_timestamp(), now, + active_threshold)) { + continue; + } + + auto os_type = device_info->os_type(); + count_by_os_type[os_type] += 1; + } + return count_by_os_type; +} + +void SyncDeviceInfoObserver::Process( + const proto::CustomInput& input, + const FeatureProcessorState& feature_processor_state, + ProcessedCallback callback) { + int wait_for_device_info_in_seconds = 0; + auto it = input.additional_args().find("wait_for_device_info_in_seconds"); + if (it != input.additional_args().end()) { + if (!base::StringToInt(it->second, &wait_for_device_info_in_seconds)) { + wait_for_device_info_in_seconds = 0; + } + } + + if (wait_for_device_info_in_seconds > 0 && + (device_info_status_ == DeviceInfoStatus::TIMEOUT_NOT_POSTED || + device_info_status_ == DeviceInfoStatus::TIMEOUT_POSTED_BUT_NOT_HIT)) { + pending_actions_.push_back(base::BindOnce( + &SyncDeviceInfoObserver::ReadyToFinishProcessing, + weak_ptr_factory_.GetWeakPtr(), input, std::move(callback))); + + if (device_info_status_ == DeviceInfoStatus::TIMEOUT_NOT_POSTED) { + device_info_status_ = DeviceInfoStatus::TIMEOUT_POSTED_BUT_NOT_HIT; + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&SyncDeviceInfoObserver::OnTimeout, + weak_ptr_factory_.GetWeakPtr()), + base::Seconds(wait_for_device_info_in_seconds)); + } + } else { + ReadyToFinishProcessing( + input, std::move(callback), + device_info_status_ == DeviceInfoStatus::INFO_AVAILABLE); + } +} + +void SyncDeviceInfoObserver::ReadyToFinishProcessing( + const proto::CustomInput& input, + ProcessedCallback callback, + bool success) { + if (!success) { + Tensor inputs(10, ProcessedValue(0.0f)); + inputs[0] = AS_FLOAT_VAL(1); // failure. + std::move(callback).Run(/*error=*/false, std::move(inputs)); + return; + } + + int active_threshold = kDefaultActiveDaysThreshold; + auto it2 = input.additional_args().find("active_days_limit"); + if (it2 != input.additional_args().end()) { + if (!base::StringToInt(it2->second, &active_threshold)) { + active_threshold = kDefaultActiveDaysThreshold; + } + } + std::map< + std::pair<syncer::DeviceInfo::FormFactor, syncer::DeviceInfo::OsType>, + int> + device_count_by_type; + int total_count = 0; + const base::Time now = base::Time::Now(); + for (const auto& device_info : device_info_tracker_->GetAllDeviceInfo()) { + if (!IsDeviceActive(device_info->last_updated_timestamp(), now, + base::Days(active_threshold))) { + continue; + } + + auto os_type = device_info->os_type(); + device_count_by_type[{device_info->form_factor(), os_type}] += 1; + total_count++; + } + + Tensor inputs(10, ProcessedValue(0.0f)); + inputs[0] = AS_FLOAT_VAL(0); // success. + inputs[1] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kPhone, OsType::kAndroid}])); + inputs[2] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kTablet, OsType::kAndroid}])); + inputs[3] = + AS_FLOAT_VAL((device_count_by_type[{FormFactor::kPhone, OsType::kIOS}])); + inputs[4] = + AS_FLOAT_VAL((device_count_by_type[{FormFactor::kTablet, OsType::kIOS}])); + inputs[5] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kDesktop, OsType::kLinux}])); + inputs[6] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kDesktop, OsType::kMac}])); + inputs[7] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kDesktop, OsType::kWindows}])); + inputs[8] = AS_FLOAT_VAL( + (device_count_by_type[{FormFactor::kDesktop, OsType::kChromeOsLacros}])); + int known_type_count = 0; + for (unsigned i = 1; i <= 8; ++i) { + known_type_count += inputs[i].float_val; + } + inputs[9] = AS_FLOAT_VAL(total_count - known_type_count); + std::move(callback).Run(/*error=*/false, std::move(inputs)); +} + +void SyncDeviceInfoObserver::OnTimeout() { + if (device_info_status_ == DeviceInfoStatus::INFO_AVAILABLE) { + return; + } + + device_info_status_ = DeviceInfoStatus::INFO_UNAVAILABLE; + + while (!pending_actions_.empty()) { + auto callback = std::move(pending_actions_.front()); + pending_actions_.pop_front(); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false)); + } + return; +} + +} // namespace segmentation_platform::processing \ No newline at end of file
diff --git a/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h new file mode 100644 index 0000000..32b4e36 --- /dev/null +++ b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h
@@ -0,0 +1,74 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_PROCESSING_SYNC_DEVICE_INFO_OBSERVER_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_PROCESSING_SYNC_DEVICE_INFO_OBSERVER_H_ + +#include "base/containers/circular_deque.h" +#include "base/feature_list.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "components/segmentation_platform/public/input_delegate.h" +#include "components/sync_device_info/device_info.h" +#include "components/sync_device_info/device_info_tracker.h" + +namespace segmentation_platform::processing { + +BASE_DECLARE_FEATURE(kSegmentationDeviceCountByOsType); + +class SyncDeviceInfoObserver : public syncer::DeviceInfoTracker::Observer, + public InputDelegate { + public: + // |device_info_tracker| must not be null and must outlive this object. + explicit SyncDeviceInfoObserver( + syncer::DeviceInfoTracker* device_info_tracker); + ~SyncDeviceInfoObserver() override; + + // DeviceInfoTracker::Observer overrides. + void OnDeviceInfoChange() override; + + // InputDelegate impl + void Process(const proto::CustomInput& input, + const FeatureProcessorState& feature_processor_state, + ProcessedCallback callback) override; + + private: + // Describes device info status for processing. + enum DeviceInfoStatus { + TIMEOUT_NOT_POSTED, + TIMEOUT_POSTED_BUT_NOT_HIT, + INFO_UNAVAILABLE, + INFO_AVAILABLE, + }; + + // Returns the count of active devices per os type. Each device is identified + // by one unique guid. No deduping is applied. + std::map<syncer::DeviceInfo::OsType, int> CountActiveDevicesByOsType( + base::TimeDelta active_threshold) const; + + // Called when ready to finish processing. + void ReadyToFinishProcessing(const proto::CustomInput& input, + ProcessedCallback callback, + bool success); + + void OnTimeout(); + + // Device info tracker. Not owned. It is managed by + // the DeviceInfoSynceService, which is guaranteed to outlive the + // SegmentationPlatformService, who owns this observer and depends on the + // DeviceInfoSyncService. + const raw_ptr<syncer::DeviceInfoTracker> device_info_tracker_; + + // Queue to put the pending actions request. + base::circular_deque<base::OnceCallback<void(bool)>> pending_actions_; + + // Describes device info status for processing. + DeviceInfoStatus device_info_status_{DeviceInfoStatus::TIMEOUT_NOT_POSTED}; + + base::WeakPtrFactory<SyncDeviceInfoObserver> weak_ptr_factory_{this}; +}; + +} // namespace segmentation_platform::processing + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_PROCESSING_SYNC_DEVICE_INFO_OBSERVER_H_ \ No newline at end of file
diff --git a/components/segmentation_platform/internal/execution/processing/sync_device_info_observer_unittest.cc b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer_unittest.cc new file mode 100644 index 0000000..747e96a6 --- /dev/null +++ b/components/segmentation_platform/internal/execution/processing/sync_device_info_observer_unittest.cc
@@ -0,0 +1,300 @@ +// 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 "components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h" + +#include "base/functional/bind.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/task_environment.h" +#include "components/segmentation_platform/internal/execution/processing/feature_processor_state.h" +#include "components/segmentation_platform/internal/metadata/metadata_writer.h" +#include "components/segmentation_platform/public/proto/model_metadata.pb.h" +#include "components/sync/protocol/sync_enums.pb.h" +#include "components/sync_device_info/device_info.h" +#include "components/sync_device_info/device_info_util.h" +#include "components/sync_device_info/fake_device_info_tracker.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace segmentation_platform::processing { + +namespace { + +#define AS_FLOAT_VAL(x) ProcessedValue(static_cast<float>(x)) + +using syncer::DeviceInfo; +using OsType = syncer::DeviceInfo::OsType; +using DeviceCountByOsTypeMap = std::map<OsType, int>; +using syncer::FakeDeviceInfoTracker; +using DeviceType = sync_pb::SyncEnums::DeviceType; +using DeviceCountByOsTypeMap = std::map<DeviceInfo::OsType, int>; + +const sync_pb::SyncEnums_DeviceType kLocalDeviceType = + sync_pb::SyncEnums_DeviceType_TYPE_LINUX; +const DeviceInfo::OsType kLocalDeviceOS = DeviceInfo::OsType::kLinux; +const DeviceInfo::FormFactor kLocalDeviceFormFactor = + DeviceInfo::FormFactor::kDesktop; + +std::unique_ptr<DeviceInfo> CreateDeviceInfo( + const std::string& guid, + DeviceType device_type, + OsType os_type, + base::Time last_updated = base::Time::Now()) { + return std::make_unique<DeviceInfo>( + guid, "name", "chrome_version", "user_agent", device_type, os_type, + kLocalDeviceFormFactor, "device_id", "manufacturer_name", "model_name", + "full_hardware_class", last_updated, + syncer::DeviceInfoUtil::GetPulseInterval(), + /*send_tab_to_self_receiving_enabled=*/false, absl::nullopt, + /*paask_info=*/absl::nullopt, + /*fcm_registration_token=*/std::string(), + /*interested_data_types=*/syncer::ModelTypeSet()); +} + +class SyncDeviceInfoObserverTest : public testing::Test { + public: + SyncDeviceInfoObserverTest() = default; + ~SyncDeviceInfoObserverTest() override = default; + + void SetUp() override { + device_info_tracker_ = std::make_unique<FakeDeviceInfoTracker>(); + sync_device_info_observer_ = + std::make_unique<SyncDeviceInfoObserver>(device_info_tracker_.get()); + } + + void TearDown() override { + sync_device_info_observer_.reset(); + device_info_tracker_.reset(); + } + + void OnProcessFinishedCallback(base::OnceClosure closure, + bool expected_error, + std::vector<float> expected_result, + bool actual_error, + Tensor actual_result) { + EXPECT_EQ(expected_error, actual_error); + for (int index = 0; index < 10; index++) { + EXPECT_EQ(actual_result[index].type, ProcessedValue::Type::FLOAT); + EXPECT_EQ(expected_result[index], actual_result[index].float_val); + } + std::move(closure).Run(); + } + + protected: + std::unique_ptr<FakeDeviceInfoTracker> device_info_tracker_; + std::unique_ptr<SyncDeviceInfoObserver> sync_device_info_observer_; + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_LocalDevice) { + base::HistogramTester histogram_tester; + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); + + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); +} + +TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_DifferentGuids) { + base::HistogramTester histogram_tester; + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + std::unique_ptr<DeviceInfo> local_device_info_2 = + CreateDeviceInfo("local_device_2", kLocalDeviceType, kLocalDeviceOS); + device_info_tracker_->Add( + {local_device_info.get(), local_device_info_2.get()}); + + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Linux", 2, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); +} + +TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_DifferentOS) { + base::HistogramTester histogram_tester; + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + std::unique_ptr<DeviceInfo> local_device_info_2 = + CreateDeviceInfo("local_device_2", kLocalDeviceType, OsType::kMac); + device_info_tracker_->Add( + {local_device_info.get(), local_device_info_2.get()}); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Mac", 1, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); +} + +TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_InactiveDevice) { + base::HistogramTester histogram_tester; + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + std::unique_ptr<DeviceInfo> local_device_info_2 = + CreateDeviceInfo("local_device_2", kLocalDeviceType, OsType::kMac, + base::Time::Now() - base::Days(20)); + device_info_tracker_->Add( + {local_device_info.get(), local_device_info_2.get()}); + + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); + histogram_tester.ExpectUniqueSample( + "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); +} + +TEST_F(SyncDeviceInfoObserverTest, AddingDeviceBeforeProcess) { + FeatureProcessorState state; + proto::SegmentationModelMetadata metadata; + MetadataWriter writer(&metadata); + + auto* sync_input = writer.AddCustomInput(MetadataWriter::CustomInput{ + .tensor_length = 10, + .fill_policy = proto::CustomInput::FILL_SYNC_DEVICE_INFO, + .name = "SyncDeviceInfo"}); + (*sync_input->mutable_additional_args())["wait_for_device_info_in_seconds"] = + "2"; + (*sync_input->mutable_additional_args())["active_days_limit"] = "14"; + + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); + + std::vector<float> expected_result = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0}; + base::RunLoop loop; + sync_device_info_observer_->Process( + *sync_input, state, + base::BindOnce(&SyncDeviceInfoObserverTest::OnProcessFinishedCallback, + base::Unretained(this), loop.QuitClosure(), false, + expected_result)); + loop.Run(); +} + +TEST_F(SyncDeviceInfoObserverTest, + ProcessWithTimeoutAndAddingDeviceWithoutWait) { + FeatureProcessorState state; + proto::SegmentationModelMetadata metadata; + MetadataWriter writer(&metadata); + + auto* sync_input = writer.AddCustomInput(MetadataWriter::CustomInput{ + .tensor_length = 10, + .fill_policy = proto::CustomInput::FILL_SYNC_DEVICE_INFO, + .name = "SyncDeviceInfo"}); + (*sync_input->mutable_additional_args())["wait_for_device_info_in_seconds"] = + "2"; + (*sync_input->mutable_additional_args())["active_days_limit"] = "14"; + + std::vector<float> expected_result = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0}; + base::RunLoop loop; + sync_device_info_observer_->Process( + *sync_input, state, + base::BindOnce(&SyncDeviceInfoObserverTest::OnProcessFinishedCallback, + base::Unretained(this), loop.QuitClosure(), false, + expected_result)); + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); + loop.Run(); +} + +TEST_F(SyncDeviceInfoObserverTest, ProcessWithNoTimeout) { + FeatureProcessorState state; + proto::SegmentationModelMetadata metadata; + MetadataWriter writer(&metadata); + + auto* sync_input = writer.AddCustomInput(MetadataWriter::CustomInput{ + .tensor_length = 10, + .fill_policy = proto::CustomInput::FILL_SYNC_DEVICE_INFO, + .name = "SyncDeviceInfo"}); + (*sync_input->mutable_additional_args())["wait_for_device_info_in_seconds"] = + "0"; + (*sync_input->mutable_additional_args())["active_days_limit"] = "14"; + + // Failure flag is set. + std::vector<float> expected_result = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + base::RunLoop loop; + sync_device_info_observer_->Process( + *sync_input, state, + base::BindOnce(&SyncDeviceInfoObserverTest::OnProcessFinishedCallback, + base::Unretained(this), loop.QuitClosure(), false, + expected_result)); + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); + loop.Run(); +} + +TEST_F(SyncDeviceInfoObserverTest, ProcessWithNotIntegerTimeout) { + FeatureProcessorState state; + proto::SegmentationModelMetadata metadata; + MetadataWriter writer(&metadata); + + auto* sync_input = writer.AddCustomInput(MetadataWriter::CustomInput{ + .tensor_length = 10, + .fill_policy = proto::CustomInput::FILL_SYNC_DEVICE_INFO, + .name = "SyncDeviceInfo"}); + (*sync_input->mutable_additional_args())["wait_for_device_info_in_seconds"] = + "true"; + (*sync_input->mutable_additional_args())["active_days_limit"] = "14"; + + // Failure flag is set. + std::vector<float> expected_result = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + base::RunLoop loop; + sync_device_info_observer_->Process( + *sync_input, state, + base::BindOnce(&SyncDeviceInfoObserverTest::OnProcessFinishedCallback, + base::Unretained(this), loop.QuitClosure(), false, + expected_result)); + + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); + loop.Run(); +} + +TEST_F(SyncDeviceInfoObserverTest, ProcessWithTimeoutBeforeAddingDevice) { + FeatureProcessorState state; + proto::SegmentationModelMetadata metadata; + MetadataWriter writer(&metadata); + + auto* sync_input = writer.AddCustomInput(MetadataWriter::CustomInput{ + .tensor_length = 10, + .fill_policy = proto::CustomInput::FILL_SYNC_DEVICE_INFO, + .name = "SyncDeviceInfo"}); + (*sync_input->mutable_additional_args())["wait_for_device_info_in_seconds"] = + "2"; + (*sync_input->mutable_additional_args())["active_days_limit"] = "14"; + + // Failure flag is set. + std::vector<float> expected_result = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + base::RunLoop loop; + sync_device_info_observer_->Process( + *sync_input, state, + base::BindOnce(&SyncDeviceInfoObserverTest::OnProcessFinishedCallback, + base::Unretained(this), loop.QuitClosure(), false, + expected_result)); + loop.Run(); + std::unique_ptr<DeviceInfo> local_device_info = + CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); + // Adding a device triggers OnDeviceInfoChange(). + device_info_tracker_->Add(local_device_info.get()); +} + +} // namespace + +} // namespace segmentation_platform::processing \ No newline at end of file
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc index cd5a48f6..85e2fd0 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -13,12 +13,12 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/system/sys_info.h" -#include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/time/clock.h" #include "components/prefs/pref_registry_simple.h" #include "components/segmentation_platform/internal/constants.h" #include "components/segmentation_platform/internal/database/storage_service.h" +#include "components/segmentation_platform/internal/execution/processing/sync_device_info_observer.h" #include "components/segmentation_platform/internal/platform_options.h" #include "components/segmentation_platform/internal/proto/model_prediction.pb.h" #include "components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h" @@ -27,7 +27,6 @@ #include "components/segmentation_platform/internal/selection/segment_selector_impl.h" #include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h" #include "components/segmentation_platform/internal/stats.h" -#include "components/segmentation_platform/internal/sync_device_info_observer.h" #include "components/segmentation_platform/public/config.h" #include "components/segmentation_platform/public/field_trial_register.h" #include "components/segmentation_platform/public/input_context.h" @@ -128,8 +127,10 @@ weak_ptr_factory_.GetWeakPtr())); // Create sync device info observer. - sync_device_info_observer_ = std::make_unique<SyncDeviceInfoObserver>( - init_params->device_info_tracker); + input_delegate_holder_->SetDelegate( + proto::CustomInput::FILL_SYNC_DEVICE_INFO, + std::make_unique<processing::SyncDeviceInfoObserver>( + init_params->device_info_tracker)); } SegmentationPlatformServiceImpl::~SegmentationPlatformServiceImpl() {
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.h b/components/segmentation_platform/internal/segmentation_platform_service_impl.h index c0a7521..a32fc87 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.h +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.h
@@ -11,18 +11,15 @@ #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" -#include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "components/segmentation_platform/internal/database/storage_service.h" -#include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/platform_options.h" #include "components/segmentation_platform/internal/scheduler/execution_service.h" #include "components/segmentation_platform/internal/selection/cached_result_provider.h" #include "components/segmentation_platform/internal/service_proxy_impl.h" #include "components/segmentation_platform/internal/signals/signal_handler.h" -#include "components/segmentation_platform/internal/sync_device_info_observer.h" #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h" #include "components/segmentation_platform/public/segmentation_platform_service.h" #include "components/sync_device_info/device_info_tracker.h" @@ -190,9 +187,6 @@ // For caching any method calls that were received before initialization. base::circular_deque<base::OnceClosure> pending_actions_; - // Sync device info observer. - std::unique_ptr<SyncDeviceInfoObserver> sync_device_info_observer_; - base::WeakPtrFactory<SegmentationPlatformServiceImpl> weak_ptr_factory_{this}; };
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc b/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc index 4c3cd260..965d834 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_test_base.cc
@@ -138,6 +138,8 @@ params->configs = std::move(configs); params->field_trial_register = std::make_unique<MockFieldTrialRegister>(); params->device_info_tracker = device_info_tracker_.get(); + params->input_delegate_holder = + std::make_unique<processing::InputDelegateHolder>(); segmentation_platform_service_impl_ = std::make_unique<SegmentationPlatformServiceImpl>(std::move(params)); }
diff --git a/components/segmentation_platform/internal/segmentation_ukm_helper.cc b/components/segmentation_platform/internal/segmentation_ukm_helper.cc index ec4901c..d055c63 100644 --- a/components/segmentation_platform/internal/segmentation_ukm_helper.cc +++ b/components/segmentation_platform/internal/segmentation_ukm_helper.cc
@@ -99,7 +99,8 @@ SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY, SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID, SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES, - SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT}; + SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT, + SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID_V2}; } std::vector<std::string> segment_ids = base::SplitString( base::GetFieldTrialParamValueByFeature(
diff --git a/components/segmentation_platform/internal/sync_device_info_observer.cc b/components/segmentation_platform/internal/sync_device_info_observer.cc deleted file mode 100644 index 4dd770a..0000000 --- a/components/segmentation_platform/internal/sync_device_info_observer.cc +++ /dev/null
@@ -1,119 +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 "components/segmentation_platform/internal/sync_device_info_observer.h" - -#include "base/feature_list.h" -#include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_functions.h" -#include "base/strings/stringprintf.h" -#include "base/time/time.h" -#include "components/sync/base/features.h" -#include "components/sync_device_info/device_info.h" -#include "components/sync_device_info/device_info_tracker.h" -#include "components/sync_device_info/device_info_util.h" - -namespace segmentation_platform { - -using OsType = syncer::DeviceInfo::OsType; - -namespace { - -constexpr int kDefaultActiveDaysThreshold = 14; - -base::TimeDelta Age(base::Time last_update, base::Time now) { - // Don't allow negative age for things somehow updated in the future. - return std::max(base::TimeDelta(), now - last_update); -} - -// Determines if a device with |last_update| timestamp should be considered -// active, given the current time. -bool IsActiveDevice(base::Time last_update, base::Time now) { - base::TimeDelta active_days_threshold = - base::Days(base::GetFieldTrialParamByFeatureAsInt( - kSegmentationDeviceCountByOsType, "active_days_threshold", - kDefaultActiveDaysThreshold)); - return Age(last_update, now) < active_days_threshold; -} - -// Keep the following in sync with variants in -// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml. -const char* ConvertOsTypeToString(OsType os_type) { - switch (os_type) { - case OsType::kWindows: - return "Windows"; - case OsType::kMac: - return "Mac"; - case OsType::kLinux: - return "Linux"; - case OsType::kIOS: - return "iOS"; - case OsType::kAndroid: - return "Android"; - case OsType::kChromeOsAsh: - return "ChromeOsAsh"; - case OsType::kChromeOsLacros: - return "ChromeOsLacros"; - case OsType::kFuchsia: - return "Fuchsia"; - case OsType::kUnknown: - return "Unknown"; - } -} - -} // namespace - -BASE_FEATURE(kSegmentationDeviceCountByOsType, - "SegmentationDeviceCountByOsType", - base::FEATURE_ENABLED_BY_DEFAULT); - -SyncDeviceInfoObserver::SyncDeviceInfoObserver( - syncer::DeviceInfoTracker* device_info_tracker) - : device_info_tracker_(device_info_tracker) { - DCHECK(device_info_tracker_); - device_info_tracker_->AddObserver(this); -} - -SyncDeviceInfoObserver::~SyncDeviceInfoObserver() { - device_info_tracker_->RemoveObserver(this); -} - -// Count device by os types and record them in UMA only if not recorded yet. -void SyncDeviceInfoObserver::OnDeviceInfoChange() { - if (!device_info_tracker_->IsSyncing() || device_info_recorded_) - return; - - device_info_recorded_ = true; - - // Record device count by OS types. - std::map<OsType, int> count_by_os_type = CountActiveDevicesByOsType(); - - // Record UMA metrics of device counts by OS types. - // Record 0 when there are no devices associated with one OS type. - for (int os_type_idx = static_cast<int>(OsType::kUnknown); - os_type_idx <= static_cast<int>(OsType::kFuchsia); ++os_type_idx) { - OsType os_type = static_cast<OsType>(os_type_idx); - int count = count_by_os_type[os_type]; - base::UmaHistogramSparse( - base::StringPrintf("SegmentationPlatform.DeviceCountByOsType.%s", - ConvertOsTypeToString(os_type)), - std::min(count, 100)); - } -} - -std::map<OsType, int> SyncDeviceInfoObserver::CountActiveDevicesByOsType() - const { - std::map<OsType, int> count_by_os_type; - const base::Time now = base::Time::Now(); - for (const auto& device_info : device_info_tracker_->GetAllDeviceInfo()) { - if (!IsActiveDevice(device_info->last_updated_timestamp(), now)) - continue; - - auto os_type = device_info->os_type(); - count_by_os_type[os_type] += 1; - } - return count_by_os_type; -} - -} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/sync_device_info_observer.h b/components/segmentation_platform/internal/sync_device_info_observer.h deleted file mode 100644 index 5df2fee59..0000000 --- a/components/segmentation_platform/internal/sync_device_info_observer.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SYNC_DEVICE_INFO_OBSERVER_H_ -#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SYNC_DEVICE_INFO_OBSERVER_H_ - -#include "base/feature_list.h" -#include "components/sync_device_info/device_info.h" -#include "components/sync_device_info/device_info_tracker.h" - -namespace segmentation_platform { - -BASE_DECLARE_FEATURE(kSegmentationDeviceCountByOsType); - -class SyncDeviceInfoObserver : public syncer::DeviceInfoTracker::Observer { - public: - SyncDeviceInfoObserver() = delete; - // |device_info_tracker| must not be null and must outlive this object. - explicit SyncDeviceInfoObserver( - syncer::DeviceInfoTracker* device_info_tracker); - ~SyncDeviceInfoObserver() override; - - // DeviceInfoTracker::Observer overrides. - void OnDeviceInfoChange() override; - - private: - // Returns the count of active devices per os type. Each device is identified - // by one unique guid. No deduping is applied. - std::map<syncer::DeviceInfo::OsType, int> CountActiveDevicesByOsType() const; - - // Device info tracker. Not owned. It is managed by - // the DeviceInfoSynceService, which is guaranteed to outlive the - // SegmentationPlatformService, who owns this observer and depends on the - // DeviceInfoSyncService. - const raw_ptr<syncer::DeviceInfoTracker> device_info_tracker_; - // Flag indicating if device info has been recorded. - bool device_info_recorded_ = false; -}; - -} // namespace segmentation_platform - -#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SYNC_DEVICE_INFO_OBSERVER_H_
diff --git a/components/segmentation_platform/internal/sync_device_info_observer_unittest.cc b/components/segmentation_platform/internal/sync_device_info_observer_unittest.cc deleted file mode 100644 index 90a76d4..0000000 --- a/components/segmentation_platform/internal/sync_device_info_observer_unittest.cc +++ /dev/null
@@ -1,135 +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 "components/segmentation_platform/internal/sync_device_info_observer.h" - -#include "base/test/metrics/histogram_tester.h" -#include "components/sync/protocol/sync_enums.pb.h" -#include "components/sync_device_info/device_info.h" -#include "components/sync_device_info/device_info_util.h" -#include "components/sync_device_info/fake_device_info_tracker.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace segmentation_platform { -namespace { - -using syncer::DeviceInfo; -using OsType = syncer::DeviceInfo::OsType; -using DeviceCountByOsTypeMap = std::map<OsType, int>; -using syncer::FakeDeviceInfoTracker; -using DeviceType = sync_pb::SyncEnums::DeviceType; -using DeviceCountByOsTypeMap = std::map<DeviceInfo::OsType, int>; - -const sync_pb::SyncEnums_DeviceType kLocalDeviceType = - sync_pb::SyncEnums_DeviceType_TYPE_LINUX; -const DeviceInfo::OsType kLocalDeviceOS = DeviceInfo::OsType::kLinux; -const DeviceInfo::FormFactor kLocalDeviceFormFactor = - DeviceInfo::FormFactor::kDesktop; - -std::unique_ptr<DeviceInfo> CreateDeviceInfo( - const std::string& guid, - DeviceType device_type, - OsType os_type, - base::Time last_updated = base::Time::Now()) { - return std::make_unique<DeviceInfo>( - guid, "name", "chrome_version", "user_agent", device_type, os_type, - kLocalDeviceFormFactor, "device_id", "manufacturer_name", "model_name", - "full_hardware_class", last_updated, - syncer::DeviceInfoUtil::GetPulseInterval(), - /*send_tab_to_self_receiving_enabled=*/false, absl::nullopt, - /*paask_info=*/absl::nullopt, - /*fcm_registration_token=*/std::string(), - /*interested_data_types=*/syncer::ModelTypeSet()); -} - -class SyncDeviceInfoObserverTest : public testing::Test { - protected: - SyncDeviceInfoObserverTest() = default; - ~SyncDeviceInfoObserverTest() override = default; - - void SetUp() override { - device_info_tracker_ = std::make_unique<FakeDeviceInfoTracker>(); - sync_device_info_observer_ = - std::make_unique<SyncDeviceInfoObserver>(device_info_tracker_.get()); - } - - void TearDown() override { - sync_device_info_observer_.reset(); - device_info_tracker_.reset(); - } - - std::unique_ptr<FakeDeviceInfoTracker> device_info_tracker_; - std::unique_ptr<SyncDeviceInfoObserver> sync_device_info_observer_; -}; - -TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_LocalDevice) { - base::HistogramTester histogram_tester; - std::unique_ptr<DeviceInfo> local_device_info = - CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); - // Adding a device triggers OnDeviceInfoChange(). - device_info_tracker_->Add(local_device_info.get()); - - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); -} - -TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_DifferentGuids) { - base::HistogramTester histogram_tester; - std::unique_ptr<DeviceInfo> local_device_info = - CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); - std::unique_ptr<DeviceInfo> local_device_info_2 = - CreateDeviceInfo("local_device_2", kLocalDeviceType, kLocalDeviceOS); - device_info_tracker_->Add( - {local_device_info.get(), local_device_info_2.get()}); - - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Linux", 2, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); -} - -TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_DifferentOS) { - base::HistogramTester histogram_tester; - std::unique_ptr<DeviceInfo> local_device_info = - CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); - std::unique_ptr<DeviceInfo> local_device_info_2 = - CreateDeviceInfo("local_device_2", kLocalDeviceType, OsType::kMac); - device_info_tracker_->Add( - {local_device_info.get(), local_device_info_2.get()}); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Mac", 1, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); -} - -TEST_F(SyncDeviceInfoObserverTest, OnDeviceInfoChange_InactiveDevice) { - base::HistogramTester histogram_tester; - std::unique_ptr<DeviceInfo> local_device_info = - CreateDeviceInfo("local_device", kLocalDeviceType, kLocalDeviceOS); - std::unique_ptr<DeviceInfo> local_device_info_2 = - CreateDeviceInfo("local_device_2", kLocalDeviceType, OsType::kMac, - base::Time::Now() - base::Days(20)); - device_info_tracker_->Add( - {local_device_info.get(), local_device_info_2.get()}); - - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Linux", 1, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Mac", 0, 1); - histogram_tester.ExpectUniqueSample( - "SegmentationPlatform.DeviceCountByOsType.Windows", 0, 1); -} - -} // namespace - -} // namespace segmentation_platform
diff --git a/components/segmentation_platform/public/proto/model_metadata.proto b/components/segmentation_platform/public/proto/model_metadata.proto index bf72bc1..a83c25a 100644 --- a/components/segmentation_platform/public/proto/model_metadata.proto +++ b/components/segmentation_platform/public/proto/model_metadata.proto
@@ -132,6 +132,19 @@ // Additional arg: // `name`: The name of the field to be looked up in input context. FILL_FROM_INPUT_CONTEXT = 4; + + // Output is a tensor of length 10 consisting of float values denoting + // various devices count by type with different form factor and os type. + // See `SyncDeviceInfoObserver` for description of each value. + // Output type: float + // Output length: 10 + // Additional arg: + // `active_days_limit`: Number of days after which the device is + // considered not active after last sync. + // `wait_for_device_info_in_seconds`: Number of seconds to wait for sync + // device info before timeout. If 0, then does not wait for sync and times + // out immediately if device info is not available. + FILL_SYNC_DEVICE_INFO = 5; } // The fill type of the custom input.
diff --git a/components/services/app_service/public/cpp/file_handler.cc b/components/services/app_service/public/cpp/file_handler.cc index 189e8e14..a9c5947a 100644 --- a/components/services/app_service/public/cpp/file_handler.cc +++ b/components/services/app_service/public/cpp/file_handler.cc
@@ -6,6 +6,8 @@ #include <tuple> +#include "base/strings/string_util.h" + namespace apps { FileHandler::FileHandler() = default; @@ -84,9 +86,11 @@ std::set<std::string> GetFileExtensionsFromFileHandler( const FileHandler& file_handler) { std::set<std::string> file_extensions; - for (const auto& accept_entry : file_handler.accept) - file_extensions.insert(accept_entry.file_extensions.begin(), - accept_entry.file_extensions.end()); + for (const auto& accept_entry : file_handler.accept) { + for (const std::string& extension : accept_entry.file_extensions) { + file_extensions.insert(base::ToLowerASCII(extension)); + } + } return file_extensions; }
diff --git a/components/services/app_service/public/cpp/file_handler.h b/components/services/app_service/public/cpp/file_handler.h index 6f2416fd..04d7cda2 100644 --- a/components/services/app_service/public/cpp/file_handler.h +++ b/components/services/app_service/public/cpp/file_handler.h
@@ -78,10 +78,12 @@ const FileHandler& file_handler); // Get a set of all file extensions supported by any of |file_handlers|. +// Note: These are always transformed to lower-case. std::set<std::string> GetFileExtensionsFromFileHandlers( const FileHandlers& file_handlers); // Get a set of all file extensions supported by |file_handler|. +// Note: These are always transformed to lower-case. std::set<std::string> GetFileExtensionsFromFileHandler( const FileHandler& file_handler);
diff --git a/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc b/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc index dd782cad..dd57ee4 100644 --- a/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc +++ b/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc
@@ -75,8 +75,8 @@ mojom::SubframeClipRect rect; absl::optional<base::UnguessableToken> maybe_deserialized_token = - base::UnguessableToken::Deserialize2(id_pair.embedding_token_high(), - id_pair.embedding_token_low()); + base::UnguessableToken::Deserialize(id_pair.embedding_token_high(), + id_pair.embedding_token_low()); if (!maybe_deserialized_token.has_value()) { continue; } @@ -201,7 +201,7 @@ DCHECK(paint_preview.has_value()); absl::optional<base::UnguessableToken> embedding_token = - base::UnguessableToken::Deserialize2( + base::UnguessableToken::Deserialize( paint_preview->root_frame().embedding_token_high(), paint_preview->root_frame().embedding_token_low()); if (!embedding_token.has_value()) { @@ -295,7 +295,7 @@ DCHECK(paint_preview.has_value()); absl::optional<base::UnguessableToken> maybe_root_frame_guid = - base::UnguessableToken::Deserialize2( + base::UnguessableToken::Deserialize( paint_preview->root_frame().embedding_token_high(), paint_preview->root_frame().embedding_token_low()); if (!maybe_root_frame_guid.has_value()) { @@ -387,8 +387,8 @@ const base::flat_map<base::UnguessableToken, SkpResult>& skp_map, mojom::PaintPreviewBeginCompositeResponsePtr* response) { absl::optional<base::UnguessableToken> maybe_guid = - base::UnguessableToken::Deserialize2(frame_proto.embedding_token_high(), - frame_proto.embedding_token_low()); + base::UnguessableToken::Deserialize(frame_proto.embedding_token_high(), + frame_proto.embedding_token_low()); if (!maybe_guid.has_value()) { return false; } @@ -448,8 +448,8 @@ RecordingMap* recording_map, bool* subframe_failed) { absl::optional<base::UnguessableToken> maybe_frame_guid = - base::UnguessableToken::Deserialize2(frame_proto.embedding_token_high(), - frame_proto.embedding_token_low()); + base::UnguessableToken::Deserialize(frame_proto.embedding_token_high(), + frame_proto.embedding_token_low()); if (!maybe_frame_guid.has_value()) { return nullptr; } @@ -471,8 +471,8 @@ *subframe_failed = false; for (const auto& id_pair : frame_proto.content_id_to_embedding_tokens()) { absl::optional<base::UnguessableToken> maybe_subframe_embedding_token = - base::UnguessableToken::Deserialize2(id_pair.embedding_token_high(), - id_pair.embedding_token_low()); + base::UnguessableToken::Deserialize(id_pair.embedding_token_high(), + id_pair.embedding_token_low()); if (!maybe_subframe_embedding_token.has_value()) { DVLOG(1) << "Subframe has invalid embedding token"; @@ -493,7 +493,7 @@ base::ranges::find(subframes, subframe_embedding_token, [](const PaintPreviewFrameProto& frame_proto) { absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2( + base::UnguessableToken::Deserialize( frame_proto.embedding_token_high(), frame_proto.embedding_token_low()); if (!token.has_value()) {
diff --git a/components/sessions/ios/ios_restore_live_tab.h b/components/sessions/ios/ios_restore_live_tab.h index e57877e..19a3e90 100644 --- a/components/sessions/ios/ios_restore_live_tab.h +++ b/components/sessions/ios/ios_restore_live_tab.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_SESSIONS_IOS_IOS_RESTORE_LIVE_TAB_H_ #define COMPONENTS_SESSIONS_IOS_IOS_RESTORE_LIVE_TAB_H_ -#include "base/supports_user_data.h" #include "components/sessions/ios/ios_live_tab.h" @class CRWSessionStorage;
diff --git a/components/signin/public/identity_manager/account_managed_status_finder.cc b/components/signin/public/identity_manager/account_managed_status_finder.cc index 72529c87..c7ae12e0 100644 --- a/components/signin/public/identity_manager/account_managed_status_finder.cc +++ b/components/signin/public/identity_manager/account_managed_status_finder.cc
@@ -67,27 +67,29 @@ } // namespace // static -bool AccountManagedStatusFinder::IsNonEnterpriseUser(const std::string& email) { +AccountManagedStatusFinder::EmailEnterpriseStatus +AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail( + const std::string& email) { size_t email_separator_pos = email.find('@'); if (email.empty() || email_separator_pos == std::string::npos || email_separator_pos == email.size() - 1) { // An empty email means no logged-in user, or incognito user in case of // ChromiumOS. Also, some tests use nonsense email addresses (e.g. "test"); // these should be treated as non-enterprise too. - return true; + return EmailEnterpriseStatus::kKnownNonEnterprise; } const std::u16string domain = base::UTF8ToUTF16(gaia::ExtractDomainName(email)); for (size_t i = 0; i < std::size(kNonManagedDomainPatterns); i++) { std::u16string pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]); if (MatchDomain(domain, pattern, i)) - return true; + return EmailEnterpriseStatus::kKnownNonEnterprise; } if (g_non_managed_domain_for_testing && domain == base::UTF8ToUTF16(g_non_managed_domain_for_testing)) { - return true; + return EmailEnterpriseStatus::kKnownNonEnterprise; } - return false; + return EmailEnterpriseStatus::kUnknown; } // static @@ -106,7 +108,8 @@ // tell the account type from the email. if (!identity_manager_->HasAccountWithRefreshToken(account_.account_id)) { outcome_ = Outcome::kError; - } else if (IsNonEnterpriseUser(account_.email)) { + } else if (IsEnterpriseUserBasedOnEmail(account_.email) == + EmailEnterpriseStatus::kKnownNonEnterprise) { outcome_ = Outcome::kNonEnterprise; } else if (gaia::IsGoogleInternalAccountEmail( gaia::CanonicalizeEmail(account_.email))) {
diff --git a/components/signin/public/identity_manager/account_managed_status_finder.h b/components/signin/public/identity_manager/account_managed_status_finder.h index 132967f..66cfa4fb5 100644 --- a/components/signin/public/identity_manager/account_managed_status_finder.h +++ b/components/signin/public/identity_manager/account_managed_status_finder.h
@@ -19,16 +19,18 @@ // account. class AccountManagedStatusFinder : public signin::IdentityManager::Observer { public: + // Whether an email belongs to an enterprise domain. + enum class EmailEnterpriseStatus { + // It's unknown whether an email belongs to an enterprise domain. + kUnknown, + // Email belongs to a well-known non-enterprise domain. + kKnownNonEnterprise, + }; + // Check whether the given account is known to be non-enterprise. Domains such - // as gmail.com and googlemail.com are known to not be managed. Also returns - // true if the username is empty or not a valid email address. - // Note that this is accurate in only one direction: If it returns true, the - // account is definitely non-enterprise. But if it returns false, it may or - // may not be an enterprise account. - // TODO(crbug.com/1378553): Consider changing the return type to an enum to - // make the possible outcomes clearer. (This would also avoid the weird - // negation in the method name.) - static bool IsNonEnterpriseUser(const std::string& email); + // as gmail.com and googlemail.com are known to not be managed. + static EmailEnterpriseStatus IsEnterpriseUserBasedOnEmail( + const std::string& email); // Allows to register a domain that is recognized as non-enterprise for tests. // Note that `domain` needs to live until this method is invoked with nullptr.
diff --git a/components/signin/public/identity_manager/account_managed_status_finder_unittest.cc b/components/signin/public/identity_manager/account_managed_status_finder_unittest.cc index 7b08b3d..8a23b0e 100644 --- a/components/signin/public/identity_manager/account_managed_status_finder_unittest.cc +++ b/components/signin/public/identity_manager/account_managed_status_finder_unittest.cc
@@ -12,7 +12,7 @@ namespace signin { -TEST(AccountManagedStatusFinderStaticTest, IsNonEnterpriseUser) { +TEST(AccountManagedStatusFinderStaticTest, IsEnterpriseUserBasedOnEmail) { // List of example emails that are not enterprise users. // clang-format off static const char* kNonEnterpriseUsers[] = { @@ -33,12 +33,17 @@ }; for (const char* username : kNonEnterpriseUsers) { - EXPECT_TRUE(AccountManagedStatusFinder::IsNonEnterpriseUser(username)) - << "IsNonEnterpriseUser returned false for " << username; + EXPECT_EQ( + AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail(username), + AccountManagedStatusFinder::EmailEnterpriseStatus::kKnownNonEnterprise) + << "IsEnterpriseUserBasedOnEmail returned kUnknown for " << username; } for (const char* username : kEnterpriseUsers) { - EXPECT_FALSE(AccountManagedStatusFinder::IsNonEnterpriseUser(username)) - << "IsNonEnterpriseUser returned true for " << username; + EXPECT_EQ( + AccountManagedStatusFinder::IsEnterpriseUserBasedOnEmail(username), + AccountManagedStatusFinder::EmailEnterpriseStatus::kUnknown) + << "IsEnterpriseUserBasedOnEmail returned kKnownNonEnterprise for " + << username; } }
diff --git a/components/supervised_user/core/common/BUILD.gn b/components/supervised_user/core/common/BUILD.gn index eefeda45..a821afc7 100644 --- a/components/supervised_user/core/common/BUILD.gn +++ b/components/supervised_user/core/common/BUILD.gn
@@ -6,6 +6,10 @@ sources = [ "features.cc", "features.h", + "pref_names.cc", + "pref_names.h", + "supervised_user_constants.cc", + "supervised_user_constants.h", ] deps = [ "//base" ] }
diff --git a/components/supervised_user/core/common/pref_names.cc b/components/supervised_user/core/common/pref_names.cc new file mode 100644 index 0000000..8af75fd9 --- /dev/null +++ b/components/supervised_user/core/common/pref_names.cc
@@ -0,0 +1,81 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/supervised_user/core/common/pref_names.h" + +namespace prefs { + +// Stores the email address associated with the google account of the custodian +// of the supervised user, set when the supervised user is created. +const char kSupervisedUserCustodianEmail[] = "profile.managed.custodian_email"; + +// Stores the display name associated with the google account of the custodian +// of the supervised user, updated (if possible) each time the supervised user +// starts a session. +const char kSupervisedUserCustodianName[] = "profile.managed.custodian_name"; + +// Stores the obfuscated gaia id associated with the google account of the +// custodian of the supervised user, updated (if possible) each time the +// supervised user starts a session. +const char kSupervisedUserCustodianObfuscatedGaiaId[] = + "profile.managed.custodian_obfuscated_gaia_id"; + +// Stores the URL of the profile image associated with the google account of the +// custodian of the supervised user. +const char kSupervisedUserCustodianProfileImageURL[] = + "profile.managed.custodian_profile_image_url"; + +// Stores the URL of the profile associated with the google account of the +// custodian of the supervised user. +const char kSupervisedUserCustodianProfileURL[] = + "profile.managed.custodian_profile_url"; + +// Stores the email address associated with the google account of the secondary +// custodian of the supervised user, set when the supervised user is created. +const char kSupervisedUserSecondCustodianEmail[] = + "profile.managed.second_custodian_email"; + +// Stores the display name associated with the google account of the secondary +// custodian of the supervised user, updated (if possible) each time the +// supervised user starts a session. +const char kSupervisedUserSecondCustodianName[] = + "profile.managed.second_custodian_name"; + +// Stores the obfuscated gaia id associated with the google account of the +// secondary custodian of the supervised user, updated (if possible) each time +// the supervised user starts a session. +const char kSupervisedUserSecondCustodianObfuscatedGaiaId[] = + "profile.managed.second_custodian_obfuscated_gaia_id"; + +// Stores the URL of the profile image associated with the google account of the +// secondary custodian of the supervised user. +const char kSupervisedUserSecondCustodianProfileImageURL[] = + "profile.managed.second_custodian_profile_image_url"; + +// Stores the URL of the profile associated with the google account of the +// secondary custodian of the supervised user. +const char kSupervisedUserSecondCustodianProfileURL[] = + "profile.managed.second_custodian_profile_url"; + +// Whether the supervised user may approve extension permission requests. If +// false, extensions should not be able to request new permissions, and new +// extensions should not be installable. +const char kSupervisedUserExtensionsMayRequestPermissions[] = + "profile.managed.extensions_may_request_permissions"; + +// Maps host names to whether the host is manually allowed or blocked. +const char kSupervisedUserManualHosts[] = "profile.managed.manual_hosts"; + +// Maps URLs to whether the URL is manually allowed or blocked. +const char kSupervisedUserManualURLs[] = "profile.managed.manual_urls"; + +// Stores whether the SafeSites filter is enabled. +const char kSupervisedUserSafeSites[] = "profile.managed.safe_sites"; + +// Stores settings that can be modified both by a supervised user and their +// manager. See SupervisedUserSharedSettingsService for a description of +// the format. +const char kSupervisedUserSharedSettings[] = "profile.managed.shared_settings"; + +} // namespace prefs \ No newline at end of file
diff --git a/components/supervised_user/core/common/pref_names.h b/components/supervised_user/core/common/pref_names.h new file mode 100644 index 0000000..e3b6d6cc --- /dev/null +++ b/components/supervised_user/core/common/pref_names.h
@@ -0,0 +1,29 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_ +#define COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_ + +namespace prefs { + +extern const char kSupervisedUserCustodianEmail[]; +extern const char kSupervisedUserCustodianName[]; +extern const char kSupervisedUserCustodianObfuscatedGaiaId[]; +extern const char kSupervisedUserCustodianProfileImageURL[]; +extern const char kSupervisedUserCustodianProfileURL[]; +extern const char kSupervisedUserSecondCustodianEmail[]; +extern const char kSupervisedUserSecondCustodianName[]; +extern const char kSupervisedUserSecondCustodianObfuscatedGaiaId[]; +extern const char kSupervisedUserSecondCustodianProfileImageURL[]; +extern const char kSupervisedUserSecondCustodianProfileURL[]; + +extern const char kSupervisedUserExtensionsMayRequestPermissions[]; +extern const char kSupervisedUserManualHosts[]; +extern const char kSupervisedUserManualURLs[]; +extern const char kSupervisedUserSafeSites[]; +extern const char kSupervisedUserSharedSettings[]; + +} // namespace prefs + +#endif // COMPONENTS_SUPERVISED_USER_CORE_COMMON_PREF_NAMES_H_
diff --git a/chrome/browser/supervised_user/supervised_user_constants.cc b/components/supervised_user/core/common/supervised_user_constants.cc similarity index 91% rename from chrome/browser/supervised_user/supervised_user_constants.cc rename to components/supervised_user/core/common/supervised_user_constants.cc index 16d1a27..30d3c7c6 100644 --- a/chrome/browser/supervised_user/supervised_user_constants.cc +++ b/components/supervised_user/core/common/supervised_user_constants.cc
@@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/common/pref_names.h" +#include "components/supervised_user/core/common/supervised_user_constants.h" + +#include "components/supervised_user/core/common/pref_names.h" namespace supervised_users {
diff --git a/chrome/browser/supervised_user/supervised_user_constants.h b/components/supervised_user/core/common/supervised_user_constants.h similarity index 84% rename from chrome/browser/supervised_user/supervised_user_constants.h rename to components/supervised_user/core/common/supervised_user_constants.h index 0f39871..0c5201c 100644 --- a/chrome/browser/supervised_user/supervised_user_constants.h +++ b/components/supervised_user/core/common/supervised_user_constants.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_CONSTANTS_H_ -#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_CONSTANTS_H_ +#ifndef COMPONENTS_SUPERVISED_USER_CORE_COMMON_SUPERVISED_USER_CONSTANTS_H_ +#define COMPONENTS_SUPERVISED_USER_CORE_COMMON_SUPERVISED_USER_CONSTANTS_H_ namespace supervised_users { @@ -35,4 +35,4 @@ } // namespace supervised_users -#endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_CONSTANTS_H_ +#endif // COMPONENTS_SUPERVISED_USER_CORE_COMMON_SUPERVISED_USER_CONSTANTS_H_
diff --git a/components/test/data/autofill/autofill_iban_form.html b/components/test/data/autofill/autofill_iban_form.html new file mode 100644 index 0000000..9b61cea --- /dev/null +++ b/components/test/data/autofill/autofill_iban_form.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> +<!-- +Copyright 2023 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html> +<head> +<title>IBAN local save Test - Form with IBAN</title> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> +</head> +<body> + <form name="addr1.1" id="form1" action="https://example.com/" method="post"> + IBAN: <input type="text" name="iban" id="iban"> + <button id="fill_form" type="button">Fill IBAN value</button> + <button id="submit" type="submit">Submit</button> + </form> + <script type="text/javascript"> + document.getElementById("fill_form").addEventListener( + "click", + function() { + document.getElementsByName("iban")[0].value = "AT483200000012345864"; + }); +</script> +</body> +</html>
diff --git a/components/tracing/common/background_tracing_state_manager.cc b/components/tracing/common/background_tracing_state_manager.cc index 2f1fed5..b44d8997 100644 --- a/components/tracing/common/background_tracing_state_manager.cc +++ b/components/tracing/common/background_tracing_state_manager.cc
@@ -6,6 +6,7 @@ #include "base/json/values_util.h" #include "base/task/single_thread_task_runner.h" +#include "base/values.h" #include "components/tracing/common/pref_names.h" #include "content/public/browser/background_tracing_config.h" #include "content/public/browser/browser_thread.h" @@ -71,11 +72,13 @@ const base::Value::List* upload_times = dict.FindList(kUploadTimesKey); if (upload_times) { - for (const auto& scenario_dict : *upload_times) { - DCHECK(scenario_dict.is_dict()); - const std::string* scenario = scenario_dict.FindStringKey(kScenarioKey); + for (const base::Value& scenario_val : *upload_times) { + DCHECK(scenario_val.is_dict()); + const base::Value::Dict& scenario_dict = scenario_val.GetDict(); + + const std::string* scenario = scenario_dict.FindString(kScenarioKey); const base::Value* timestamp_val = - scenario_dict.FindKey(kUploadTimestampKey); + scenario_dict.Find(kUploadTimestampKey); if (!scenario || !timestamp_val) { continue; }
diff --git a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java index eacb949..8a3cbe1 100644 --- a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java +++ b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateMessageTest.java
@@ -162,7 +162,7 @@ .when(mMockJni) .handlePrimaryAction(NATIVE_TRANSLATE_MESSAGE); - Assert.assertEquals(new Integer(PrimaryActionClickBehavior.DO_NOT_DISMISS), + Assert.assertEquals(Integer.valueOf(PrimaryActionClickBehavior.DO_NOT_DISMISS), messageProperties.get(MessageBannerProperties.ON_PRIMARY_ACTION).get()); verifyNoMoreInteractions(mMessageDispatcher);
diff --git a/components/ukm/ukm_service.cc b/components/ukm/ukm_service.cc index 83a32ed1f..bab4f63 100644 --- a/components/ukm/ukm_service.cc +++ b/components/ukm/ukm_service.cc
@@ -208,6 +208,10 @@ DVLOG(1) << "UkmService::Constructor"; reporting_service_.Initialize(); + cloned_install_subscription_ = client->AddOnClonedInstallDetectedCallback( + base::BindOnce(&UkmService::OnClonedInstallDetected, + self_ptr_factory_.GetWeakPtr())); + base::RepeatingClosure rotate_callback = base::BindRepeating( &UkmService::RotateLog, self_ptr_factory_.GetWeakPtr()); // MetricsServiceClient outlives UkmService, and @@ -404,6 +408,14 @@ metrics_providers_.OnClientStateCleared(); } +void UkmService::OnClonedInstallDetected() { + // Purge all logs, as they may come from a previous install. Unfortunately, + // since the cloned install detector works asynchronously, it is possible that + // this is called after logs were already sent. However, practically speaking, + // this should not happen, since logs are only sent late into the session. + reporting_service_.ukm_log_store()->Purge(); +} + void UkmService::RegisterMetricsProvider( std::unique_ptr<metrics::MetricsProvider> provider) { metrics_providers_.RegisterMetricsProvider(std::move(provider));
diff --git a/components/ukm/ukm_service.h b/components/ukm/ukm_service.h index c0e3eb25..af9f75d 100644 --- a/components/ukm/ukm_service.h +++ b/components/ukm/ukm_service.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <memory> +#include "base/callback_list.h" #include "base/feature_list.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" @@ -111,6 +112,9 @@ // to provide the reason of the reset - this is only used for UMA logging. void ResetClientState(ResetReason reason); + // Called if this install is detected as cloned. + void OnClonedInstallDetected(); + // Registers the specified |provider| to provide additional metrics into the // UKM log. Should be called during MetricsService initialization only. virtual void RegisterMetricsProvider( @@ -223,6 +227,10 @@ // A callback invoked when initialization of the service is complete. base::OnceClosure initialization_complete_callback_; + // Subscription for a callback that runs if this install is detected as + // cloned. + base::CallbackListSubscription cloned_install_subscription_; + SEQUENCE_CHECKER(sequence_checker_); // Weak pointers factory used to post task on different threads. All weak
diff --git a/components/ukm/ukm_service_unittest.cc b/components/ukm/ukm_service_unittest.cc index be29792..abcdf23 100644 --- a/components/ukm/ukm_service_unittest.cc +++ b/components/ukm/ukm_service_unittest.cc
@@ -25,11 +25,14 @@ #include "base/test/test_simple_task_runner.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" +#include "components/metrics/cloned_install_detector.h" #include "components/metrics/log_decoder.h" #include "components/metrics/metrics_log_uploader.h" +#include "components/metrics/metrics_pref_names.h" #include "components/metrics/test/test_metrics_provider.h" #include "components/metrics/test/test_metrics_service_client.h" #include "components/metrics/ukm_demographic_metrics_provider.h" +#include "components/metrics/unsent_log_store.h" #include "components/prefs/testing_pref_service.h" #include "components/ukm/observers/ukm_consent_state_observer.h" #include "components/ukm/ukm_entry_filter.h" @@ -90,6 +93,33 @@ raw_ptr<UkmRecorder> recorder_; }; +class TestMetricsServiceClientWithClonedInstallDetector + : public metrics::TestMetricsServiceClient { + public: + TestMetricsServiceClientWithClonedInstallDetector() = default; + + TestMetricsServiceClientWithClonedInstallDetector( + const TestMetricsServiceClientWithClonedInstallDetector&) = delete; + TestMetricsServiceClientWithClonedInstallDetector& operator=( + const TestMetricsServiceClientWithClonedInstallDetector&) = delete; + + ~TestMetricsServiceClientWithClonedInstallDetector() override = default; + + // metrics::MetricsServiceClient: + base::CallbackListSubscription AddOnClonedInstallDetectedCallback( + base::OnceClosure callback) override { + return cloned_install_detector_.AddOnClonedInstallDetectedCallback( + std::move(callback)); + } + + metrics::ClonedInstallDetector* cloned_install_detector() { + return &cloned_install_detector_; + } + + private: + metrics::ClonedInstallDetector cloned_install_detector_; +}; + namespace { bool TestIsWebstoreExtension(base::StringPiece id) { @@ -1844,6 +1874,45 @@ EXPECT_EQ(external_client_id, prefs_.GetUint64(prefs::kUkmClientId)); } +// Verifies that when a cloned install is detected, logs are purged. +TEST_P(UkmServiceTest, PurgeLogsOnClonedInstallDetected) { + TestMetricsServiceClientWithClonedInstallDetector client; + UkmService service(&prefs_, &client, + std::make_unique<MockDemographicMetricsProvider>()); + service.Initialize(); + + // Store various logs. + metrics::UnsentLogStore* test_log_store = + service.reporting_service_for_testing().ukm_log_store(); + test_log_store->StoreLog("dummy log data", metrics::LogMetadata()); + test_log_store->StageNextLog(); + test_log_store->StoreLog("more dummy log data", metrics::LogMetadata()); + EXPECT_TRUE(test_log_store->has_staged_log()); + EXPECT_TRUE(test_log_store->has_unsent_logs()); + + metrics::ClonedInstallDetector* cloned_install_detector = + client.cloned_install_detector(); + cloned_install_detector->RegisterPrefs(prefs_.registry()); + + static constexpr char kTestRawId[] = "test"; + // Hashed machine id for |kTestRawId|. + static constexpr int kTestHashedId = 2216819; + + // Save a machine id that will not cause a clone to be detected. + prefs_.SetInteger(metrics::prefs::kMetricsMachineId, kTestHashedId); + cloned_install_detector->SaveMachineIdForTesting(&prefs_, kTestRawId); + // Verify that the logs are still present. + EXPECT_TRUE(test_log_store->has_staged_log()); + EXPECT_TRUE(test_log_store->has_unsent_logs()); + + // Save a machine id that will cause a clone to be detected. + prefs_.SetInteger(metrics::prefs::kMetricsMachineId, kTestHashedId + 1); + cloned_install_detector->SaveMachineIdForTesting(&prefs_, kTestRawId); + // Verify that the logs were purged. + EXPECT_FALSE(test_log_store->has_staged_log()); + EXPECT_FALSE(test_log_store->has_unsent_logs()); +} + #if BUILDFLAG(IS_CHROMEOS_ASH) namespace {
diff --git a/components/upload_list/text_log_upload_list.cc b/components/upload_list/text_log_upload_list.cc index 9320e969..fec8e0d 100644 --- a/components/upload_list/text_log_upload_list.cc +++ b/components/upload_list/text_log_upload_list.cc
@@ -27,6 +27,7 @@ constexpr char kJsonLogKeyCaptureTime[] = "capture_time"; constexpr char kJsonLogKeyState[] = "state"; constexpr char kJsonLogKeySource[] = "source"; +constexpr char kJsonLogKeyPathHash[] = "path_hash"; std::vector<std::string> SplitIntoLines(const std::string& file_contents) { return base::SplitString(file_contents, base::kWhitespaceASCII, @@ -175,9 +176,16 @@ static_cast<TextLogUploadList::UploadInfo::State>(state.value()); // Parse source. - const std::string* source = dict.FindStringKey(kJsonLogKeySource); - if (source) + if (const std::string* source = dict.FindStringKey(kJsonLogKeySource); + source) { info->source = *source; + } + + // Parse path hash. + if (const std::string* path_hash = dict.FindStringKey(kJsonLogKeyPathHash); + path_hash) { + info->path_hash = *path_hash; + } return info; }
diff --git a/components/upload_list/text_log_upload_list_unittest.cc b/components/upload_list/text_log_upload_list_unittest.cc index 9a02376..3764af80 100644 --- a/components/upload_list/text_log_upload_list_unittest.cc +++ b/components/upload_list/text_log_upload_list_unittest.cc
@@ -24,6 +24,7 @@ const char kTestLocalID[] = "fedcba9876543210"; const char kTestCaptureTime[] = "2345678901"; const char kTestSource[] = "test_source"; +const char kTestPathHash[] = "1a2b3c4d5e6f"; class TextLogUploadListTest : public testing::Test { public: @@ -528,6 +529,46 @@ } } +TEST_F(TextLogUploadListTest, ParseWithPathHash_JSON) { + std::stringstream stream; + for (int i = 1; i <= 4; ++i) { + stream << "{"; + stream << "\"upload_time\":\"" << kTestUploadTime << "\","; + stream << "\"upload_id\":\"" << kTestUploadId << "\","; + stream << "\"local_id\":\"" << kTestLocalID << "\","; + stream << "\"capture_time\":\"" << kTestCaptureTime << "\","; + stream << "\"state\":" + << static_cast<int>(UploadList::UploadInfo::State::Uploaded) << ","; + stream << "\"source\":\"" << kTestSource << "\","; + stream << "\"path_hash\":\"" << kTestPathHash << "\""; + stream << "}" << std::endl; + } + WriteUploadLog(stream.str()); + + scoped_refptr<TextLogUploadList> upload_list = + new TextLogUploadList(log_path()); + + base::RunLoop run_loop; + upload_list->Load(run_loop.QuitClosure()); + run_loop.Run(); + + std::vector<UploadList::UploadInfo> uploads; + upload_list->GetUploads(999, &uploads); + + EXPECT_EQ(4u, uploads.size()); + for (const UploadList::UploadInfo& upload : uploads) { + double time_double = upload.upload_time.ToDoubleT(); + EXPECT_STREQ(kTestUploadTime, base::NumberToString(time_double).c_str()); + EXPECT_STREQ(kTestUploadId, upload.upload_id.c_str()); + EXPECT_STREQ(kTestLocalID, upload.local_id.c_str()); + time_double = upload.capture_time.ToDoubleT(); + EXPECT_STREQ(kTestCaptureTime, base::NumberToString(time_double).c_str()); + EXPECT_EQ(UploadList::UploadInfo::State::Uploaded, upload.state); + EXPECT_STREQ(kTestSource, upload.source.c_str()); + EXPECT_STREQ(kTestPathHash, upload.path_hash.c_str()); + } +} + TEST_F(TextLogUploadListTest, ParseHybridFormat) { std::stringstream stream; for (int i = 1; i <= 4; ++i) {
diff --git a/components/upload_list/upload_list.cc b/components/upload_list/upload_list.cc index bc143272..0d07e15 100644 --- a/components/upload_list/upload_list.cc +++ b/components/upload_list/upload_list.cc
@@ -48,14 +48,7 @@ const base::Time& upload_time) : upload_id(upload_id), upload_time(upload_time), state(State::Uploaded) {} -UploadList::UploadInfo::UploadInfo(const UploadInfo& upload_info) - : upload_id(upload_info.upload_id), - upload_time(upload_info.upload_time), - local_id(upload_info.local_id), - capture_time(upload_info.capture_time), - state(upload_info.state), - source(upload_info.source), - file_size(upload_info.file_size) {} +UploadList::UploadInfo::UploadInfo(const UploadInfo& upload_info) = default; UploadList::UploadInfo::~UploadInfo() = default;
diff --git a/components/upload_list/upload_list.h b/components/upload_list/upload_list.h index 34aeeab..bb1655f 100644 --- a/components/upload_list/upload_list.h +++ b/components/upload_list/upload_list.h
@@ -33,6 +33,7 @@ Uploaded, }; + UploadInfo(const UploadInfo& upload_info); UploadInfo(const std::string& upload_id, const base::Time& upload_time, const std::string& local_id, @@ -44,7 +45,6 @@ State state, const std::u16string& file_size); UploadInfo(const std::string& upload_id, const base::Time& upload_time); - UploadInfo(const UploadInfo& upload_info); ~UploadInfo(); // These fields are only valid when |state| == UploadInfo::State::Uploaded. @@ -63,6 +63,9 @@ // Identifies where the crash comes from. std::string source; + // The MD5sum of the path of the crash meta file. + std::string path_hash; + // Formatted file size for locally stored data. std::u16string file_size; };
diff --git a/components/user_education/views/help_bubble_factory_views.cc b/components/user_education/views/help_bubble_factory_views.cc index de44714..5aef320ab 100644 --- a/components/user_education/views/help_bubble_factory_views.cc +++ b/components/user_education/views/help_bubble_factory_views.cc
@@ -106,8 +106,9 @@ } void HelpBubbleViews::OnAnchorBoundsChanged() { - if (help_bubble_view_) + if (help_bubble_view_) { help_bubble_view_->OnAnchorBoundsChanged(); + } } gfx::Rect HelpBubbleViews::GetBoundsInScreen() const { @@ -180,7 +181,7 @@ void HelpBubbleViews::OnElementBoundsChanged(ui::TrackedElement* element) { if (help_bubble_view_ && element == anchor_element_) { - help_bubble_view_->set_force_anchor_rect(element->GetScreenBounds()); + help_bubble_view_->SetForceAnchorRect(element->GetScreenBounds()); OnAnchorBoundsChanged(); } }
diff --git a/components/user_education/views/help_bubble_view.cc b/components/user_education/views/help_bubble_view.cc index ca221c1a..ef55100 100644 --- a/components/user_education/views/help_bubble_view.cc +++ b/components/user_education/views/help_bubble_view.cc
@@ -39,6 +39,7 @@ #include "ui/views/animation/ink_drop.h" #include "ui/views/background.h" #include "ui/views/bubble/bubble_border.h" +#include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/image_button.h" @@ -294,8 +295,10 @@ : BubbleDialogDelegateView(anchor.view, TranslateArrow(params.arrow), views::BubbleBorder::STANDARD_SHADOW), - delegate_(delegate), - force_anchor_rect_(anchor.rect) { + delegate_(delegate) { + if (anchor.rect.has_value()) { + SetForceAnchorRect(anchor.rect.value()); + } // The anchor for promo bubbles should not highlight. set_highlight_button_when_shown(false); DCHECK(anchor.view) @@ -702,7 +705,27 @@ } gfx::Rect HelpBubbleView::GetAnchorRect() const { - return force_anchor_rect_.value_or(BubbleDialogDelegateView::GetAnchorRect()); + gfx::Rect default_anchor_rect = BubbleDialogDelegateView::GetAnchorRect(); + if (!local_anchor_bounds_) { + return default_anchor_rect; + } + + // Ensure that we are not trying to clamp the anchor bounds to a completely + // empty bounds. + gfx::Size size = default_anchor_rect.size(); + size.SetToMax({1, 1}); + + // Clamp the local bounds to the size of the anchor view. + const int left = std::clamp(local_anchor_bounds_->x(), 0, size.width() - 1); + const int right = std::clamp(local_anchor_bounds_->right(), 1, size.width()); + const int top = std::clamp(local_anchor_bounds_->y(), 0, size.height() - 1); + const int bottom = + std::clamp(local_anchor_bounds_->bottom(), 1, size.height()); + gfx::Rect result(left, top, right - left, bottom - top); + + // Translate back to screen coordinates. + result.Offset(default_anchor_rect.OffsetFromOrigin()); + return result; } // static @@ -736,6 +759,12 @@ return non_default_buttons_[index]; } +void HelpBubbleView::SetForceAnchorRect(gfx::Rect force_anchor_rect) { + force_anchor_rect.Offset( + -views::BubbleDialogDelegateView::GetAnchorRect().OffsetFromOrigin()); + local_anchor_bounds_ = force_anchor_rect; +} + BEGIN_METADATA(HelpBubbleView, views::BubbleDialogDelegateView) END_METADATA
diff --git a/components/user_education/views/help_bubble_view.h b/components/user_education/views/help_bubble_view.h index a9711b7..0c5166f 100644 --- a/components/user_education/views/help_bubble_view.h +++ b/components/user_education/views/help_bubble_view.h
@@ -79,9 +79,7 @@ views::LabelButton* GetDefaultButtonForTesting() const; views::LabelButton* GetNonDefaultButtonForTesting(int index) const; - void set_force_anchor_rect(gfx::Rect force_anchor_rect) { - force_anchor_rect_ = force_anchor_rect; - } + void SetForceAnchorRect(gfx::Rect force_anchor_rect); protected: // BubbleDialogDelegateView: @@ -95,6 +93,7 @@ private: FRIEND_TEST_ALL_PREFIXES(HelpBubbleViewTimeoutTest, RespectsProvidedTimeoutAfterActivate); + friend class HelpBubbleViewsTest; void MaybeStartAutoCloseTimer(); @@ -102,10 +101,8 @@ const base::raw_ptr<const HelpBubbleDelegate> delegate_; - // Forces the anchor rect to the specified rectangle (in screen coordinates). - // If an artificial anchor rect is used, we assume the exact target cannot be - // localized, and a visible arrow is not shown. - absl::optional<gfx::Rect> force_anchor_rect_; + // If set, overrides the anchor bounds within the anchor view. + absl::optional<gfx::Rect> local_anchor_bounds_; base::raw_ptr<views::ImageView> icon_view_ = nullptr; std::vector<views::Label*> labels_;
diff --git a/components/user_education/views/help_bubble_view_unittest.cc b/components/user_education/views/help_bubble_view_unittest.cc index d621a729..8e13f4b 100644 --- a/components/user_education/views/help_bubble_view_unittest.cc +++ b/components/user_education/views/help_bubble_view_unittest.cc
@@ -203,7 +203,7 @@ constexpr gfx::Vector2d kAnchorOffset{9, 13}; anchor_bounds.Offset(kAnchorOffset); - bubble->set_force_anchor_rect(anchor_bounds); + bubble->SetForceAnchorRect(anchor_bounds); bubble->OnAnchorBoundsChanged(); gfx::Rect expected = bubble_bounds; @@ -249,11 +249,15 @@ } protected: + gfx::Rect GetHelpBubbleAnchorRect() const { + return help_bubble_->bubble_view()->GetAnchorRect(); + } + std::unique_ptr<ui::test::TestElement> test_element_; std::unique_ptr<HelpBubbleViews> help_bubble_; }; -// This duplicates the previous test, but with a HelpBubbleViews object. +// This duplicates the HelpBubbleViewTest, but with a HelpBubbleViews object. TEST_F(HelpBubbleViewsTest, AnchorToRect) { const auto widget_bounds = GetWidgetClientBounds(); const auto anchor_bounds = test_element_->GetScreenBounds(); @@ -270,7 +274,7 @@ 2); } -// This duplicates the previous test, but with a HelpBubbleViews object. +// This duplicates the HelpBubbleViewTest, but with a HelpBubbleViews object. TEST_F(HelpBubbleViewsTest, AnchorRectUpdated) { const gfx::Rect old_bounds = help_bubble_->GetBoundsInScreen(); @@ -288,4 +292,103 @@ EXPECT_EQ(expected, help_bubble_->GetBoundsInScreen()); } +// This checks a case where the target anchor region scrolls partially out of +// the host view. The anchor rect should be the intersection of the two. +TEST_F(HelpBubbleViewsTest, AnchorRectOverlapsEdge) { + const gfx::Rect old_bounds = help_bubble_->GetBoundsInScreen(); + + // Move the anchor target so that the upper left is beyond the edge of the + // anchor view. + auto new_bounds = test_element_->GetScreenBounds(); + new_bounds.Offset(-100, -100); + test_element_->SetScreenBounds(new_bounds); + ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + test_element_.get(), kHelpBubbleAnchorBoundsChangedEvent); + + // Verify that the help bubble has moved. + constexpr gfx::Rect kNewAnchorBounds{kWidgetBounds.x(), kWidgetBounds.y(), 50, + 50}; + EXPECT_EQ(kNewAnchorBounds, GetHelpBubbleAnchorRect()); + const gfx::Rect help_bubble_bounds = help_bubble_->GetBoundsInScreen(); + EXPECT_LT(help_bubble_bounds.y(), old_bounds.y()); + EXPECT_GT(help_bubble_bounds.CenterPoint().y(), kNewAnchorBounds.y()); + EXPECT_LT(help_bubble_bounds.CenterPoint().y(), kNewAnchorBounds.bottom()); + + // Bubble may have mirrored horizontally. Check which orientation it's in and + // verify the position is appropriate to the new anchor region. + switch (help_bubble_->bubble_view()->GetBubbleFrameView()->GetArrow()) { + case views::BubbleBorder::RIGHT_CENTER: + EXPECT_LT(help_bubble_bounds.x(), old_bounds.x()); + EXPECT_LT(help_bubble_bounds.right(), kNewAnchorBounds.x()); + break; + case views::BubbleBorder::LEFT_CENTER: + EXPECT_GT(help_bubble_bounds.x(), old_bounds.x()); + EXPECT_GT(help_bubble_bounds.x(), kNewAnchorBounds.right()); + break; + default: + NOTREACHED() << "Arrow should only be right-center or left-center."; + } +} + +// This checks a case where the target anchor region scrolls fully out of +// the host view. The anchor rect should be a one-pixel slice on the edge +// closest to the actual anchor. +TEST_F(HelpBubbleViewsTest, AnchorOutsideBoundsHorizontal) { + const gfx::Rect old_bounds = help_bubble_->GetBoundsInScreen(); + + // Move the anchor target entirely off the right side of the anchor view. + auto new_bounds = test_element_->GetScreenBounds(); + new_bounds.Offset(200, 0); + test_element_->SetScreenBounds(new_bounds); + ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + test_element_.get(), kHelpBubbleAnchorBoundsChangedEvent); + + // Verify that the help bubble has moved. It might be mirrored, however. + constexpr gfx::Rect kNewAnchorBounds{kWidgetBounds.right() - 1, + kWidgetBounds.y() + 50, 1, 100}; + EXPECT_EQ(kNewAnchorBounds, GetHelpBubbleAnchorRect()); + const gfx::Rect help_bubble_bounds = help_bubble_->GetBoundsInScreen(); + EXPECT_EQ(help_bubble_bounds.y(), old_bounds.y()); + EXPECT_GT(help_bubble_bounds.x(), old_bounds.x()); + EXPECT_LT(help_bubble_bounds.right(), kNewAnchorBounds.x()); +} + +// This checks a case where the target anchor region scrolls fully out of +// the host view. The anchor rect should be a one-pixel slice on the edge +// closest to the actual anchor. +TEST_F(HelpBubbleViewsTest, AnchorOutsideBoundsVertical) { + const gfx::Rect old_bounds = help_bubble_->GetBoundsInScreen(); + + // Move the anchor target entirely beyond the bottom of the anchor view. + auto new_bounds = test_element_->GetScreenBounds(); + new_bounds.Offset(0, 200); + test_element_->SetScreenBounds(new_bounds); + ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + test_element_.get(), kHelpBubbleAnchorBoundsChangedEvent); + + // Verify that the help bubble has moved. It might be mirrored, however. + constexpr gfx::Rect kNewAnchorBounds{kWidgetBounds.x() + 50, + kWidgetBounds.bottom() - 1, 100, 1}; + EXPECT_EQ(kNewAnchorBounds, GetHelpBubbleAnchorRect()); + const gfx::Rect help_bubble_bounds = help_bubble_->GetBoundsInScreen(); + EXPECT_EQ(help_bubble_bounds.x(), old_bounds.x()); + EXPECT_GT(help_bubble_bounds.y(), old_bounds.y()); + EXPECT_LT(help_bubble_bounds.y(), kNewAnchorBounds.y()); + EXPECT_GE(help_bubble_bounds.bottom(), kNewAnchorBounds.y()); + EXPECT_LT(help_bubble_bounds.right(), kNewAnchorBounds.x()); +} + +// Verifies that a bubble anchored to a region will still move with the owning +// Widget. +TEST_F(HelpBubbleViewsTest, MoveAnchorWidget) { + const auto old_bubble_bounds = help_bubble_->GetBoundsInScreen(); + gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen(); + constexpr gfx::Vector2d kOffset{9, 13}; + widget_bounds.Offset(kOffset); + widget_->SetBounds(widget_bounds); + gfx::Rect expected = old_bubble_bounds; + expected.Offset(kOffset); + EXPECT_EQ(expected, help_bubble_->GetBoundsInScreen()); +} + } // namespace user_education
diff --git a/components/user_education/webui/help_bubble_handler.cc b/components/user_education/webui/help_bubble_handler.cc index 99139307..9cfd74e 100644 --- a/components/user_education/webui/help_bubble_handler.cc +++ b/components/user_education/webui/help_bubble_handler.cc
@@ -230,7 +230,7 @@ return; // Note: any of the following calls could destroy *this* via a callback. - if (!data->element->visible() && visible) { + if (visible) { data->element->SetVisible(true, rect); } else if (data->element->visible() && !visible) { // Is a help bubble currently showing?
diff --git a/components/user_education/webui/tracked_element_webui.cc b/components/user_education/webui/tracked_element_webui.cc index 148d14c..515acfe 100644 --- a/components/user_education/webui/tracked_element_webui.cc +++ b/components/user_education/webui/tracked_element_webui.cc
@@ -50,10 +50,10 @@ void TrackedElementWebUI::SetVisible(bool visible, gfx::RectF bounds) { if (visible == visible_) { if (visible && last_known_bounds_ != bounds) { + last_known_bounds_ = bounds; // This event signals that the bounds of the element have been updated. ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( this, kHelpBubbleAnchorBoundsChangedEvent); - last_known_bounds_ = bounds; } return; }
diff --git a/components/user_manager/fake_user_manager.cc b/components/user_manager/fake_user_manager.cc index 918752d..7e6ef2e 100644 --- a/components/user_manager/fake_user_manager.cc +++ b/components/user_manager/fake_user_manager.cc
@@ -139,6 +139,9 @@ void FakeUserManager::LogoutAllUsers() { primary_user_ = nullptr; active_user_ = nullptr; + + logged_in_users_.clear(); + lru_logged_in_users_.clear(); } void FakeUserManager::SetUserNonCryptohomeDataEphemeral(
diff --git a/components/user_notes/storage/user_note_database.cc b/components/user_notes/storage/user_note_database.cc index 6309cce..378f04ed 100644 --- a/components/user_notes/storage/user_note_database.cc +++ b/components/user_notes/storage/user_note_database.cc
@@ -105,7 +105,7 @@ continue; } absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { continue; }
diff --git a/components/vector_icons/launch.icon b/components/vector_icons/launch.icon index 105d1fca..924d3fb 100644 --- a/components/vector_icons/launch.icon +++ b/components/vector_icons/launch.icon
@@ -3,6 +3,7 @@ // found in the LICENSE file. CANVAS_DIMENSIONS, 18, +FLIPS_IN_RTL, MOVE_TO, 13.5f, 13.5f, R_H_LINE_TO, -9, R_V_LINE_TO, -9,
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc index ad5e7dd..dacf04d 100644 --- a/components/viz/host/host_frame_sink_manager.cc +++ b/components/viz/host/host_frame_sink_manager.cc
@@ -432,8 +432,10 @@ } void HostFrameSinkManager::StartFrameCountingForTest( + base::TimeTicks start_time, base::TimeDelta bucket_size) { - frame_sink_manager_->StartFrameCountingForTest(bucket_size); // IN-TEST + frame_sink_manager_->StartFrameCountingForTest(start_time, // IN-TEST + bucket_size); } void HostFrameSinkManager::StopFrameCountingForTest(
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h index 4dc56a3..5bc6bc7 100644 --- a/components/viz/host/host_frame_sink_manager.h +++ b/components/viz/host/host_frame_sink_manager.h
@@ -220,7 +220,8 @@ void UpdateDebugRendererSettings(const DebugRendererSettings& debug_settings); // Starts the frame counting in Viz. - void StartFrameCountingForTest(base::TimeDelta bucket_size); + void StartFrameCountingForTest(base::TimeTicks start_time, + base::TimeDelta bucket_size); // Ends the frame counting in Viz thread and returns data to the client. void StopFrameCountingForTest(
diff --git a/components/viz/service/display/display_resource_provider.cc b/components/viz/service/display/display_resource_provider.cc index a2ebc2f..2233043 100644 --- a/components/viz/service/display/display_resource_provider.cc +++ b/components/viz/service/display/display_resource_provider.cc
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "components/viz/common/resources/resource_sizes.h" #include "gpu/command_buffer/common/shared_image_trace_utils.h" +#include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/trace_util.h" @@ -85,11 +86,8 @@ // Texture resources may not come with a size, in which case don't report // one. if (!resource.transferable.size.IsEmpty()) { - // TODO (hitawala): Update size check to use multiplanar - // SharedImageFormat. - uint64_t total_bytes = ResourceSizes::UncheckedSizeInBytesAligned<size_t>( - resource.transferable.size, - resource.transferable.format.resource_format()); + uint64_t total_bytes = resource.transferable.format.EstimatedSizeInBytes( + resource.transferable.size); dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, static_cast<uint64_t>(total_bytes)); @@ -168,12 +166,8 @@ } gfx::BufferFormat DisplayResourceProvider::GetBufferFormat(ResourceId id) { - return BufferFormat(GetResourceFormat(id)); -} - -ResourceFormat DisplayResourceProvider::GetResourceFormat(ResourceId id) { ChildResource* resource = GetResource(id); - return resource->transferable.format.resource_format(); + return gpu::ToBufferFormat(resource->transferable.format); } const gfx::ColorSpace& DisplayResourceProvider::GetOverlayColorSpace(
diff --git a/components/viz/service/display/display_resource_provider.h b/components/viz/service/display/display_resource_provider.h index 6eef1b37..effa9bca 100644 --- a/components/viz/service/display/display_resource_provider.h +++ b/components/viz/service/display/display_resource_provider.h
@@ -90,7 +90,6 @@ bool IsResourceSoftwareBacked(ResourceId id); // Return the format of the underlying buffer that can be used for scanout. gfx::BufferFormat GetBufferFormat(ResourceId id); - ResourceFormat GetResourceFormat(ResourceId id); // Returns the color space that the resource needs to be interpreted in by the // operating system. const gfx::ColorSpace& GetOverlayColorSpace(ResourceId id);
diff --git a/components/viz/service/display/overlay_processor_ozone.cc b/components/viz/service/display/overlay_processor_ozone.cc index 923c247..6a3a78f 100644 --- a/components/viz/service/display/overlay_processor_ozone.cc +++ b/components/viz/service/display/overlay_processor_ozone.cc
@@ -99,6 +99,11 @@ if (!source_color_space.IsValid()) return true; + // TODO(b/249215983): Disable promotion of HDR content to overlay until + // decoding to monitor colorspace is supported. + if (source_color_space.IsHDR()) + return false; + // Since https://crrev.com/c/2336347, we force BT.601/narrow for the // COLOR_ENCODING and COLOR_RANGE DRM/KMS properties. On the other hand, the // compositor is able to handle different YUV encodings and ranges. Therefore,
diff --git a/components/viz/service/display/overlay_processor_ozone_unittest.cc b/components/viz/service/display/overlay_processor_ozone_unittest.cc index e0cbaa7..e6f4025 100644 --- a/components/viz/service/display/overlay_processor_ozone_unittest.cc +++ b/components/viz/service/display/overlay_processor_ozone_unittest.cc
@@ -221,12 +221,17 @@ candidates[0] = candidate; - // We do allow color space mismatches as long as the ContentColorUsage is the - // same as the primary plane's (and this applies to all platforms). + // In Chrome OS, we don't allow the promotion of the candidate if the + // content is HDR. On other platforms, we do allow color space mismatches as + // long as the ContentColorUsage is the same as the primary plane's primary_plane.color_space = gfx::ColorSpace::CreateHDR10(); candidates[0].color_space = gfx::ColorSpace::CreateHLG(); processor.CheckOverlaySupport(&primary_plane, &candidates); +#if BUILDFLAG(IS_CHROMEOS_ASH) + EXPECT_FALSE(candidates.at(0).overlay_handled); +#else EXPECT_TRUE(candidates.at(0).overlay_handled); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) candidates[0] = candidate;
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 223a556..3244e4cc 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -916,19 +916,7 @@ current_frame()->overlay_list.begin(), surface_candidate); #endif // BUILDFLAG(IS_WIN) } - } else { -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) - // If there's no primary plane on these platforms it mean's we're delegating - // to the system compositor, and don't need the buffers anymore. If those - // buffers are managed by buffer_queue_, we can tell it to destroy them. - // They'll be recreated when we need them again when GetCurrentBuffer() is - // called. - if (buffer_queue_) { - buffer_queue_->DestroyBuffers(); - } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) } - ScheduleOverlays(); debug_tint_modulate_count_++; }
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc index 21b021eb..325b397f 100644 --- a/components/viz/service/display_embedder/buffer_queue.cc +++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -6,10 +6,10 @@ #include <utility> -#include "base/metrics/histogram_macros.h" #include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/service/display/skia_output_surface.h" #include "gpu/command_buffer/common/shared_image_usage.h" +#include "gpu/command_buffer/common/sync_token.h" namespace viz { @@ -156,8 +156,6 @@ } std::unique_ptr<BufferQueue::AllocatedBuffer> BufferQueue::GetNextBuffer() { - RecreateBuffersIfDestroyed(); - DCHECK(!available_buffers_.empty()); std::unique_ptr<AllocatedBuffer> buffer = @@ -167,12 +165,6 @@ } gpu::Mailbox BufferQueue::GetLastSwappedBuffer() { - if (buffers_destroyed_) { - // Buffers will not be destroyed on platforms where we need to use a buffer - // for overlay testing (Ash). - return gpu::Mailbox(); - } - // The last swapped buffer will generally be in displayed_buffer_, as long as // SwapBuffersComplete() has been called at least once for a non-empty swap // since the last Reshape(). @@ -207,27 +199,6 @@ number_of_buffers_ = n; } -void BufferQueue::DestroyBuffers() { - if (buffers_destroyed_) { - return; - } - buffers_destroyed_ = true; - destroyed_timer_ = base::ElapsedTimer(); - FreeAllBuffers(); -} - -void BufferQueue::RecreateBuffersIfDestroyed() { - if (!buffers_destroyed_) { - return; - } - AllocateBuffers(number_of_buffers_); - buffers_destroyed_ = false; - base::TimeDelta elapsed = destroyed_timer_->Elapsed(); - UMA_HISTOGRAM_TIMES("Compositing.BufferQueue.TimeUntilBuffersRecreatedMs", - elapsed); - destroyed_timer_.reset(); -} - BufferQueue::AllocatedBuffer::AllocatedBuffer(const gpu::Mailbox& mailbox, const gfx::Rect& rect) : mailbox(mailbox), damage(rect) {}
diff --git a/components/viz/service/display_embedder/buffer_queue.h b/components/viz/service/display_embedder/buffer_queue.h index c09153d8..786aef6 100644 --- a/components/viz/service/display_embedder/buffer_queue.h +++ b/components/viz/service/display_embedder/buffer_queue.h
@@ -13,7 +13,6 @@ #include "base/containers/circular_deque.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" -#include "base/timer/elapsed_timer.h" #include "components/viz/service/viz_service_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/ipc/common/surface_handle.h" @@ -50,10 +49,6 @@ // target for compositing). gpu::Mailbox GetCurrentBuffer(); - // Returns a mailbox to be used for overlay testing. This will be the last - // swapped buffer if one exists, or another buffer in the queue if not. This - // will return a zero-mailbox if DestroyBuffers() has been called and buffers - // have not been recreated since. gpu::Mailbox GetLastSwappedBuffer(); // Returns a rectangle whose contents may have changed since the current @@ -100,15 +95,6 @@ // |available_buffers_|. void RecreateBuffers(); - // Destroys all allocated buffers. This should be used when the renderer knows - // these buffers will no longer be needed, e.g. when delegating to the system - // compositor. - // Buffers will be recreated the next time GetCurrentBuffer() is called. - // NOTE: This should not be used on platforms that use buffers for - // overlay testing because GetLastSwappedBuffer() will not recreate the - // buffers. - void DestroyBuffers(); - private: friend class BufferQueueTest; friend class BufferQueueMockedSharedImageInterfaceTest; @@ -141,10 +127,6 @@ // Return a buffer that is available to be drawn into. std::unique_ptr<AllocatedBuffer> GetNextBuffer(); - // If |buffers_destroyed_| = true, this will create |number_of_buffers_| - // buffers with the settings last set by Reshape(). - void RecreateBuffersIfDestroyed(); - // Used to create and destroy shared images. const raw_ptr<SkiaOutputSurface> skia_output_surface_; // Used when creating shared images. @@ -171,15 +153,6 @@ // may be nullptr, if they represent frames that have been destroyed, or // frames where SwapBuffers() was called without calling GetCurrentBuffer(). base::circular_deque<std::unique_ptr<AllocatedBuffer>> in_flight_buffers_; - - // Whether the buffers have been destroyed and are not yet recreated. - bool buffers_destroyed_ = false; - // Started when DestroyBuffers() destroys all buffers, and reported the next - // time RecreateBuffersIfDestroyed() is called. The timer will be reset after - // reporting. - // Used to see how often we destroy buffers and recreate them very soon, which - // we want to be rare. - absl::optional<base::ElapsedTimer> destroyed_timer_; }; } // namespace viz
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc index 81bab320..25d54da 100644 --- a/components/viz/service/display_embedder/buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -591,32 +591,4 @@ EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb4); } -TEST_F(BufferQueueTest, DestroyBuffers) { - EXPECT_TRUE(buffer_queue_->Reshape(screen_size, kBufferQueueColorSpace, - kBufferQueueFormat)); - auto mb1 = SendDamagedFrame(small_damage); - auto mb2 = SendDamagedFrame(small_damage); - auto mb3 = SendDamagedFrame(small_damage); - std::vector<gpu::Mailbox> original_buffers = {mb1, mb2, mb3}; - - EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb1); - buffer_queue_->SwapBuffers(small_damage); - EXPECT_EQ(buffer_queue_->GetCurrentBuffer(), mb2); - buffer_queue_->SwapBuffers(small_damage); - - buffer_queue_->DestroyBuffers(); - - // All buffers are destroyed, and GetLastSwappedBuffer should not recreate - // them. - EXPECT_TRUE(buffer_queue_->GetLastSwappedBuffer().IsZero()); - buffer_queue_->SwapBuffersComplete(); // mb1 - EXPECT_TRUE(buffer_queue_->GetLastSwappedBuffer().IsZero()); - - // GetCurrentBuffer should create the new buffers. - auto mb4 = buffer_queue_->GetCurrentBuffer(); - EXPECT_FALSE(mb4.IsZero()); - EXPECT_THAT(original_buffers, Not(Contains(mb4))); - EXPECT_FALSE(buffer_queue_->GetLastSwappedBuffer().IsZero()); -} - } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc index 3da721e..a3c07a7 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
@@ -161,8 +161,7 @@ SkAlphaType alpha_type, uint32_t usage, bool is_thread_safe) override { - size_t estimated_size = - ResourceSizes::CheckedSizeInBytes<size_t>(size, format); + size_t estimated_size = format.EstimatedSizeInBytes(size); auto result = std::make_unique<gpu::TestImageBacking>( mailbox, format, size, color_space, surface_origin, alpha_type, usage, estimated_size);
diff --git a/components/viz/service/frame_sinks/frame_counter.cc b/components/viz/service/frame_sinks/frame_counter.cc index b7e62e8..4b26b00 100644 --- a/components/viz/service/frame_sinks/frame_counter.cc +++ b/components/viz/service/frame_sinks/frame_counter.cc
@@ -4,6 +4,7 @@ #include "components/viz/service/frame_sinks/frame_counter.h" +#include <limits> #include <utility> #include <vector> @@ -21,8 +22,9 @@ } // namespace -FrameCounter::FrameCounter(base::TimeDelta bucket_size) - : start_time_(base::TimeTicks::Now()), bucket_size_(bucket_size) {} +FrameCounter::FrameCounter(base::TimeTicks start_time, + base::TimeDelta bucket_size) + : start_time_(start_time), bucket_size_(bucket_size) {} FrameCounter::~FrameCounter() = default; @@ -32,7 +34,7 @@ DCHECK(!base::Contains(frame_sink_data_, frame_sink_id)); auto per_sink_data = mojom::FrameCountingPerSinkData::New( - type, is_root, std::vector<uint16_t>()); + type, is_root, 0, std::vector<uint16_t>()); per_sink_data->presented_frames.reserve(kMaxFrameRecords); frame_sink_data_[frame_sink_id] = std::move(per_sink_data); @@ -43,16 +45,28 @@ auto& per_sink_data = frame_sink_data_[frame_sink_id]; DCHECK(!per_sink_data.is_null()); - DCHECK_LE(start_time_, present_timestamp); + if (start_time_ > present_timestamp) { + LOG(WARNING) << "Presentation timestamp is less than start time, skip."; + return; + } + size_t bucket_index = (present_timestamp - start_time_).InSeconds() / bucket_size_.InSeconds(); DCHECK_LT(bucket_index, kMaxFrameRecords); auto& presented_frames = per_sink_data->presented_frames; - if (bucket_index >= presented_frames.size()) - presented_frames.resize(bucket_index + 1, 0u); - ++presented_frames[bucket_index]; + if (presented_frames.empty()) { + CHECK_LT(bucket_index, std::numeric_limits<uint16_t>::max()); + per_sink_data->start_bucket = bucket_index; + } + + const size_t relative_index = bucket_index - per_sink_data->start_bucket; + if (relative_index >= presented_frames.size()) { + presented_frames.resize(relative_index + 1, 0u); + } + + ++presented_frames[relative_index]; } mojom::FrameCountingDataPtr FrameCounter::TakeData() {
diff --git a/components/viz/service/frame_sinks/frame_counter.h b/components/viz/service/frame_sinks/frame_counter.h index fcfbe59d..3b6b41e 100644 --- a/components/viz/service/frame_sinks/frame_counter.h +++ b/components/viz/service/frame_sinks/frame_counter.h
@@ -18,7 +18,7 @@ // per frame sink. class VIZ_SERVICE_EXPORT FrameCounter { public: - explicit FrameCounter(base::TimeDelta bucket_size); + FrameCounter(base::TimeTicks start_time, base::TimeDelta bucket_size); ~FrameCounter(); // Add a record for a frame sink.
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index 2e42441..5e18213 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -830,9 +830,10 @@ } void FrameSinkManagerImpl::StartFrameCountingForTest( + base::TimeTicks start_time, base::TimeDelta bucket_size) { DCHECK(!frame_counter_.has_value()); - frame_counter_.emplace(bucket_size); + frame_counter_.emplace(start_time, bucket_size); for (auto& [sink_id, support] : support_map_) { DCHECK_EQ(sink_id, support->frame_sink_id());
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h index 3347a4a5f..1e39a0e4 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -157,7 +157,8 @@ base::TimeDelta interval) override; void StartThrottlingAllFrameSinks(base::TimeDelta interval) override; void StopThrottlingAllFrameSinks() override; - void StartFrameCountingForTest(base::TimeDelta bucket_size) override; + void StartFrameCountingForTest(base::TimeTicks start_time, + base::TimeDelta bucket_size) override; void StopFrameCountingForTest( StopFrameCountingForTestCallback callback) override;
diff --git a/components/viz/test/test_frame_sink_manager.h b/components/viz/test/test_frame_sink_manager.h index e4652ba..72b28ee 100644 --- a/components/viz/test/test_frame_sink_manager.h +++ b/components/viz/test/test_frame_sink_manager.h
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/time/time.h" #include "components/viz/common/surfaces/frame_sink_bundle_id.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -75,7 +76,8 @@ base::TimeDelta interval) override {} void StartThrottlingAllFrameSinks(base::TimeDelta interval) override {} void StopThrottlingAllFrameSinks() override {} - void StartFrameCountingForTest(base::TimeDelta bucket_size) override {} + void StartFrameCountingForTest(base::TimeTicks start_time, + base::TimeDelta bucket_size) override {} void StopFrameCountingForTest( StopFrameCountingForTestCallback callback) override {}
diff --git a/components/webapk/OWNERS b/components/webapk/OWNERS index e2ef192a..3f3a939 100644 --- a/components/webapk/OWNERS +++ b/components/webapk/OWNERS
@@ -1,3 +1 @@ -eirage@chromium.org -hartmanng@chromium.org -yfriedman@chromium.org +file://chrome/android/webapk/OWNERS \ No newline at end of file
diff --git a/components/zoom/zoom_controller.cc b/components/zoom/zoom_controller.cc index 098b984..3906b76f 100644 --- a/components/zoom/zoom_controller.cc +++ b/components/zoom/zoom_controller.cc
@@ -53,6 +53,9 @@ ZoomController::~ZoomController() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + for (auto& observer : observers_) { + observer.OnZoomControllerDestroyed(); + } } bool ZoomController::IsAtDefaultZoom() const { @@ -319,6 +322,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); // At this point we should no longer be sending any zoom events with this // WebContents. + for (auto& observer : observers_) { + observer.OnZoomControllerDestroyed(); + } observers_.Clear(); }
diff --git a/components/zoom/zoom_controller.h b/components/zoom/zoom_controller.h index 87d7463..85c5da9 100644 --- a/components/zoom/zoom_controller.h +++ b/components/zoom/zoom_controller.h
@@ -195,7 +195,7 @@ scoped_refptr<const ZoomRequestClient> last_client_; // Observer receiving notifications on state changes. - base::ObserverList<ZoomObserver>::Unchecked observers_; + base::ObserverList<ZoomObserver> observers_; raw_ptr<content::BrowserContext> browser_context_; // Keep track of the HostZoomMap we're currently subscribed to.
diff --git a/components/zoom/zoom_observer.h b/components/zoom/zoom_observer.h index 48bfd05..4ba2087f 100644 --- a/components/zoom/zoom_observer.h +++ b/components/zoom/zoom_observer.h
@@ -10,14 +10,14 @@ namespace zoom { // Interface for objects that wish to be notified of changes in ZoomController. -class ZoomObserver { +class ZoomObserver : public base::CheckedObserver { public: + // Fired when the WebContents or the ZoomController is destructed. + virtual void OnZoomControllerDestroyed() {} + // Notification that the zoom percentage has changed. virtual void OnZoomChanged(const ZoomController::ZoomChangedEventData& data) { } - - protected: - virtual ~ZoomObserver() {} }; } // namespace zoom
diff --git a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h index 4e8720f9..24161568 100644 --- a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h +++ b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.h
@@ -62,6 +62,7 @@ uint32_t operation_mask, const gfx::ImageSkia& image, const gfx::Vector2d& image_offset) override; + void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; void Destroy() override; private:
diff --git a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm index 2f3e5361..11f898f 100644 --- a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm +++ b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm
@@ -110,4 +110,9 @@ offset:offset]; } +void WebContentsNSViewBridge::UpdateWindowControlsOverlay( + const gfx::Rect& bounding_rect) { + [ns_view_ updateWindowControlsOverlay:bounding_rect]; +} + } // namespace remote_cocoa
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.h b/content/app_shim_remote_cocoa/web_contents_view_cocoa.h index 06c2294a..e87d2f55 100644 --- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.h +++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.h
@@ -50,6 +50,8 @@ NSDragOperation _dragOperation; NSPoint _dragOffset; CGFloat _dragImageHeight; + + gfx::Rect _windowControlsOverlayRect; } // Set or un-set the mojo interface through which to communicate with the @@ -86,6 +88,8 @@ // immediately or in the near future. - (void)updateWebContentsVisibility:(remote_cocoa::mojom::Visibility)visibility; +- (void)updateWindowControlsOverlay:(const gfx::Rect&)boundingRect; + @end @interface NSWindow (WebContentsViewCocoa)
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm index 81c2cae..759b5680 100644 --- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
@@ -613,6 +613,28 @@ return _viewsHostableView; } +- (void)updateWindowControlsOverlay:(const gfx::Rect&)boundingRect { + _windowControlsOverlayRect = boundingRect; +} + +- (NSView*)hitTest:(NSPoint)point { + if (!_windowControlsOverlayRect.IsEmpty()) { + // _windowControlsOverlayRect represents the area at the top of the web + // contents that is available for the web. As such, if the y coordinate + // falls within this rect, but the x coordinate doesn't we want to route + // events to the BridgedContentView (our superview) instead. + gfx::Point p = gfx::Point(point); + p.set_y(NSHeight(self.bounds) - p.y()); + if (p.y() >= _windowControlsOverlayRect.y() && + p.y() < _windowControlsOverlayRect.bottom() && + (p.x() < _windowControlsOverlayRect.x() || + p.x() >= _windowControlsOverlayRect.right())) { + return self.superview; + } + } + return [super hitTest:point]; +} + @end @implementation NSWindow (WebContentsViewCocoa)
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index f8325e9..8287ce0 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1130,6 +1130,8 @@ "interest_group/interest_group_k_anonymity_manager.h", "interest_group/interest_group_manager_impl.cc", "interest_group/interest_group_manager_impl.h", + "interest_group/interest_group_pa_report_util.cc", + "interest_group/interest_group_pa_report_util.h", "interest_group/interest_group_permissions_cache.cc", "interest_group/interest_group_permissions_cache.h", "interest_group/interest_group_permissions_checker.cc",
diff --git a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm index 25018022..4df612f 100644 --- a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm +++ b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
@@ -257,11 +257,13 @@ )~~"); } +// This test proves AXCellForColumnAndRow([0, 0])=NULL because +// NULL values are filtered by the dump tree formatter. IN_PROC_BROWSER_TEST_F(AXTreeFormatterMacBrowserTest, ParameterizedAttributesIntArrayNilValue) { TestFormat(R"~~(<table role="grid"></table>)~~", {"AXCellForColumnAndRow([0, 0])=*"}, R"~~(AXWebArea -++AXTable AXCellForColumnAndRow([0, 0])=NULL +++AXTable ++++AXGroup )~~"); }
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index d1209ac..fe52e274 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -129,7 +129,7 @@ PlatformChildIterator& operator--() override; PlatformChildIterator operator--(int); gfx::NativeViewAccessible GetNativeViewAccessible() const override; - BrowserAccessibility* get() const; + BrowserAccessibility* get() const override; absl::optional<size_t> GetIndexInParent() const override; BrowserAccessibility& operator*() const override; BrowserAccessibility* operator->() const override;
diff --git a/content/browser/android/dialog_overlay_impl.cc b/content/browser/android/dialog_overlay_impl.cc index 53c4f62..c23b0c9 100644 --- a/content/browser/android/dialog_overlay_impl.cc +++ b/content/browser/android/dialog_overlay_impl.cc
@@ -34,7 +34,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return 0; }
diff --git a/content/browser/attribution_reporting/attribution_debug_report.cc b/content/browser/attribution_reporting/attribution_debug_report.cc index b2a788d..4069fe3 100644 --- a/content/browser/attribution_reporting/attribution_debug_report.cc +++ b/content/browser/attribution_reporting/attribution_debug_report.cc
@@ -86,6 +86,7 @@ case EventLevelResult::kSuccess: case EventLevelResult::kProhibitedByBrowserPolicy: case EventLevelResult::kSuccessDroppedLowerPriority: + case EventLevelResult::kNotRegistered: return absl::nullopt; case EventLevelResult::kInternalError: return DataTypeIfCookieSet(DebugDataType::kTriggerUnknownError,
diff --git a/content/browser/attribution_reporting/attribution_debug_report_unittest.cc b/content/browser/attribution_reporting/attribution_debug_report_unittest.cc index b18c0e7..4d2b82d5 100644 --- a/content/browser/attribution_reporting/attribution_debug_report_unittest.cc +++ b/content/browser/attribution_reporting/attribution_debug_report_unittest.cc
@@ -600,6 +600,13 @@ }, "type": "trigger-event-report-window-passed" }])json"}, + {EventLevelResult::kNotRegistered, + /*replaced_event_level_report=*/absl::nullopt, + /*new_event_level_report=*/absl::nullopt, + /*source=*/absl::nullopt, CreateReportResult::Limits(), + /*dropped_event_level_report=*/absl::nullopt, + /*trigger_debug_key=*/absl::nullopt, + /*expected_report_body=*/nullptr}, }; for (bool is_debug_cookie_set : {false, true}) {
diff --git a/content/browser/attribution_reporting/attribution_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom index fe70567..2a6d94e 100644 --- a/content/browser/attribution_reporting/attribution_internals.mojom +++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -170,6 +170,7 @@ kProhibitedByBrowserPolicy, kDeduplicated, kReportWindowPassed, + kNotRegistered, // Event-level statuses: kLowPriority, @@ -180,7 +181,6 @@ // Aggregatable statuses: kNoHistograms, kInsufficientBudget, - kNotRegistered, }; Status event_level_status;
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc index 002d447..3f7ac7a5 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -467,6 +467,8 @@ return WebUITriggerStatus::kExcessiveEventLevelReports; case EventLevelStatus::kReportWindowPassed: return WebUITriggerStatus::kReportWindowPassed; + case EventLevelStatus::kNotRegistered: + return WebUITriggerStatus::kNotRegistered; } }
diff --git a/content/browser/attribution_reporting/attribution_interop_parser.cc b/content/browser/attribution_reporting/attribution_interop_parser.cc index 188cbfb..b25083b 100644 --- a/content/browser/attribution_reporting/attribution_interop_parser.cc +++ b/content/browser/attribution_reporting/attribution_interop_parser.cc
@@ -351,6 +351,41 @@ return aggregatable_results; } +base::Value::List AttributionInteropParser::ParseVerboseDebugReports( + base::Value::Dict& output) { + static constexpr char kKey[] = "verbose_debug_reports"; + + base::Value::List reports; + + base::Value* value = output.Find(kKey); + if (!value) { + return reports; + } + + auto context = PushContext(kKey); + ParseList(output.Find(kKey), + base::BindLambdaForTesting([&](base::Value value) { + if (!EnsureDictionary(&value)) { + return; + } + + base::Value::Dict report; + + base::Value::Dict& value_dict = value.GetDict(); + MoveValue(value_dict, "report", report, "payload"); + MoveValue(value_dict, "report_url", report); + MoveValue(value_dict, "report_time", report); + + if (has_error()) { + return; + } + + reports.Append(std::move(report)); + })); + + return reports; +} + absl::optional<base::Value> AttributionInteropParser::InteropOutputFromSimulatorOutput(base::Value output) { error_manager_.ResetErrorState(); @@ -365,6 +400,9 @@ base::Value::List aggregatable_results = ParseAggregatableReports(output.GetDict()); + base::Value::List verbose_debug_reports = + ParseVerboseDebugReports(output.GetDict()); + if (has_error()) { return absl::nullopt; } @@ -378,6 +416,10 @@ dict.Set("aggregatable_results", std::move(aggregatable_results)); } + if (!verbose_debug_reports.empty()) { + dict.Set("verbose_debug_reports", std::move(verbose_debug_reports)); + } + return base::Value(std::move(dict)); }
diff --git a/content/browser/attribution_reporting/attribution_interop_parser.h b/content/browser/attribution_reporting/attribution_interop_parser.h index fa38114f..de095ca1 100644 --- a/content/browser/attribution_reporting/attribution_interop_parser.h +++ b/content/browser/attribution_reporting/attribution_interop_parser.h
@@ -92,6 +92,8 @@ base::Value::List ParseAggregatableReports(base::Value::Dict& output); + base::Value::List ParseVerboseDebugReports(base::Value::Dict& output); + // Returns true if `key` is present in `dict` and the integer is parsed // successfully. template <typename T>
diff --git a/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc b/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc index 1c56c48..8a186cb 100644 --- a/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc +++ b/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc
@@ -159,6 +159,19 @@ "value": "0x159" }] } + }], + "verbose_debug_reports": [{ + "report": [{ + "body": { + "attribution_destination": "https://destination2.test", + "limit": "1", + "source_event_id": "222", + "source_site": "https://source1.test" + }, + "type": "source-destination-limit" + }], + "report_time": "1643235575000", + "report_url": "https://reporter1.test/.well-known/attribution-reporting/debug/verbose" }] })json"; @@ -184,6 +197,19 @@ "value": "0x159" }] } + }], + "verbose_debug_reports": [{ + "payload": [{ + "body": { + "attribution_destination": "https://destination2.test", + "limit": "1", + "source_event_id": "222", + "source_site": "https://source1.test" + }, + "type": "source-destination-limit" + }], + "report_time": "1643235575000", + "report_url": "https://reporter1.test/.well-known/attribution-reporting/debug/verbose" }] })json"; @@ -843,6 +869,45 @@ } }] })json", + }, + { + R"(["verbose_debug_reports"]: must be a list)", + R"json({ + "verbose_debug_reports": {} + })json", + }, + { + R"(["verbose_debug_reports"][0]: must be a dictionary)", + R"json({ + "verbose_debug_reports": [""] + })json", + }, + { + R"(["verbose_debug_reports"][0]["report"]: must be present)", + R"json({ + "verbose_debug_reports": [{ + "report_time": "", + "report_url": "" + }] + })json", + }, + { + R"(["verbose_debug_reports"][0]["report_time"]: must be present)", + R"json({ + "verbose_debug_reports": [{ + "report": [], + "report_url": "" + }] + })json", + }, + { + R"(["verbose_debug_reports"][0]["report_url"]: must be present)", + R"json({ + "verbose_debug_reports": [{ + "report": [], + "report_time": "" + }] + })json", }}; INSTANTIATE_TEST_SUITE_P(AttributionInteropParserInvalidOutputs,
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc index 19cd9e0..bd9a5269 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -169,9 +169,9 @@ void RecordCreateReportStatus(CreateReportResult result) { static_assert(AttributionTrigger::EventLevelResult::kMaxValue == - AttributionTrigger::EventLevelResult::kReportWindowPassed, - "Bump version of Conversions.CreateReportStatus6 histogram."); - base::UmaHistogramEnumeration("Conversions.CreateReportStatus6", + AttributionTrigger::EventLevelResult::kNotRegistered, + "Bump version of Conversions.CreateReportStatus7 histogram."); + base::UmaHistogramEnumeration("Conversions.CreateReportStatus7", result.event_level_status()); static_assert( AttributionTrigger::AggregatableResult::kMaxValue ==
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc index db6c0e0..a743c7a 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -1079,13 +1079,16 @@ GURL session_only_origin("https://sessiononly.example"); auto impression = SourceBuilder() - .SetSourceOrigin(*SuitableOrigin::Create(session_only_origin)) + .SetReportingOrigin(*SuitableOrigin::Create(session_only_origin)) .Build(); mock_storage_policy_->AddSessionOnly(session_only_origin); attribution_manager_->HandleSource(impression); - attribution_manager_->HandleTrigger(DefaultTrigger()); + attribution_manager_->HandleTrigger( + TriggerBuilder() + .SetReportingOrigin(impression.common_info().reporting_origin()) + .Build()); EXPECT_THAT(StoredSources(), SizeIs(1)); EXPECT_THAT(StoredReports(), SizeIs(1)); @@ -1097,38 +1100,6 @@ EXPECT_THAT(StoredReports(), IsEmpty()); } -TEST_F(AttributionManagerImplTest, - SessionOnlyOrigins_DeletedIfAnyOriginMatches) { - const auto session_only_origin = - *SuitableOrigin::Deserialize("https://sessiononly.example"); - // Create impressions which each have the session only origin as one of - // impression/conversion/reporting origin. - auto impression1 = - SourceBuilder().SetSourceOrigin(session_only_origin).Build(); - auto impression2 = - SourceBuilder().SetReportingOrigin(session_only_origin).Build(); - auto impression3 = - SourceBuilder().SetDestinationOrigin(session_only_origin).Build(); - - // Create one impression which is not session only. - auto impression4 = SourceBuilder().Build(); - - mock_storage_policy_->AddSessionOnly(session_only_origin->GetURL()); - - attribution_manager_->HandleSource(impression1); - attribution_manager_->HandleSource(impression2); - attribution_manager_->HandleSource(impression3); - attribution_manager_->HandleSource(impression4); - - EXPECT_THAT(StoredSources(), SizeIs(4)); - - ShutdownManager(); - CreateManager(); - - // All session-only impressions should be deleted. - EXPECT_THAT(StoredSources(), SizeIs(1)); -} - // Tests that trigger priority cannot result in more than the maximum number of // reports being sent. A report will never be queued for the expiry window while // the source is active given we only queue reports which are reported within @@ -1171,7 +1142,7 @@ attribution_manager_->HandleTrigger(DefaultTrigger()); EXPECT_THAT(StoredReports(), IsEmpty()); histograms.ExpectUniqueSample( - "Conversions.CreateReportStatus6", + "Conversions.CreateReportStatus7", AttributionTrigger::EventLevelResult::kNoMatchingImpressions, 1); histograms.ExpectUniqueSample( "Conversions.AggregatableReport.CreateReportStatus3",
diff --git a/content/browser/attribution_reporting/attribution_observer_types.cc b/content/browser/attribution_reporting/attribution_observer_types.cc index dec3991..d5608668 100644 --- a/content/browser/attribution_reporting/attribution_observer_types.cc +++ b/content/browser/attribution_reporting/attribution_observer_types.cc
@@ -58,7 +58,8 @@ replaced_event_level_report_.has_value(), event_level_status_ == EventLevelResult::kSuccessDroppedLowerPriority); - if (event_level_status_ != EventLevelResult::kInternalError) { + if (event_level_status_ != EventLevelResult::kInternalError && + event_level_status_ != EventLevelResult::kNotRegistered) { DCHECK_EQ(source_.has_value(), event_level_status_ != EventLevelResult::kNoMatchingImpressions && event_level_status_ !=
diff --git a/content/browser/attribution_reporting/attribution_report_network_sender.cc b/content/browser/attribution_reporting/attribution_report_network_sender.cc index 19d9b00..591c021 100644 --- a/content/browser/attribution_reporting/attribution_report_network_sender.cc +++ b/content/browser/attribution_reporting/attribution_report_network_sender.cc
@@ -74,7 +74,7 @@ std::string body = SerializeAttributionJson(report.ReportBody()); SendReport( std::move(url), body, net::HttpRequestHeaders(), - base::BindOnce(&AttributionReportNetworkSender::OnDebugReportSent, + base::BindOnce(&AttributionReportNetworkSender::OnVerboseDebugReportSent, base::Unretained(this), base::BindOnce(std::move(callback), std::move(report)))); } @@ -236,17 +236,20 @@ headers ? headers->response_code() : 0)); } -void AttributionReportNetworkSender::OnDebugReportSent( +void AttributionReportNetworkSender::OnVerboseDebugReportSent( base::OnceCallback<void(int status)> callback, UrlLoaderList::iterator it, scoped_refptr<net::HttpResponseHeaders> headers) { // HTTP statuses are positive; network errors are negative. int status = headers ? headers->response_code() : (*it)->NetError(); + + // Since net errors are always negative and HTTP errors are always positive, + // it is fine to combine these in a single histogram. + base::UmaHistogramSparse( + "Conversions.VerboseDebugReport.HttpResponseOrNetErrorCode", status); + loaders_in_progress_.erase(it); std::move(callback).Run(status); - - // TODO(crbug.com/1371970): Consider recording metric for debug report - // sending. } } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_report_network_sender.h b/content/browser/attribution_reporting/attribution_report_network_sender.h index bab2ac2..87544edf 100644 --- a/content/browser/attribution_reporting/attribution_report_network_sender.h +++ b/content/browser/attribution_reporting/attribution_report_network_sender.h
@@ -74,10 +74,11 @@ UrlLoaderList::iterator it, scoped_refptr<net::HttpResponseHeaders> headers); - // Called when headers are available for a sent debug report. - void OnDebugReportSent(base::OnceCallback<void(int status)> callback, - UrlLoaderList::iterator it, - scoped_refptr<net::HttpResponseHeaders> headers); + // Called when headers are available for a sent verbose debug report. + void OnVerboseDebugReportSent( + base::OnceCallback<void(int status)> callback, + UrlLoaderList::iterator it, + scoped_refptr<net::HttpResponseHeaders> headers); // Reports that are actively being sent. UrlLoaderList loaders_in_progress_;
diff --git a/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc b/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc index 48e4497..745abab 100644 --- a/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc +++ b/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc
@@ -64,6 +64,9 @@ "https://report.test/.well-known/attribution-reporting/debug/" "report-aggregate-attribution"; +const char kVerboseDebugReportMetricName[] = + "Conversions.VerboseDebugReport.HttpResponseOrNetErrorCode"; + AttributionReport DefaultEventLevelReport() { return ReportBuilder( AttributionInfoBuilder(SourceBuilder(base::Time()).BuildStored()) @@ -1001,6 +1004,8 @@ TEST_F(AttributionReportNetworkSenderTest, ErrorReportSent_ReportBodySetCorrectly) { + base::HistogramTester histograms; + static constexpr char kExpectedReportBody[] = R"([{)" R"("body":{)" @@ -1035,10 +1040,15 @@ EXPECT_EQ(kExpectedReportBody, network::GetUploadData(*pending_request)); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( kErrorReportUrl, "")); + + histograms.ExpectUniqueSample(kVerboseDebugReportMetricName, + net::HttpStatusCode::HTTP_OK, 1); } TEST_F(AttributionReportNetworkSenderTest, ErrorReportSent_CallbackInvokedWithNetworkError) { + base::HistogramTester histograms; + static constexpr char kErrorReportUrl[] = "https://report.test/.well-known/attribution-reporting/debug/verbose"; @@ -1065,6 +1075,9 @@ GURL(kErrorReportUrl), network::URLLoaderCompletionStatus(net::ERR_CONNECTION_ABORTED), network::mojom::URLResponseHead::New(), ""); + + histograms.ExpectUniqueSample(kVerboseDebugReportMetricName, + net::ERR_CONNECTION_ABORTED, 1); } } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_storage.h b/content/browser/attribution_reporting/attribution_storage.h index 8870a59..f2c782c 100644 --- a/content/browser/attribution_reporting/attribution_storage.h +++ b/content/browser/attribution_reporting/attribution_storage.h
@@ -122,14 +122,17 @@ // report time in storage, if any. virtual absl::optional<base::Time> AdjustOfflineReportTimes() = 0; - // Deletes all data in storage for storage keys matching `filter`, between - // `delete_begin` and `delete_end` time. More specifically, this: + // Deletes all data in storage for reporting origins matching `filter`, + // between `delete_begin` and `delete_end` time. More specifically, this: // 1. Deletes all sources within the time range. If any report is // attributed to this source it is also deleted. // 2. Deletes all reports within the time range. All sources // attributed to the report are also deleted. + // 3. Deletes any rate limits matching `filter` or whose corresponding source + // was deleted. // - // Note: if `filter` is null, it means that all storage keys should match. + // Note: if `filter` is null, it means that all reporting origins should + // match. virtual void ClearData(base::Time delete_begin, base::Time delete_end, StoragePartition::StorageKeyMatcherFunction filter,
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 8b1267a7..640f19e 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -822,11 +822,20 @@ const attribution_reporting::TriggerRegistration& trigger_registration = trigger.registration(); + if (trigger_registration.event_triggers.vec().empty()) { + event_level_status = EventLevelResult::kNotRegistered; + } + if (trigger_registration.aggregatable_trigger_data.vec().empty() && trigger_registration.aggregatable_values.values().empty()) { aggregatable_status = AggregatableResult::kNotRegistered; } + if (event_level_status.has_value() && aggregatable_status.has_value()) { + return assemble_report_result(/*new_event_level_status=*/absl::nullopt, + /*new_aggregaable_status=*/absl::nullopt); + } + // We don't bother creating the DB here if it doesn't exist, because it's not // possible for there to be a matching source if there's no DB. if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { @@ -871,11 +880,14 @@ } absl::optional<uint64_t> dedup_key; - if (EventLevelResult create_event_level_status = MaybeCreateEventLevelReport( - *attribution_info, trigger, new_event_level_report, dedup_key, - limits.max_event_level_reports_per_destination); - create_event_level_status != EventLevelResult::kSuccess) { - event_level_status = create_event_level_status; + if (!event_level_status.has_value()) { + if (EventLevelResult create_event_level_status = + MaybeCreateEventLevelReport( + *attribution_info, trigger, new_event_level_report, dedup_key, + limits.max_event_level_reports_per_destination); + create_event_level_status != EventLevelResult::kSuccess) { + event_level_status = create_event_level_status; + } } if (!aggregatable_status.has_value()) { @@ -1676,17 +1688,12 @@ std::vector<StoredSource::Id> source_ids_to_delete; int num_event_reports_deleted = 0; while (statement.Step()) { - if (filter.is_null() || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(0)))) || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(1)))) || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(2))))) { - source_ids_to_delete.emplace_back(statement.ColumnInt64(3)); - if (statement.GetColumnType(4) != sql::ColumnType::kNull) { + if (filter.is_null() || filter.Run(blink::StorageKey(DeserializeOrigin( + statement.ColumnString(0))))) { + source_ids_to_delete.emplace_back(statement.ColumnInt64(1)); + if (statement.GetColumnType(2) != sql::ColumnType::kNull) { if (!DeleteReportInternal(AttributionReport::EventLevelData::Id( - statement.ColumnInt64(4)))) { + statement.ColumnInt64(2)))) { return; } @@ -2451,18 +2458,13 @@ int num_aggregate_reports_deleted = 0; while (statement.Step()) { - if (filter.is_null() || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(0)))) || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(1)))) || - filter.Run( - blink::StorageKey(DeserializeOrigin(statement.ColumnString(2))))) { - source_ids_to_delete.emplace_back(statement.ColumnInt64(3)); - if (statement.GetColumnType(4) != sql::ColumnType::kNull) { + if (filter.is_null() || filter.Run(blink::StorageKey(DeserializeOrigin( + statement.ColumnString(0))))) { + source_ids_to_delete.emplace_back(statement.ColumnInt64(1)); + if (statement.GetColumnType(2) != sql::ColumnType::kNull) { if (!DeleteReportInternal( AttributionReport::AggregatableAttributionData::Id( - statement.ColumnInt64(4)))) { + statement.ColumnInt64(2)))) { return -1; } ++num_aggregate_reports_deleted;
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc index e0c8d06..993648f 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_query_plans_unittest.cc
@@ -193,5 +193,43 @@ UsesPrimaryKey()); } +TEST_F(AttributionSqlQueryPlanTest, kRateLimitAttributionAllowedSql) { + EXPECT_THAT(GetPlan(attribution_queries::kRateLimitAttributionAllowedSql), + UsesIndex("rate_limit_reporting_origin_idx", + {"scope", "destination_site", "source_site"})); +} + +TEST_F(AttributionSqlQueryPlanTest, kRateLimitSourceAllowedSql) { + EXPECT_THAT(GetPlan(attribution_queries::kRateLimitSourceAllowedSql), + UsesIndex("rate_limit_source_site_reporting_origin_idx", + {"scope", "source_site", "reporting_origin"})); +} + +TEST_F(AttributionSqlQueryPlanTest, kRateLimitSelectReportingOriginsSql) { + EXPECT_THAT(GetPlan(attribution_queries::kRateLimitSelectReportingOriginsSql), + UsesIndex("rate_limit_reporting_origin_idx", + {"scope", "destination_site", "source_site"})); +} + +TEST_F(AttributionSqlQueryPlanTest, kDeleteRateLimitRangeSql) { + EXPECT_THAT(GetPlan(attribution_queries::kDeleteRateLimitRangeSql), + UsesIndex("rate_limit_time_idx")); +} + +TEST_F(AttributionSqlQueryPlanTest, kSelectRateLimitsForDeletionSql) { + EXPECT_THAT(GetPlan(attribution_queries::kSelectRateLimitsForDeletionSql), + UsesIndex("rate_limit_time_idx")); +} + +TEST_F(AttributionSqlQueryPlanTest, kDeleteExpiredRateLimitsSql) { + EXPECT_THAT(GetPlan(attribution_queries::kDeleteExpiredRateLimitsSql), + UsesIndex("rate_limit_time_idx")); +} + +TEST_F(AttributionSqlQueryPlanTest, kDeleteRateLimitsBySourceIdSql) { + EXPECT_THAT(GetPlan(attribution_queries::kDeleteRateLimitsBySourceIdSql), + UsesIndex("rate_limit_source_id_idx")); +} + } // namespace } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc index d6f5605c..5d06cab 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_unittest.cc
@@ -403,7 +403,7 @@ base::Time::Min(), base::Time::Max(), base::BindRepeating( std::equal_to<blink::StorageKey>(), - blink::StorageKey(source.common_info().source_origin()))); + blink::StorageKey(source.common_info().reporting_origin()))); EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); CloseDatabase(); @@ -457,7 +457,7 @@ base::Time::Now(), base::Time::Now(), base::BindRepeating( std::equal_to<blink::StorageKey>(), - blink::StorageKey(source.common_info().source_origin()))); + blink::StorageKey(source.common_info().reporting_origin()))); EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); CloseDatabase(); @@ -650,108 +650,6 @@ EXPECT_EQ(3u, rate_limit_rows); } -TEST_F(AttributionStorageSqlTest, - DeleteRateLimitRowsForSubdomainImpressionOrigin) { - OpenDatabase(); - delegate()->set_max_attributions_per_source(1); - delegate()->set_rate_limits({ - .time_window = base::Days(7), - .max_source_registration_reporting_origins = - std::numeric_limits<int64_t>::max(), - .max_attribution_reporting_origins = std::numeric_limits<int64_t>::max(), - .max_attributions = std::numeric_limits<int64_t>::max(), - }); - const auto source_origin = - *SuitableOrigin::Deserialize("https://sub.impression.example/"); - const auto reporting_origin = - *SuitableOrigin::Deserialize("https://a.example/"); - const auto destination_origin = - *SuitableOrigin::Deserialize("https://b.example/"); - storage()->StoreSource(SourceBuilder() - .SetExpiry(base::Days(30)) - .SetSourceOrigin(source_origin) - .SetReportingOrigin(reporting_origin) - .SetDestinationOrigin(destination_origin) - .Build()); - - task_environment_.FastForwardBy(base::Days(1)); - EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, - MaybeCreateAndStoreEventLevelReport( - TriggerBuilder() - .SetDestinationOrigin(destination_origin) - .SetReportingOrigin(reporting_origin) - .Build())); - EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); - - task_environment_.FastForwardBy(base::Days(1)); - EXPECT_TRUE( - storage()->DeleteReport(AttributionReport::EventLevelData::Id(1))); - storage()->ClearData(base::Time::Min(), base::Time::Max(), - base::BindRepeating(std::equal_to<blink::StorageKey>(), - blink::StorageKey(source_origin))); - - CloseDatabase(); - sql::Database raw_db; - EXPECT_TRUE(raw_db.Open(db_path())); - size_t conversion_rows; - sql::test::CountTableRows(&raw_db, "event_level_reports", &conversion_rows); - EXPECT_EQ(0u, conversion_rows); - size_t rate_limit_rows; - sql::test::CountTableRows(&raw_db, "rate_limits", &rate_limit_rows); - EXPECT_EQ(0u, rate_limit_rows); -} - -TEST_F(AttributionStorageSqlTest, - DeleteRateLimitRowsForSubdomainConversionOrigin) { - OpenDatabase(); - delegate()->set_max_attributions_per_source(1); - delegate()->set_rate_limits({ - .time_window = base::Days(7), - .max_source_registration_reporting_origins = - std::numeric_limits<int64_t>::max(), - .max_attribution_reporting_origins = std::numeric_limits<int64_t>::max(), - .max_attributions = std::numeric_limits<int64_t>::max(), - }); - const auto source_origin = *SuitableOrigin::Deserialize("https://b.example/"); - const auto reporting_origin = - *SuitableOrigin::Deserialize("https://a.example/"); - const auto destination_origin = - *SuitableOrigin::Deserialize("https://sub.impression.example/"); - storage()->StoreSource(SourceBuilder() - .SetExpiry(base::Days(30)) - .SetSourceOrigin(source_origin) - .SetReportingOrigin(reporting_origin) - .SetDestinationOrigin(destination_origin) - .Build()); - - task_environment_.FastForwardBy(base::Days(1)); - EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, - MaybeCreateAndStoreEventLevelReport( - TriggerBuilder() - .SetDestinationOrigin(destination_origin) - .SetReportingOrigin(reporting_origin) - .Build())); - EXPECT_THAT(storage()->GetActiveSources(), SizeIs(1)); - - task_environment_.FastForwardBy(base::Days(1)); - EXPECT_TRUE( - storage()->DeleteReport(AttributionReport::EventLevelData::Id(1))); - storage()->ClearData( - base::Time::Min(), base::Time::Max(), - base::BindRepeating(std::equal_to<blink::StorageKey>(), - blink::StorageKey(destination_origin))); - - CloseDatabase(); - sql::Database raw_db; - EXPECT_TRUE(raw_db.Open(db_path())); - size_t conversion_rows; - sql::test::CountTableRows(&raw_db, "event_level_reports", &conversion_rows); - EXPECT_EQ(0u, conversion_rows); - size_t rate_limit_rows; - sql::test::CountTableRows(&raw_db, "rate_limits", &rate_limit_rows); - EXPECT_EQ(0u, rate_limit_rows); -} - TEST_F(AttributionStorageSqlTest, CantOpenDb_FailsSilentlyInRelease) { base::CreateDirectoryAndGetError(db_path(), nullptr);
diff --git a/content/browser/attribution_reporting/attribution_storage_unittest.cc b/content/browser/attribution_reporting/attribution_storage_unittest.cc index d92d310..6020cfb 100644 --- a/content/browser/attribution_reporting/attribution_storage_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_unittest.cc
@@ -760,6 +760,27 @@ MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } +TEST_F(AttributionStorageTest, + ClearData_SourceAndDestinationOriginsIrrelevant) { + const auto origin = *SuitableOrigin::Deserialize("https://a.test"); + + storage()->StoreSource(SourceBuilder() + .SetSourceOrigin(origin) + .SetDestinationOrigin(origin) + .Build()); + MaybeCreateAndStoreEventLevelReport( + TriggerBuilder().SetDestinationOrigin(origin).Build()); + + ASSERT_EQ(storage()->GetActiveSources().size(), 1u); + ASSERT_EQ(storage()->GetAttributionReports(base::Time::Max()).size(), 1u); + + storage()->ClearData(base::Time::Min(), base::Time::Max(), + GetMatcher(*origin)); + + EXPECT_EQ(storage()->GetActiveSources().size(), 1u); + EXPECT_EQ(storage()->GetAttributionReports(base::Time::Max()).size(), 1u); +} + TEST_F(AttributionStorageTest, ClearDataOutsideRange_NoDelete) { base::Time now = base::Time::Now(); auto impression = SourceBuilder(now).Build(); @@ -779,7 +800,7 @@ storage()->StoreSource(impression); storage()->ClearData( now, now + base::Minutes(20), - GetMatcher(impression.common_info().destination_origin())); + GetMatcher(impression.common_info().reporting_origin())); EXPECT_EQ(AttributionTrigger::EventLevelResult::kNoMatchingImpressions, MaybeCreateAndStoreEventLevelReport(DefaultTrigger())); } @@ -795,7 +816,7 @@ MaybeCreateAndStoreEventLevelReport(conversion)); storage()->ClearData(now - base::Minutes(20), now + base::Minutes(20), - GetMatcher(impression.common_info().source_origin())); + GetMatcher(impression.common_info().reporting_origin())); EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } @@ -854,7 +875,7 @@ EXPECT_EQ(AttributionTrigger::EventLevelResult::kSuccess, MaybeCreateAndStoreEventLevelReport(conversion)); storage()->ClearData(base::Time::Now(), base::Time::Now(), - GetMatcher(impression.common_info().source_origin())); + GetMatcher(impression.common_info().reporting_origin())); EXPECT_THAT(storage()->GetAttributionReports(base::Time::Max()), IsEmpty()); } @@ -2814,6 +2835,14 @@ TEST_F(AttributionStorageTest, TopLevelTriggerFiltering) { const auto origin = *SuitableOrigin::Deserialize("https://r.test"); + auto event_triggers = *attribution_reporting::EventTriggerDataList::Create( + {attribution_reporting::EventTriggerData( + /*data=*/11, + /*priority=*/12, + /*dedup_key=*/13, + /*filters=*/AttributionFilters(), + /*not_filters=*/AttributionFilters())}); + std::vector<attribution_reporting::AggregatableTriggerData> aggregatable_trigger_data{ *attribution_reporting::AggregatableTriggerData::Create( @@ -2843,8 +2872,7 @@ }), /*not_filters=*/AttributionFilters(), /*debug_key=*/absl::nullopt, - /*aggregatable_dedup_key=*/absl::nullopt, - /*event_triggers=*/attribution_reporting::EventTriggerDataList(), + /*aggregatable_dedup_key=*/absl::nullopt, event_triggers, *attribution_reporting::AggregatableTriggerDataList::Create( aggregatable_trigger_data), aggregatable_values, @@ -2862,8 +2890,7 @@ }), /*not_filters=*/AttributionFilters(), /*debug_key=*/absl::nullopt, - /*aggregatable_dedup_key=*/absl::nullopt, - /*event_triggers=*/attribution_reporting::EventTriggerDataList(), + /*aggregatable_dedup_key=*/absl::nullopt, event_triggers, *attribution_reporting::AggregatableTriggerDataList::Create( aggregatable_trigger_data), aggregatable_values, @@ -2879,8 +2906,7 @@ /*not_filters=*/ AttributionFiltersForSourceType(AttributionSourceType::kNavigation), /*debug_key=*/absl::nullopt, - /*aggregatable_dedup_key=*/absl::nullopt, - /*event_triggers=*/attribution_reporting::EventTriggerDataList(), + /*aggregatable_dedup_key=*/absl::nullopt, event_triggers, *attribution_reporting::AggregatableTriggerDataList::Create( aggregatable_trigger_data), aggregatable_values, @@ -2898,13 +2924,11 @@ AttributionTrigger::AggregatableResult:: kNoMatchingSourceFilterData))); - EXPECT_THAT( - storage()->MaybeCreateAndStoreReport(trigger2), - AllOf( - CreateReportEventLevelStatusIs( - AttributionTrigger::EventLevelResult::kNoMatchingConfigurations), - CreateReportAggregatableStatusIs( - AttributionTrigger::AggregatableResult::kSuccess))); + EXPECT_THAT(storage()->MaybeCreateAndStoreReport(trigger2), + AllOf(CreateReportEventLevelStatusIs( + AttributionTrigger::EventLevelResult::kSuccess), + CreateReportAggregatableStatusIs( + AttributionTrigger::AggregatableResult::kSuccess))); EXPECT_THAT(storage()->MaybeCreateAndStoreReport(trigger3), AllOf(CreateReportEventLevelStatusIs( @@ -3156,4 +3180,18 @@ MaybeCreateAndStoreEventLevelReport(trigger)); } +TEST_F(AttributionStorageTest, NoEventTriggerData_NotRegisteredReturned) { + EXPECT_THAT( + storage()->MaybeCreateAndStoreReport( + DefaultAggregatableTriggerBuilder().Build( + /*generate_event_trigger_data=*/false)), + AllOf(CreateReportEventLevelStatusIs( + AttributionTrigger::EventLevelResult::kNotRegistered), + CreateReportAggregatableStatusIs( + AttributionTrigger::AggregatableResult::kNoMatchingImpressions), + NewEventLevelReportIs(absl::nullopt), + NewAggregatableReportIs(absl::nullopt))); + EXPECT_THAT(storage()->GetAttributionReports(base::Time::Now()), IsEmpty()); +} + } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc index 012107dee..cc25d37 100644 --- a/content/browser/attribution_reporting/attribution_test_utils.cc +++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -1022,6 +1022,8 @@ return out << "falselyAttributedSource"; case AttributionTrigger::EventLevelResult::kReportWindowPassed: return out << "reportWindowPassed"; + case AttributionTrigger::EventLevelResult::kNotRegistered: + return out << "notRegistered"; } }
diff --git a/content/browser/attribution_reporting/attribution_trigger.h b/content/browser/attribution_reporting/attribution_trigger.h index 17f5fa04..11d9fb7 100644 --- a/content/browser/attribution_reporting/attribution_trigger.h +++ b/content/browser/attribution_reporting/attribution_trigger.h
@@ -41,7 +41,8 @@ kExcessiveReports = 13, kFalselyAttributedSource = 14, kReportWindowPassed = 15, - kMaxValue = kReportWindowPassed, + kNotRegistered = 16, + kMaxValue = kNotRegistered, }; // Represents the potential aggregatable outcomes from attempting to register
diff --git a/content/browser/attribution_reporting/rate_limit_table.cc b/content/browser/attribution_reporting/rate_limit_table.cc index 4ac7049d..70f4fc9 100644 --- a/content/browser/attribution_reporting/rate_limit_table.cc +++ b/content/browser/attribution_reporting/rate_limit_table.cc
@@ -14,6 +14,7 @@ #include "content/browser/attribution_reporting/attribution_storage_delegate.h" #include "content/browser/attribution_reporting/common_source_info.h" #include "content/browser/attribution_reporting/rate_limit_result.h" +#include "content/browser/attribution_reporting/sql_queries.h" #include "content/browser/attribution_reporting/sql_utils.h" #include "content/browser/attribution_reporting/storable_source.h" #include "content/public/browser/attribution_config.h" @@ -179,17 +180,10 @@ base::Time min_timestamp = attribution_info.time - rate_limits.time_window; static_assert(static_cast<int>(Scope::kAttribution) == 1, - "update `scope=1` clause below"); + "update `scope=1` in query below"); - static constexpr char kAttributionAllowedSql[] = - "SELECT COUNT(*)FROM rate_limits " - "WHERE scope=1 " - "AND destination_site=? " - "AND source_site=? " - "AND reporting_origin=? " - "AND time>?"; - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kAttributionAllowedSql)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kRateLimitAttributionAllowedSql)); statement.BindString(0, common_info.DestinationSite().Serialize()); statement.BindString(1, common_info.SourceSite().Serialize()); statement.BindString(2, common_info.reporting_origin().Serialize()); @@ -220,18 +214,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); static_assert(static_cast<int>(Scope::kSource) == 0, - "update `scope=0` clause below"); + "update `scope=0` query below"); // Check the number of unique destinations covered by all source registrations // whose [source_time, expiry_time] intersect with the current source_time. - static constexpr char kSourceAllowedSql[] = - "SELECT destination_site FROM rate_limits " - "WHERE scope=0 " - "AND source_site=? " - "AND reporting_origin=? " - "AND expiry_time>?"; - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kSourceAllowedSql)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kRateLimitSourceAllowedSql)); const CommonSourceInfo& common_info = source.common_info(); statement.BindString(0, common_info.SourceSite().Serialize()); @@ -302,13 +290,8 @@ base::Time min_timestamp = time - rate_limits.time_window; - static constexpr char kSelectSql[] = - "SELECT reporting_origin FROM rate_limits " - "WHERE scope=? " - "AND source_site=? " - "AND destination_site=? " - "AND time>?"; - sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSelectSql)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kRateLimitSelectReportingOriginsSql)); statement.BindInt(0, static_cast<int>(scope)); statement.BindString(1, common_info.SourceSite().Serialize()); statement.BindString(2, common_info.DestinationSite().Serialize()); @@ -340,12 +323,8 @@ DCHECK(!((delete_begin.is_null() || delete_begin.is_min()) && delete_end.is_max())); - static constexpr char kDeleteRateLimitRangeSql[] = - // clang-format off - "DELETE FROM rate_limits " - "WHERE time BETWEEN ? AND ?"; // clang-format on - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kDeleteRateLimitRangeSql)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kDeleteRateLimitRangeSql)); statement.BindTime(0, delete_begin); statement.BindTime(1, delete_end); return statement.Run(); @@ -379,25 +358,15 @@ return false; } - static constexpr char kSelectSql[] = - // clang-format off - "SELECT id,source_origin,destination_origin," - "reporting_origin " - "FROM rate_limits " - "WHERE time BETWEEN ? AND ?"; // clang-format on - sql::Statement select_statement( - db->GetCachedStatement(SQL_FROM_HERE, kSelectSql)); + sql::Statement select_statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kSelectRateLimitsForDeletionSql)); select_statement.BindTime(0, delete_begin); select_statement.BindTime(1, delete_end); while (select_statement.Step()) { int64_t rate_limit_id = select_statement.ColumnInt64(0); if (filter.Run(blink::StorageKey( - DeserializeOrigin(select_statement.ColumnString(1)))) || - filter.Run(blink::StorageKey( - DeserializeOrigin(select_statement.ColumnString(2)))) || - filter.Run(blink::StorageKey( - DeserializeOrigin(select_statement.ColumnString(3))))) { + DeserializeOrigin(select_statement.ColumnString(1))))) { // See https://www.sqlite.org/isolation.html for why it's OK for this // DELETE to be interleaved in the surrounding SELECT. delete_statement.Reset(/*clear_bound_vars=*/false); @@ -420,18 +389,14 @@ base::Time timestamp = now - delegate_->GetRateLimits().time_window; static_assert(static_cast<int>(Scope::kAttribution) == 1, - "update `scope=1` clause below"); + "update `scope=1` query below"); // Attribution rate limit entries can be deleted as long as their time falls // outside the rate limit window. For source entries, if the expiry time has // not passed, keep entries around to ensure // `SourceAllowedForDestinationLimit()` is computed properly. - static constexpr char kDeleteExpiredRateLimits[] = - // clang-format off - "DELETE FROM rate_limits " - "WHERE time<=? AND(scope=1 OR expiry_time<=?)"; // clang-format on - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kDeleteExpiredRateLimits)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kDeleteExpiredRateLimitsSql)); statement.BindTime(0, timestamp); statement.BindTime(1, now); return statement.Run(); @@ -447,10 +412,8 @@ return false; } - static constexpr char kDeleteRateLimitSql[] = - "DELETE FROM rate_limits WHERE source_id=?"; - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kDeleteRateLimitSql)); + sql::Statement statement(db->GetCachedStatement( + SQL_FROM_HERE, attribution_queries::kDeleteRateLimitsBySourceIdSql)); for (StoredSource::Id id : source_ids) { statement.Reset(/*clear_bound_vars=*/true);
diff --git a/content/browser/attribution_reporting/rate_limit_table_unittest.cc b/content/browser/attribution_reporting/rate_limit_table_unittest.cc index b7b34c44..b961e0d0 100644 --- a/content/browser/attribution_reporting/rate_limit_table_unittest.cc +++ b/content/browser/attribution_reporting/rate_limit_table_unittest.cc
@@ -548,28 +548,28 @@ {}, }, { - "1 deletion: time range and filter match for source origin", - now + base::Milliseconds(1), + "no deletions: filter doesn't match for source origin", + base::Time::Min(), base::Time::Max(), base::BindRepeating([](const blink::StorageKey& storage_key) { return storage_key == blink::StorageKey::CreateFromStringForTesting( "https://a.s1.test"); }), - {3}, + {}, }, { - "2 deletions: filter matches for destination origin", + "no deletions: filter doesn't match for destination origin", base::Time::Min(), base::Time::Max(), base::BindRepeating([](const blink::StorageKey& storage_key) { return storage_key == blink::StorageKey::CreateFromStringForTesting( "https://b.d1.test"); }), - {2, 4}, + {}, }, { - "1 deletion: filter matches for reporting origin", - base::Time::Min(), + "1 deletion: time range and filter match for reporting origin", + now + base::Milliseconds(1), base::Time::Max(), base::BindRepeating([](const blink::StorageKey& storage_key) { return storage_key == blink::StorageKey::CreateFromStringForTesting(
diff --git a/content/browser/attribution_reporting/sql_queries.h b/content/browser/attribution_reporting/sql_queries.h index b4d72ea..60942e7 100644 --- a/content/browser/attribution_reporting/sql_queries.h +++ b/content/browser/attribution_reporting/sql_queries.h
@@ -39,8 +39,7 @@ ")LIMIT ?"; inline constexpr const char kScanCandidateData[] = - "SELECT I.source_origin,I.destination_origin,I.reporting_origin," - "I.source_id,C.report_id " + "SELECT I.reporting_origin,I.source_id,C.report_id " "FROM sources I LEFT JOIN event_level_reports C ON " "C.source_id=I.source_id WHERE" "(I.source_time BETWEEN ?1 AND ?2)OR" @@ -62,8 +61,7 @@ "SELECT dedup_key FROM dedup_keys WHERE source_id=? AND report_type=?"; inline constexpr const char kScanCandidateDataAggregatable[] = - "SELECT I.source_origin,I.destination_origin,I.reporting_origin," - "I.source_id,A.aggregation_id " + "SELECT I.reporting_origin,I.source_id,A.aggregation_id " "FROM sources I LEFT JOIN aggregatable_report_metadata A " "ON A.source_id=I.source_id WHERE" "(I.source_time BETWEEN ?1 AND ?2)OR" @@ -220,6 +218,44 @@ // clang-format on +inline constexpr const char kRateLimitAttributionAllowedSql[] = + "SELECT COUNT(*)FROM rate_limits " + "WHERE scope=1 " + "AND destination_site=? " + "AND source_site=? " + "AND reporting_origin=? " + "AND time>?"; + +inline constexpr const char kRateLimitSourceAllowedSql[] = + "SELECT destination_site FROM rate_limits " + "WHERE scope=0 " + "AND source_site=? " + "AND reporting_origin=? " + "AND expiry_time>?"; + +inline constexpr const char kRateLimitSelectReportingOriginsSql[] = + "SELECT reporting_origin FROM rate_limits " + "WHERE scope=? " + "AND source_site=? " + "AND destination_site=? " + "AND time>?"; + +inline constexpr const char kDeleteRateLimitRangeSql[] = + "DELETE FROM rate_limits " + "WHERE time BETWEEN ? AND ?"; + +inline constexpr const char kSelectRateLimitsForDeletionSql[] = + "SELECT id,reporting_origin " + "FROM rate_limits " + "WHERE time BETWEEN ? AND ?"; + +inline constexpr const char kDeleteExpiredRateLimitsSql[] = + "DELETE FROM rate_limits " + "WHERE time<=? AND(scope=1 OR expiry_time<=?)"; + +inline constexpr const char kDeleteRateLimitsBySourceIdSql[] = + "DELETE FROM rate_limits WHERE source_id=?"; + } // namespace content::attribution_queries #endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_SQL_QUERIES_H_
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 3e9cc8c0..d3b1570 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -162,8 +162,8 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableExperimentalWebPlatformFeatures); // TODO(sreejakshetty): Initialize ScopedFeatureLists from test constructor. - EnableFeatureAndSetParams(features::kBackForwardCache, - "TimeToLiveInBackForwardCacheInSeconds", "3600"); + EnableFeatureAndSetParams(features::kBackForwardCacheTimeToLiveControl, + "time_to_live_seconds", "3600"); // Entry to the cache can be slow during testing and cause flakiness. DisableFeature(features::kBackForwardCacheEntryTimeout); EnableFeatureAndSetParams(features::kBackForwardCache,
diff --git a/content/browser/back_forward_cache_features_browsertest.cc b/content/browser/back_forward_cache_features_browsertest.cc index f629d47..047a805 100644 --- a/content/browser/back_forward_cache_features_browsertest.cc +++ b/content/browser/back_forward_cache_features_browsertest.cc
@@ -4307,8 +4307,9 @@ {}, {}, {}, FROM_HERE); } +// https://crbug.com/1410441 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, - PresentationConnectionClosed) { + DISABLED_PresentationConnectionClosed) { ASSERT_TRUE(CreateHttpsServer()->Start()); GURL url_a(https_server()->GetURL( "a.test", "/back_forward_cache/presentation_controller.html"));
diff --git a/content/browser/back_forward_cache_internal_browsertest.cc b/content/browser/back_forward_cache_internal_browsertest.cc index bf2a07a..29d008a 100644 --- a/content/browser/back_forward_cache_internal_browsertest.cc +++ b/content/browser/back_forward_cache_internal_browsertest.cc
@@ -3721,24 +3721,10 @@ ExpectCached(rfhs[3], /*cached=*/true, /*backgrounded=*/false); } -class CustomTTLBackForwardCacheBrowserTest - : public BackForwardCacheBrowserTest { - protected: - void SetUpCommandLine(base::CommandLine* command_line) override { - EnableFeatureAndSetParams(kBackForwardCacheTimeToLiveControl, - "time_to_live_seconds", - base::NumberToString(kTimeToLiveSeconds)); - BackForwardCacheBrowserTest::SetUpCommandLine(command_line); - } - - const int kTimeToLiveSeconds = 4000; -}; - // Test that the BackForwardCacheTimeToLiveControl feature works and takes -// precedence over the main BackForwardCache's TimeToLiveInBackForwardCache -// parameter. -IN_PROC_BROWSER_TEST_F(CustomTTLBackForwardCacheBrowserTest, - TestTimeToLiveParameter) { +// precedence over the default value +// `kDefaultTimeToLiveInBackForwardCacheInSeconds`. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, TestTimeToLiveParameter) { // Inject mock time task runner to be used in the eviction timer, so we can, // check for the functionality we are interested before and after the time to // live. We don't replace SingleThreadTaskRunner::GetCurrentDefault to ensure @@ -3751,8 +3737,9 @@ base::TimeDelta time_to_live_in_back_forward_cache = BackForwardCacheImpl::GetTimeToLiveInBackForwardCache(); - // This should match the value set in EnableFeatureAndSetParams. - EXPECT_EQ(time_to_live_in_back_forward_cache, base::Seconds(4000)); + // This should match the value set via EnableFeatureAndSetParams by + // parent test class `BackForwardCacheBrowserTest`. + EXPECT_EQ(time_to_live_in_back_forward_cache, base::Seconds(3600)); base::TimeDelta delta = base::Milliseconds(1);
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index e74c2209..d4927994 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -190,6 +190,7 @@ #include <shellapi.h> #include <windows.h> +#include "base/threading/platform_thread_win.h" #include "net/base/winsock_init.h" #include "sandbox/policy/win/sandbox_win.h" #include "sandbox/win/src/sandbox.h" @@ -562,6 +563,12 @@ return pre_early_init_error_code; } +#if BUILDFLAG(IS_WIN) + // This assumes FeatureList is initialized, and must happen before + // SetCurrentThreadType() below. + base::InitializePlatformThreadFeatures(); +#endif + // SetCurrentThreadType relies on CurrentUIThread on some platforms. The // MessagePumpForUI needs to be bound to the main thread by this point. DCHECK(base::CurrentUIThread::IsSet());
diff --git a/content/browser/browser_thread_browsertest.cc b/content/browser/browser_thread_browsertest.cc index 5d01c54..c171c6a 100644 --- a/content/browser/browser_thread_browsertest.cc +++ b/content/browser/browser_thread_browsertest.cc
@@ -39,7 +39,7 @@ IN_PROC_BROWSER_TEST_F(ContentBrowserTest, ExpectedThreadPriorities) { base::ThreadPriorityForTest expected_priority = base::ThreadPriorityForTest::kNormal; -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) // In browser main loop the kCompositing thread type is set. // Only Windows, Android and ChromeOS will set kDisplay priority for // kCompositing thread type. We omit Windows here as it has a special @@ -50,13 +50,12 @@ #else expected_priority = base::ThreadPriorityForTest::kDisplay; #endif -#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) +#endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) EXPECT_EQ(base::PlatformThread::GetCurrentThreadPriorityForTest(), expected_priority); - // Browser IO thread is set to kCompositing except for Windows, so the - // `expected_priority` for browser IO is the same as browser main's. + // The `expected_priority` for browser IO is the same as browser main's. GetIOThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 0b0c6d67..d4c0be6 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -60,8 +60,6 @@ // child process client id. constexpr uint32_t kBrowserClientId = 0u; -static const char* kBrowser = "Browser"; - scoped_refptr<viz::ContextProviderCommandBuffer> CreateContextProvider( scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, @@ -441,7 +439,6 @@ compositor->context_factory()->GetGpuMemoryBufferManager(); params.pipes.compositor_frame_sink_associated_remote = std::move(sink_remote); params.pipes.client_receiver = std::move(client_receiver); - params.client_name = kBrowser; auto frame_sink = std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( std::move(context_provider),
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc index 20ec123..2b0db9d 100644 --- a/content/browser/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -171,8 +171,9 @@ // Enable BackForwardCache: if (IsBackForwardCacheEnabled()) { feature_list_for_back_forward_cache_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); } else {
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 51317c02..0f8f801 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -1683,6 +1683,10 @@ kFormAutocompleteAttributeEmptyError: return protocol::Audits::GenericIssueErrorTypeEnum:: FormAutocompleteAttributeEmptyError; + case blink::mojom::GenericIssueErrorType:: + kFormEmptyIdAndNameAttributesForInputError: + return protocol::Audits::GenericIssueErrorTypeEnum:: + FormEmptyIdAndNameAttributesForInputError; } }
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 62ad996..3491598 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -2717,8 +2717,9 @@ public: DevToolsProtocolBackForwardCacheTest() { feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/fenced_frame/fenced_frame_browsertest.cc b/content/browser/fenced_frame/fenced_frame_browsertest.cc index d5841cf2..4ec6fef7 100644 --- a/content/browser/fenced_frame/fenced_frame_browsertest.cc +++ b/content/browser/fenced_frame/fenced_frame_browsertest.cc
@@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> +#include <string> + #include "base/functional/callback.h" #include "base/memory/ref_counted.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" @@ -48,6 +52,7 @@ #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/network/public/cpp/cors/cors.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h" @@ -60,6 +65,8 @@ namespace { +namespace cors = network::cors::header_names; + constexpr char kAddIframeScript[] = R"({ (()=>{ return new Promise((resolve) => { @@ -71,6 +78,8 @@ })(); })"; +constexpr char kReportingURL[] = "/_report_event_server.html"; + GURL AddAndVerifyFencedFrameURL( FencedFrameURLMapping* fenced_frame_url_mapping, const GURL& https_url, @@ -4601,6 +4610,44 @@ } } + std::unique_ptr<net::test_server::BasicHttpResponse> + GetResponseWithAccessAllowHeaders( + const net::test_server::HttpRequest* request) { + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + + response->set_code(net::HTTP_OK); + response->AddCustomHeader(cors::kAccessControlAllowMethods, + request->method_string); + if (base::Contains(request->headers, "Origin")) { + response->AddCustomHeader(cors::kAccessControlAllowOrigin, "*"); + } + if (base::Contains(request->headers, cors::kAccessControlRequestHeaders)) { + response->AddCustomHeader( + cors::kAccessControlAllowHeaders, + request->headers.at(cors::kAccessControlRequestHeaders)); + } + + return response; + } + + // For cross-origin reporting destination, a preflight request is sent before + // the actual request. + void VerifyPreflightRequest(const net::test_server::HttpRequest* request) { + EXPECT_EQ(request->method, net::test_server::HttpMethod::METHOD_OPTIONS); + EXPECT_TRUE(base::Contains(request->headers, "Origin")); + EXPECT_TRUE( + base::Contains(request->headers.at(cors::kAccessControlRequestHeaders), + "attribution-reporting-eligible")); + } + + scoped_refptr<FencedFrameReporter> CreateFencedFrameReporter() { + return FencedFrameReporter::CreateForFledge( + web_contents() + ->GetPrimaryMainFrame() + ->GetStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess()); + } + // A helper function for specifying reportEvent tests. Each step consists of a // series of `Step`s specified above. void RunTest(std::vector<Step>& steps) { @@ -4613,17 +4660,27 @@ responses; std::vector<std::unique_ptr<net::test_server::ControllableHttpResponse>> redirects; - for (size_t i = 0; i < steps.size() + 1; ++i) { - responses.emplace_back( - std::make_unique<net::test_server::ControllableHttpResponse>( - https_server(), "/_report_event_server.html")); - } + + std::string reporting_origin = "c.test"; // We also register interceptors for redirections that we want to perform. // Each redirect must be from a unique path so that messages aren't // unintentionally intercepted and blocked. { std::set<std::string> paths; for (auto& step : steps) { + responses.emplace_back( + std::make_unique<net::test_server::ControllableHttpResponse>( + https_server(), kReportingURL)); + std::string final_destination_origin = + step.redirects.empty() ? step.destination.origin + : step.redirects.back().origin; + if (final_destination_origin != reporting_origin) { + // The reporting beacon is cross-origin. Two requests will be sent. + // First is the preflight request, the second is the actual request. + responses.emplace_back( + std::make_unique<net::test_server::ControllableHttpResponse>( + https_server(), kReportingURL)); + } if (step.is_target_nested_iframe) { ASSERT_FALSE(step.is_embedder_initiated); ASSERT_FALSE(step.is_opaque); @@ -4648,6 +4705,11 @@ } } } + // An additional response is used to check any spurious waiting reported + // events. + responses.emplace_back( + std::make_unique<net::test_server::ControllableHttpResponse>( + https_server(), kReportingURL)); ASSERT_TRUE(https_server()->Start()); // Set up the embedder and a fenced frame. @@ -4668,11 +4730,7 @@ // Create a FencedFrameReporter and pass it reporting metadata. scoped_refptr<FencedFrameReporter> fenced_frame_reporter = - FencedFrameReporter::CreateForFledge( - web_contents() - ->GetPrimaryMainFrame() - ->GetStoragePartition() - ->GetURLLoaderFactoryForBrowserProcess()); + CreateFencedFrameReporter(); GURL reporting_url( https_server()->GetURL("c.test", "/_report_event_server.html")); // Set valid reporting metadata for buyer. @@ -4790,13 +4848,40 @@ // If relevant, check that the event report succeeded. if (step.report_event_result == Step::Result::kSuccess) { + std::string final_destination_origin = + step.redirects.empty() ? step.destination.origin + : step.redirects.back().origin; + if (final_destination_origin != reporting_origin) { + auto& preflight_response = *responses[response_index]; + // Verify the preflight request contains the eligibility header under + // "Access-Control-Request-Headers". + preflight_response.WaitForRequest(); + VerifyPreflightRequest(preflight_response.http_request()); + + // Send response with extra headers. + std::unique_ptr<net::test_server::BasicHttpResponse> + access_allow_response = GetResponseWithAccessAllowHeaders( + preflight_response.http_request()); + access_allow_response->AddCustomHeader("Content-Type", + "text/plain;charset=UTF-8"); + preflight_response.Send(access_allow_response->ToResponseString()); + preflight_response.Done(); + ++response_index; + } auto& response = *responses[response_index]; response.WaitForRequest(); + // Verify the request has the correct content. EXPECT_EQ( response.http_request()->content, step.event.type + " " + base::NumberToString(navigation_index)); + // Verify the request contains the eligibility header. + EXPECT_EQ(response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_FALSE(base::Contains(response.http_request()->headers, + "Attribution-Reporting-Support")); response.Done(); - response_index++; + ++response_index; } else { ASSERT_TRUE(console_observer.Wait()); EXPECT_FALSE(console_observer.messages().empty()); @@ -4822,8 +4907,8 @@ // Fenced frame not in opaque-ads mode should fail reportEvent(). IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest, FencedFrameReportEventNonOpaqueAdsMode) { - net::test_server::ControllableHttpResponse response( - https_server(), "/_report_event_server.html"); + net::test_server::ControllableHttpResponse response(https_server(), + kReportingURL); ASSERT_TRUE(https_server()->Start()); // Set up the embedder and a default mode fenced frame. @@ -4860,7 +4945,7 @@ destination: ['buyer'], }); )"; - EXPECT_TRUE(ExecJs(fenced_frame_root_node, JsReplace(report_event_script))); + EXPECT_TRUE(ExecJs(fenced_frame_root_node, report_event_script)); // Check console warning. ASSERT_TRUE(console_observer.Wait()); @@ -5132,8 +5217,10 @@ // Remove this test once the FLEDGE origin trial stops supporting iframes. IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest, IframeReportingMetadata) { - net::test_server::ControllableHttpResponse response(https_server(), - "/title2.html"); + net::test_server::ControllableHttpResponse preflight_response(https_server(), + kReportingURL); + net::test_server::ControllableHttpResponse reporting_response(https_server(), + kReportingURL); ASSERT_TRUE(https_server()->Start()); GURL main_url = https_server()->GetURL("b.test", "/hello.html"); @@ -5151,12 +5238,8 @@ // Create a FencedFrameReporter and pass it reporting metadata. scoped_refptr<FencedFrameReporter> fenced_frame_reporter = - FencedFrameReporter::CreateForFledge( - web_contents() - ->GetPrimaryMainFrame() - ->GetStoragePartition() - ->GetURLLoaderFactoryForBrowserProcess()); - GURL reporting_url(https_server()->GetURL("c.test", "/title2.html")); + CreateFencedFrameReporter(); + GURL reporting_url(https_server()->GetURL("c.test", kReportingURL)); // Set valid reporting metadata for buyer. fenced_frame_reporter->OnUrlMappingReady( blink::FencedFrame::ReportingDestination::kBuyer, @@ -5197,8 +5280,524 @@ " destination: ['buyer']});", event_data))); + // Verify the preflight request contains the eligibility header under + // "Access-Control-Request-Headers". + preflight_response.WaitForRequest(); + VerifyPreflightRequest(preflight_response.http_request()); + + // Send response with extra headers. + std::unique_ptr<net::test_server::BasicHttpResponse> access_allow_response = + GetResponseWithAccessAllowHeaders(preflight_response.http_request()); + access_allow_response->AddCustomHeader("Content-Type", + "text/plain;charset=UTF-8"); + preflight_response.Send(access_allow_response->ToResponseString()); + preflight_response.Done(); + + reporting_response.WaitForRequest(); + // Verify the request has the correct content. + EXPECT_EQ(reporting_response.http_request()->content, event_data); + // Verify the request contains the eligibility header. + EXPECT_EQ(reporting_response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_FALSE(base::Contains(reporting_response.http_request()->headers, + "Attribution-Reporting-Support")); +} + +// The reportEvent beacon is a POST request. Upon receiving a 302 redirect +// response, the request is changed to a GET request. In this test case, the +// reporting url is same-origin. There is no preflight requests. +// 1. A POST request is sent to the reporting destination. +// 2. A response with 302 redirect is sent back to the requester. +// 3. A GET request is sent to the redirected destination. +IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest, + SameOriginReportEventPost302RedirectGet) { + net::test_server::ControllableHttpResponse response(https_server(), + kReportingURL); + net::test_server::ControllableHttpResponse redirect_response( + https_server(), "/redirect.html"); + ASSERT_TRUE(https_server()->Start()); + + // Set up the embedder and a default mode fenced frame. + GURL main_url = https_server()->GetURL("a.test", "/hello.html"); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + EXPECT_TRUE(ExecJs(root, + "var f = document.createElement('fencedframe');" + "f.mode = 'opaque-ads';" + "document.body.appendChild(f);")); + + EXPECT_EQ(1U, root->child_count()); + FrameTreeNode* fenced_frame_root_node = + GetFencedFrameRootNode(root->child_at(0)); + EXPECT_TRUE(fenced_frame_root_node->IsFencedFrameRoot()); + EXPECT_TRUE(fenced_frame_root_node->IsInFencedFrameTree()); + + GURL https_url( + https_server()->GetURL("a.test", "/fenced_frames/title1.html")); + + // Create a FencedFrameReporter and pass it reporting metadata. + scoped_refptr<FencedFrameReporter> fenced_frame_reporter = + CreateFencedFrameReporter(); + GURL reporting_url(https_server()->GetURL("a.test", kReportingURL)); + // Set valid reporting metadata for buyer. + fenced_frame_reporter->OnUrlMappingReady( + blink::FencedFrame::ReportingDestination::kBuyer, + {{"click", reporting_url}}); + + // Get the urn mapping object. + FencedFrameURLMapping& url_mapping = + root->current_frame_host()->GetPage().fenced_frame_urls_map(); + + // Add url and its reporting metadata to fenced frame url mapping. + auto urn_uuid = AddAndVerifyFencedFrameURL(&url_mapping, https_url, + fenced_frame_reporter); + + TestFencedFrameURLMappingResultObserver mapping_observer; + url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &mapping_observer); + TestFrameNavigationObserver observer( + fenced_frame_root_node->current_frame_host()); + + // Navigate the fenced frame. + EXPECT_TRUE(ExecJs(root, JsReplace("f.src = $1;", urn_uuid))); + + observer.WaitForCommit(); + EXPECT_TRUE(mapping_observer.mapping_complete_observed()); + EXPECT_EQ(fenced_frame_reporter, mapping_observer.fenced_frame_reporter()); + + // Perform the reportEvent call, with a unique body. + std::string event_data = "this is a click"; + std::string report_event_script = JsReplace(R"( + window.fence.reportEvent({ + eventType: 'click', + eventData: $1, + destination: ['buyer'], + }); + )", + event_data); + EXPECT_TRUE(ExecJs(fenced_frame_root_node, report_event_script)); + + { + // Verify the reporting request. + response.WaitForRequest(); + EXPECT_EQ(response.http_request()->content, event_data); + EXPECT_EQ(response.http_request()->method, + net::test_server::HttpMethod::METHOD_POST); + EXPECT_EQ( + response.http_request()->headers.at("Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_TRUE( + base::Contains(response.http_request()->headers, "Content-Length")); + EXPECT_TRUE( + base::Contains(response.http_request()->headers, "Content-Type")); + EXPECT_TRUE(base::Contains(response.http_request()->headers, "Origin")); + EXPECT_FALSE(base::Contains(response.http_request()->headers, + "Attribution-Reporting-Support")); + + // Send 302 redirect response. + GURL redirect_url = https_server()->GetURL("a.test", "/redirect.html"); + response.Send( + /*http_status=*/net::HTTP_FOUND, + /*content_type=*/"text/plain;charset=UTF-8", + /*content=*/{}, /*cookies=*/{}, /*extra_headers=*/ + {base::StrCat({"Location: ", redirect_url.spec()})}); + + response.Done(); + } + + { + // Verify the redirect request is a GET request. + redirect_response.WaitForRequest(); + EXPECT_EQ(redirect_response.http_request()->method, + net::test_server::HttpMethod::METHOD_GET); + // Check that POST-specific headers were stripped. + EXPECT_FALSE(base::Contains(redirect_response.http_request()->headers, + "Content-Length")); + EXPECT_FALSE(base::Contains(redirect_response.http_request()->headers, + "Content-Type")); + EXPECT_FALSE( + base::Contains(redirect_response.http_request()->headers, "Origin")); + // Check that the content body was stripped. + EXPECT_TRUE(redirect_response.http_request()->content.empty()); + // These extra request headers were not stripped. + EXPECT_EQ(redirect_response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_FALSE(base::Contains(response.http_request()->headers, + "Attribution-Reporting-Support")); + } +} + +// The reportEvent beacon is a POST request. Upon receiving a 302 redirect +// response, the request is changed to a GET request. In this test case, the +// reporting url is cross-origin. There are preflight requests. +// 1. A preflight request is sent to the reporting destination. +// 2. A response with 302 redirect is sent back to the requester. +// 3. A preflight request is sent to the redirected destination. +// 4. A response with 200 OK is sent back to the requester. +// 5. A GET request is sent to the redirected destination. +IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest, + CrossOriginReportEventPost302RedirectGet) { + net::test_server::ControllableHttpResponse preflight_response(https_server(), + kReportingURL); + net::test_server::ControllableHttpResponse reporting_response(https_server(), + kReportingURL); + net::test_server::ControllableHttpResponse redirect_preflight_response( + https_server(), "/redirect.html"); + net::test_server::ControllableHttpResponse redirect_response( + https_server(), "/redirect.html"); + ASSERT_TRUE(https_server()->Start()); + + // Set up the embedder and a default mode fenced frame. + GURL main_url = https_server()->GetURL("a.test", "/hello.html"); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + EXPECT_TRUE(ExecJs(root, + "var f = document.createElement('fencedframe');" + "f.mode = 'opaque-ads';" + "document.body.appendChild(f);")); + + EXPECT_EQ(1U, root->child_count()); + FrameTreeNode* fenced_frame_root_node = + GetFencedFrameRootNode(root->child_at(0)); + EXPECT_TRUE(fenced_frame_root_node->IsFencedFrameRoot()); + EXPECT_TRUE(fenced_frame_root_node->IsInFencedFrameTree()); + + GURL https_url( + https_server()->GetURL("a.test", "/fenced_frames/title1.html")); + + // Create a FencedFrameReporter and pass it reporting metadata. + scoped_refptr<FencedFrameReporter> fenced_frame_reporter = + CreateFencedFrameReporter(); + GURL reporting_url(https_server()->GetURL("c.test", kReportingURL)); + // Set valid reporting metadata for buyer. + fenced_frame_reporter->OnUrlMappingReady( + blink::FencedFrame::ReportingDestination::kBuyer, + {{"click", reporting_url}}); + + // Get the urn mapping object. + FencedFrameURLMapping& url_mapping = + root->current_frame_host()->GetPage().fenced_frame_urls_map(); + + // Add url and its reporting metadata to fenced frame url mapping. + auto urn_uuid = AddAndVerifyFencedFrameURL(&url_mapping, https_url, + fenced_frame_reporter); + + TestFencedFrameURLMappingResultObserver mapping_observer; + url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &mapping_observer); + TestFrameNavigationObserver observer( + fenced_frame_root_node->current_frame_host()); + + // Navigate the fenced frame. + EXPECT_TRUE(ExecJs(root, JsReplace("f.src = $1;", urn_uuid))); + + observer.WaitForCommit(); + EXPECT_TRUE(mapping_observer.mapping_complete_observed()); + EXPECT_EQ(fenced_frame_reporter, mapping_observer.fenced_frame_reporter()); + + // Perform the reportEvent call, with a unique body. + std::string event_data = "this is a click"; + std::string report_event_script = JsReplace(R"( + window.fence.reportEvent({ + eventType: 'click', + eventData: $1, + destination: ['buyer'], + }); + )", + event_data); + EXPECT_TRUE(ExecJs(fenced_frame_root_node, report_event_script)); + + { + // Verify the preflight request. + preflight_response.WaitForRequest(); + VerifyPreflightRequest(preflight_response.http_request()); + + // Send response with extra headers. + std::unique_ptr<net::test_server::BasicHttpResponse> access_allow_response = + GetResponseWithAccessAllowHeaders(preflight_response.http_request()); + access_allow_response->AddCustomHeader("Content-Type", + "text/plain;charset=UTF-8"); + preflight_response.Send(access_allow_response->ToResponseString()); + + preflight_response.Done(); + } + + { + reporting_response.WaitForRequest(); + EXPECT_EQ(reporting_response.http_request()->method, + net::test_server::HttpMethod::METHOD_POST); + EXPECT_EQ(reporting_response.http_request()->content, event_data); + EXPECT_TRUE(base::Contains(reporting_response.http_request()->headers, + "Content-Length")); + EXPECT_TRUE(base::Contains(reporting_response.http_request()->headers, + "Content-Type")); + EXPECT_TRUE( + base::Contains(reporting_response.http_request()->headers, "Origin")); + EXPECT_EQ(reporting_response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_FALSE(base::Contains(reporting_response.http_request()->headers, + "Attribution-Reporting-Support")); + + // Send 302 redirect response, with "Access-Control-Allow-Origin" header. + // This header is needed to get the redirect through. + GURL redirect_url = https_server()->GetURL("d.test", "/redirect.html"); + reporting_response.Send( + /*http_status=*/net::HTTP_FOUND, + /*content_type=*/"text/plain;charset=UTF-8", + /*content=*/{}, /*cookies=*/{}, /*extra_headers=*/ + {base::StrCat({cors::kAccessControlAllowOrigin, ": *"}), + base::StrCat({"Location: ", redirect_url.spec()})}); + reporting_response.Done(); + } + + { + // Verify the preflight request of the redirect. + redirect_preflight_response.WaitForRequest(); + VerifyPreflightRequest(preflight_response.http_request()); + EXPECT_EQ(redirect_preflight_response.http_request()->headers.at("Origin"), + "null"); + // Check that POST-specific headers were stripped. + EXPECT_FALSE(base::Contains( + redirect_preflight_response.http_request()->headers, "Content-Length")); + EXPECT_FALSE(base::Contains( + redirect_preflight_response.http_request()->headers, "Content-Type")); + // Check that the content body was stripped. + EXPECT_TRUE(redirect_preflight_response.http_request()->content.empty()); + // These extra request headers were not stripped. + EXPECT_EQ(redirect_preflight_response.http_request()->headers.at( + cors::kAccessControlRequestHeaders), + "attribution-reporting-eligible"); + + // Send response with extra headers. + std::unique_ptr<net::test_server::BasicHttpResponse> + redirect_access_allow_response = GetResponseWithAccessAllowHeaders( + redirect_preflight_response.http_request()); + redirect_access_allow_response->AddCustomHeader("Content-Type", + "text/plain;charset=UTF-8"); + redirect_preflight_response.Send( + redirect_access_allow_response->ToResponseString()); + + redirect_preflight_response.Done(); + } + + { + // Verify the redirect request is a GET request. + redirect_response.WaitForRequest(); + EXPECT_EQ(redirect_response.http_request()->method, + net::test_server::HttpMethod::METHOD_GET); + EXPECT_EQ(redirect_response.http_request()->headers.at("Origin"), "null"); + EXPECT_FALSE(base::Contains(redirect_response.http_request()->headers, + "Content-Length")); + EXPECT_EQ(redirect_response.http_request()->headers.at("Content-Type"), + "text/plain;charset=UTF-8"); + // Check that the content body was stripped. + EXPECT_TRUE(redirect_response.http_request()->content.empty()); + // These extra request headers were not stripped. + EXPECT_EQ(redirect_response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_FALSE(base::Contains(reporting_response.http_request()->headers, + "Attribution-Reporting-Support")); + } +} + +class FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest + : public FencedFrameReportEventBrowserTest { + public: + FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest() { + scoped_feature_list_.InitAndEnableFeature( + blink::features::kAttributionReportingCrossAppWeb); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F( + FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest, + ReportEventSameOriginSetsSupportHeader) { + net::test_server::ControllableHttpResponse response(https_server(), + kReportingURL); + ASSERT_TRUE(https_server()->Start()); + + // Set up the embedder and a default mode fenced frame. + GURL main_url = https_server()->GetURL("a.test", "/hello.html"); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + EXPECT_TRUE(ExecJs(root, + "var f = document.createElement('fencedframe');" + "f.mode = 'opaque-ads';" + "document.body.appendChild(f);")); + + EXPECT_EQ(1U, root->child_count()); + FrameTreeNode* fenced_frame_root_node = + GetFencedFrameRootNode(root->child_at(0)); + EXPECT_TRUE(fenced_frame_root_node->IsFencedFrameRoot()); + EXPECT_TRUE(fenced_frame_root_node->IsInFencedFrameTree()); + + GURL https_url( + https_server()->GetURL("a.test", "/fenced_frames/title1.html")); + + // Create a FencedFrameReporter and pass it reporting metadata. + scoped_refptr<FencedFrameReporter> fenced_frame_reporter = + CreateFencedFrameReporter(); + GURL reporting_url(https_server()->GetURL("a.test", kReportingURL)); + // Set valid reporting metadata for buyer. + fenced_frame_reporter->OnUrlMappingReady( + blink::FencedFrame::ReportingDestination::kBuyer, + {{"click", reporting_url}}); + + // Get the urn mapping object. + FencedFrameURLMapping& url_mapping = + root->current_frame_host()->GetPage().fenced_frame_urls_map(); + + // Add url and its reporting metadata to fenced frame url mapping. + auto urn_uuid = AddAndVerifyFencedFrameURL(&url_mapping, https_url, + fenced_frame_reporter); + + TestFencedFrameURLMappingResultObserver mapping_observer; + url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &mapping_observer); + TestFrameNavigationObserver observer( + fenced_frame_root_node->current_frame_host()); + + // Navigate the fenced frame. + EXPECT_TRUE(ExecJs(root, JsReplace("f.src = $1;", urn_uuid))); + + observer.WaitForCommit(); + EXPECT_TRUE(mapping_observer.mapping_complete_observed()); + EXPECT_EQ(fenced_frame_reporter, mapping_observer.fenced_frame_reporter()); + + // Perform the reportEvent call, with a unique body. + std::string event_data = "this is a click"; + std::string report_event_script = JsReplace(R"( + window.fence.reportEvent({ + eventType: 'click', + eventData: $1, + destination: ['buyer'], + }); + )", + event_data); + EXPECT_TRUE(ExecJs(fenced_frame_root_node, report_event_script)); + + // Verify the request contains the eligibility header. response.WaitForRequest(); EXPECT_EQ(response.http_request()->content, event_data); + EXPECT_EQ( + response.http_request()->headers.at("Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_EQ( + response.http_request()->headers.at("Attribution-Reporting-Support"), + "web"); +} + +IN_PROC_BROWSER_TEST_F( + FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest, + ReportEventCrossOriginSetsSupportHeader) { + // For cross-origin reportEvent beacon, a preflight request is sent before the + // actual request. `preflight_response` is used to handle the preflight + // request. `reporting_response` is used to handle the actual request. Note + // ControllableHttpResponse is used in the order they are created. + net::test_server::ControllableHttpResponse preflight_response(https_server(), + kReportingURL); + net::test_server::ControllableHttpResponse reporting_response(https_server(), + kReportingURL); + ASSERT_TRUE(https_server()->Start()); + + // Set up the embedder and a default mode fenced frame. + GURL main_url = https_server()->GetURL("a.test", "/hello.html"); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + EXPECT_TRUE(ExecJs(root, + "var f = document.createElement('fencedframe');" + "f.mode = 'opaque-ads';" + "document.body.appendChild(f);")); + + EXPECT_EQ(1U, root->child_count()); + FrameTreeNode* fenced_frame_root_node = + GetFencedFrameRootNode(root->child_at(0)); + EXPECT_TRUE(fenced_frame_root_node->IsFencedFrameRoot()); + EXPECT_TRUE(fenced_frame_root_node->IsInFencedFrameTree()); + + GURL https_url( + https_server()->GetURL("a.test", "/fenced_frames/title1.html")); + + // Create a FencedFrameReporter and pass it reporting metadata. + scoped_refptr<FencedFrameReporter> fenced_frame_reporter = + CreateFencedFrameReporter(); + GURL reporting_url(https_server()->GetURL("c.test", kReportingURL)); + // Set valid reporting metadata for buyer. + fenced_frame_reporter->OnUrlMappingReady( + blink::FencedFrame::ReportingDestination::kBuyer, + {{"click", reporting_url}}); + + // Get the urn mapping object. + FencedFrameURLMapping& url_mapping = + root->current_frame_host()->GetPage().fenced_frame_urls_map(); + + // Add url and its reporting metadata to fenced frame url mapping. + auto urn_uuid = AddAndVerifyFencedFrameURL(&url_mapping, https_url, + fenced_frame_reporter); + + TestFencedFrameURLMappingResultObserver mapping_observer; + url_mapping.ConvertFencedFrameURNToURL(urn_uuid, &mapping_observer); + TestFrameNavigationObserver observer( + fenced_frame_root_node->current_frame_host()); + + // Navigate the fenced frame. + EXPECT_TRUE(ExecJs(root, JsReplace("f.src = $1;", urn_uuid))); + + observer.WaitForCommit(); + EXPECT_TRUE(mapping_observer.mapping_complete_observed()); + EXPECT_EQ(fenced_frame_reporter, mapping_observer.fenced_frame_reporter()); + + // Perform the reportEvent call, with a unique body. + std::string event_data = "this is a click"; + std::string report_event_script = JsReplace(R"( + window.fence.reportEvent({ + eventType: 'click', + eventData: $1, + destination: ['buyer'], + }); + )", + event_data); + EXPECT_TRUE(ExecJs(fenced_frame_root_node, report_event_script)); + + { + // Verify the preflight request contains the eligibility header under + // "Access-Control-Request-Headers". + preflight_response.WaitForRequest(); + VerifyPreflightRequest(preflight_response.http_request()); + + // Send response with extra headers. + std::unique_ptr<net::test_server::BasicHttpResponse> access_allow_response = + GetResponseWithAccessAllowHeaders(preflight_response.http_request()); + access_allow_response->AddCustomHeader("Content-Type", + "text/plain;charset=UTF-8"); + preflight_response.Send(access_allow_response->ToResponseString()); + + preflight_response.Done(); + } + + // Verify the request contains the eligibility header. + { + reporting_response.WaitForRequest(); + EXPECT_EQ(reporting_response.http_request()->content, event_data); + EXPECT_EQ(reporting_response.http_request()->headers.at( + "Attribution-Reporting-Eligible"), + "event-source"); + EXPECT_EQ(reporting_response.http_request()->headers.at( + "Attribution-Reporting-Support"), + "web"); + } } // Parameterized on whether the feature is enabled or not.
diff --git a/content/browser/fenced_frame/fenced_frame_reporter.cc b/content/browser/fenced_frame/fenced_frame_reporter.cc index be6b98b8..8d25794 100644 --- a/content/browser/fenced_frame/fenced_frame_reporter.cc +++ b/content/browser/fenced_frame/fenced_frame_reporter.cc
@@ -12,12 +12,15 @@ #include "base/memory/ref_counted.h" #include "base/strings/strcat.h" #include "base/types/pass_key.h" +#include "components/attribution_reporting/os_registration.h" +#include "content/browser/attribution_reporting/attribution_manager.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/fetch_api.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/fenced_frame/redacted_fenced_frame_config.h" #include "url/gurl.h" #include "url/origin.h" @@ -231,6 +234,15 @@ request->trusted_params = network::ResourceRequest::TrustedParams(); request->trusted_params->isolation_info = net::IsolationInfo::CreateTransient(); + // TODO(xiaochenzh): The eligible header for automatic beacon should be + // `navigation-source`, update the code below when it is enabled. + request->headers.SetHeader("Attribution-Reporting-Eligible", "event-source"); + if (base::FeatureList::IsEnabled( + blink::features::kAttributionReportingCrossAppWeb)) { + request->headers.SetHeader("Attribution-Reporting-Support", + attribution_reporting::GetSupportHeader( + AttributionManager::GetOsSupport())); + } // Create and configure `SimpleURLLoader` instance. std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
diff --git a/content/browser/find_request_manager_browsertest.cc b/content/browser/find_request_manager_browsertest.cc index 7e365ccb..ef43d78 100644 --- a/content/browser/find_request_manager_browsertest.cc +++ b/content/browser/find_request_manager_browsertest.cc
@@ -1284,8 +1284,9 @@ public: FindRequestManagerTestWithBFCache() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/image_capture/image_capture_impl.cc b/content/browser/image_capture/image_capture_impl.cc index 6edd533..6771c4c 100644 --- a/content/browser/image_capture/image_capture_impl.cc +++ b/content/browser/image_capture/image_capture_impl.cc
@@ -42,10 +42,11 @@ session_id, std::move(callback)); } -void SetOptionsOnIOThread(const std::string& source_id, - MediaStreamManager* media_stream_manager, - media::mojom::PhotoSettingsPtr settings, - ImageCaptureImpl::SetOptionsCallback callback) { +void SetPhotoOptionsOnIOThread( + const std::string& source_id, + MediaStreamManager* media_stream_manager, + media::mojom::PhotoSettingsPtr settings, + ImageCaptureImpl::SetPhotoOptionsCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); const base::UnguessableToken session_id = @@ -106,12 +107,12 @@ std::move(scoped_callback))); } -void ImageCaptureImpl::SetOptions(const std::string& source_id, - media::mojom::PhotoSettingsPtr settings, - SetOptionsCallback callback) { +void ImageCaptureImpl::SetPhotoOptions(const std::string& source_id, + media::mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"), - "ImageCaptureImpl::SetOptions", + "ImageCaptureImpl::SetPhotoOptions", TRACE_EVENT_SCOPE_PROCESS); if ((settings->has_pan || settings->has_tilt || settings->has_zoom) && @@ -120,12 +121,12 @@ return; } - SetOptionsCallback scoped_callback = + SetPhotoOptionsCallback scoped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( media::BindToCurrentLoop(std::move(callback)), false); GetIOThreadTaskRunner({})->PostTask( FROM_HERE, - base::BindOnce(&SetOptionsOnIOThread, source_id, + base::BindOnce(&SetPhotoOptionsOnIOThread, source_id, BrowserMainLoop::GetInstance()->media_stream_manager(), std::move(settings), std::move(scoped_callback))); }
diff --git a/content/browser/image_capture/image_capture_impl.h b/content/browser/image_capture/image_capture_impl.h index f909cca2..be048c2c 100644 --- a/content/browser/image_capture/image_capture_impl.h +++ b/content/browser/image_capture/image_capture_impl.h
@@ -25,9 +25,9 @@ void GetPhotoState(const std::string& source_id, GetPhotoStateCallback callback) override; - void SetOptions(const std::string& source_id, - media::mojom::PhotoSettingsPtr settings, - SetOptionsCallback callback) override; + void SetPhotoOptions(const std::string& source_id, + media::mojom::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) override; void TakePhoto(const std::string& source_id, TakePhotoCallback callback) override;
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index de524741..3243689 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -1086,6 +1086,8 @@ blink::mojom::IDBTransactionDurability durability) { switch (durability) { case blink::mojom::IDBTransactionDurability::Default: + NOTREACHED(); + ABSL_FALLTHROUGH_INTENDED; case blink::mojom::IDBTransactionDurability::Strict: return true; case blink::mojom::IDBTransactionDurability::Relaxed: @@ -3039,6 +3041,8 @@ : nullptr), durability_(durability), mode_(mode) { + // `Default` should have already been converted to the bucket's setting. + DCHECK(durability_ != blink::mojom::IDBTransactionDurability::Default); DCHECK(!backing_store_ || backing_store_->idb_task_runner()->RunsTasksInCurrentSequence()); }
diff --git a/content/browser/interest_group/ad_auction_service_impl.cc b/content/browser/interest_group/ad_auction_service_impl.cc index ab254aa..d0b1fbe 100644 --- a/content/browser/interest_group/ad_auction_service_impl.cc +++ b/content/browser/interest_group/ad_auction_service_impl.cc
@@ -110,9 +110,13 @@ for (auction_worklet::mojom::PrivateAggregationRequestPtr& request : requests) { DCHECK(request); + // All for-event contributions have already been converted to histogram + // contributions by filling in post auction signals before reaching here. + DCHECK(request->contribution->is_histogram_contribution()); std::vector<mojom::AggregatableReportHistogramContributionPtr> contributions; - contributions.push_back(std::move(request->contribution)); + contributions.push_back( + std::move(request->contribution->get_histogram_contribution())); remote->SendHistogramReport(std::move(contributions), request->aggregation_mode, std::move(request->debug_mode_details)); @@ -139,7 +143,6 @@ // `client_security_state` and `trusted_url_loader_factory` are used for // event-level reports only. void SendSuccessfulAuctionReportsAndUpdateInterestGroups( - bool* has_sent_reports, PrivateAggregationManager* private_aggregation_manager, InterestGroupManagerImpl* interest_group_manager, const url::Origin& main_frame_origin, @@ -147,7 +150,7 @@ const blink::InterestGroupKey& winning_group_key, const std::string& winning_group_ad_metadata, std::map<url::Origin, - std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>>* + std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>> private_aggregation_requests, const std::vector<GURL>& report_urls, const std::vector<GURL>& debug_loss_report_urls, @@ -157,12 +160,8 @@ const network::mojom::ClientSecurityStatePtr& client_security_state, scoped_refptr<network::WrapperSharedURLLoaderFactory> trusted_url_loader_factory) { - DCHECK(has_sent_reports); DCHECK(interest_group_manager); DCHECK(client_security_state); - if (*has_sent_reports) - return; - *has_sent_reports = true; interest_group_manager->RecordInterestGroupBids(interest_groups_that_bid); interest_group_manager->RecordInterestGroupWin(winning_group_key, @@ -171,7 +170,7 @@ std::move(k_anon_keys_to_join)); SendPrivateAggregationRequests(private_aggregation_manager, main_frame_origin, - std::move(*private_aggregation_requests)); + std::move(private_aggregation_requests)); interest_group_manager->EnqueueReports( InterestGroupManagerImpl::ReportType::kSendReportTo, report_urls, frame_origin, *client_security_state, trusted_url_loader_factory); @@ -690,12 +689,38 @@ DCHECK(urn_uuid.is_valid()); DCHECK(!interest_groups_that_bid.empty()); + content::AdAuctionData ad_auction_data{winning_group_key->owner, + winning_group_key->name}; + FencedFrameURLMapping& fenced_frame_urls_map = + GetFrame()->GetPage().fenced_frame_urls_map(); + + // Set up reporting for any fenced frame that's navigated to the winning bid's + // URL. Use a URLLoaderFactory that will automatically reconnect on network + // process crashes, and can outlive the frame. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = + render_frame_host() + .GetStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess(); + scoped_refptr<FencedFrameReporter> fenced_frame_reporter = + FencedFrameReporter::CreateForFledge(url_loader_factory); + + blink::FencedFrame::RedactedFencedFrameConfig config = + fenced_frame_urls_map.AssignFencedFrameURLAndInterestGroupInfo( + urn_uuid, *render_url, std::move(ad_auction_data), + reporter->OnNavigateToWinningAdCallback(), ad_component_urls, + fenced_frame_reporter); + std::move(callback).Run(/*manually_aborted=*/false, std::move(config)); + + // Start the InterestGroupAuctionReporter. It will run reporting scripts, but + // nothing will be reported (nor the reporter deleted) until a fenced frame + // navigates to the winning ad, which will be signalled by invoking the + // callback returned by the InterestGroupAuctionReporter's + // OnNavitationToWinningAdCallback() method (invoked just above). reporters_.emplace_front(std::move(reporter)); reporters_.front()->Start(base::BindOnce( &AdAuctionServiceImpl::OnReporterComplete, base::Unretained(this), - reporters_.begin(), std::move(callback), std::move(urn_uuid), - std::move(*winning_group_key), std::move(*render_url), - std::move(ad_component_urls), std::move(winning_group_ad_metadata), + reporters_.begin(), std::move(urn_uuid), std::move(*winning_group_key), + std::move(winning_group_ad_metadata), std::move(fenced_frame_reporter), std::move(debug_loss_report_urls), std::move(debug_win_report_urls), std::move(interest_groups_that_bid), std::move(k_anon_keys_to_join))); if (auction_result_metrics) { @@ -706,12 +731,10 @@ void AdAuctionServiceImpl::OnReporterComplete( ReporterList::iterator reporter_it, - RunAdAuctionCallback callback, GURL urn_uuid, blink::InterestGroupKey winning_group_key, - GURL render_url, - std::vector<GURL> ad_component_urls, std::string winning_group_ad_metadata, + scoped_refptr<FencedFrameReporter> fenced_frame_reporter, std::vector<GURL> debug_loss_report_urls, std::vector<GURL> debug_win_report_urls, blink::InterestGroupSet interest_groups_that_bid, @@ -735,54 +758,22 @@ reporters_.erase(reporter_it); - FencedFrameURLMapping& fenced_frame_urls_map = - GetFrame()->GetPage().fenced_frame_urls_map(); - - // Need to send reports when the navigation code replaces a winning ad's URN - // with its URL, but should only do so once for the results from a given - // auction. FencedFrameURLMapping takes a RepeatingCallback, as it can map the - // same URN to a URL multiple times. To avoid multiple invocations, pass in a - // base::Owned bool, which is set to true by first invocation. - // - // The callback can also potentially be invoked after the AdAuctionServiceImpl - // is destroyed, in a number of cases, such as running an auction in an - // iframe, closing the iframe, and then navigating another frame to the URN. - // To handle this, the must not dereference `this`, so have to pass everything - // the callback needs directly. - content::AdAuctionData ad_auction_data{winning_group_key.owner, - winning_group_key.name}; - - // Set up reporting for the fenced frame. Use a URLLoaderFactory that will - // automatically reconnect on network process crashes, and can outlive the - // frame. - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = - render_frame_host() - .GetStoragePartition() - ->GetURLLoaderFactoryForBrowserProcess(); - scoped_refptr<FencedFrameReporter> fenced_frame_reporter = - FencedFrameReporter::CreateForFledge(url_loader_factory); - - blink::FencedFrame::RedactedFencedFrameConfig config = - fenced_frame_urls_map.AssignFencedFrameURLAndInterestGroupInfo( - urn_uuid, render_url, std::move(ad_auction_data), - base::BindRepeating( - &SendSuccessfulAuctionReportsAndUpdateInterestGroups, - /*has_sent_reports=*/base::Owned(std::make_unique<bool>(false)), - private_aggregation_manager_, &GetInterestGroupManager(), - main_frame_origin_, origin(), std::move(winning_group_key), - std::move(winning_group_ad_metadata), - base::Owned( - std::make_unique< - std::map<url::Origin, - std::vector<auction_worklet::mojom:: - PrivateAggregationRequestPtr>>>( - std::move(private_aggregation_requests))), - std::move(report_urls), std::move(debug_win_report_urls), - std::move(debug_loss_report_urls), - std::move(interest_groups_that_bid), - std::move(k_anon_keys_to_join), GetClientSecurityState(), - GetRefCountedTrustedURLLoaderFactory()), - ad_component_urls, fenced_frame_reporter); + // TODO(mmenke): Move all reporting logic to the InterestGroupAuctionReporter. + // Interest group update logic could remain here or go there as well, but + // should be performed as soon as the fenced frame on navigate callback is + // invoked, instead of only after reporting - it should also be performed if + // the current frame is deleted (e.g., if an iframe runs an auction, passes + // the URN to the parent frame, which then deletes the iframe and then + // navigates a fenced frame, interest groups should still be updated. We + // should run the InterestGroupAuctionReporter as well, but that's potentially + // another issue). + SendSuccessfulAuctionReportsAndUpdateInterestGroups( + private_aggregation_manager_, &GetInterestGroupManager(), + main_frame_origin_, origin(), winning_group_key, + winning_group_ad_metadata, std::move(private_aggregation_requests), + report_urls, debug_win_report_urls, debug_loss_report_urls, + interest_groups_that_bid, std::move(k_anon_keys_to_join), + GetClientSecurityState(), GetRefCountedTrustedURLLoaderFactory()); // Pass reporting map to the FencedFrameReporter. // TODO(mmenke): move this into InterestGroupReporter. @@ -793,8 +784,6 @@ fenced_frame_reporter->OnUrlMappingReady( destination, std::move(ad_beacon_map.metadata[destination])); } - - std::move(callback).Run(/*manually_aborted=*/false, std::move(config)); } void AdAuctionServiceImpl::MaybeLogPrivateAggregationFeature( @@ -804,6 +793,8 @@ private_aggregation_requests) { // TODO(crbug.com/1356654): Improve coverage of these use counters, i.e. // for API usage that does not result in a successful request. + // TODO(crbug.com/1410322): Use separate use counters for SendHistogram() and + // reportContributionForEvent(). if (!private_aggregation_requests.empty()) { GetContentClient()->browser()->LogWebFeatureForCurrentPage( &render_frame_host(),
diff --git a/content/browser/interest_group/ad_auction_service_impl.h b/content/browser/interest_group/ad_auction_service_impl.h index 17fe893..0fe07cfb 100644 --- a/content/browser/interest_group/ad_auction_service_impl.h +++ b/content/browser/interest_group/ad_auction_service_impl.h
@@ -12,6 +12,8 @@ #include "base/containers/unique_ptr_adapters.h" #include "base/memory/raw_ptr.h" +#include "base/memory/ref_counted.h" +#include "content/browser/fenced_frame/fenced_frame_reporter.h" #include "content/browser/fenced_frame/fenced_frame_url_mapping.h" #include "content/browser/interest_group/auction_runner.h" #include "content/browser/interest_group/auction_worklet_manager.h" @@ -137,17 +139,16 @@ std::vector<std::string> errors, std::unique_ptr<InterestGroupAuctionReporter> reporter); - void OnReporterComplete(ReporterList::iterator reporter_it, - RunAdAuctionCallback callback, - GURL urn_uuid, - blink::InterestGroupKey winning_group_key, - GURL render_url, - std::vector<GURL> ad_component_urls, - std::string winning_group_ad_metadata, - std::vector<GURL> debug_loss_report_urls, - std::vector<GURL> debug_win_report_urls, - blink::InterestGroupSet interest_groups_that_bid, - base::flat_set<std::string> k_anon_keys_to_join); + void OnReporterComplete( + ReporterList::iterator reporter_it, + GURL urn_uuid, + blink::InterestGroupKey winning_group_key, + std::string winning_group_ad_metadata, + scoped_refptr<FencedFrameReporter> fenced_frame_reporter, + std::vector<GURL> debug_loss_report_urls, + std::vector<GURL> debug_win_report_urls, + blink::InterestGroupSet interest_groups_that_bid, + base::flat_set<std::string> k_anon_keys_to_join); // Calls LogWebFeatureForCurrentPage() for the frame to inform it of FLEDGE // private aggregation API usage, if `private_aggregation_requests` is
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc index 0ef3326..fb00722 100644 --- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc +++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -210,35 +210,47 @@ report_map_[url_path] = response; } - // Registers a URL to use a "deferred" update response. For a deferred + // Registers a URL to use a "deferred" script response. For a deferred // response, the request handler returns true without a write, and writes are - // performed later in DoDeferredWrite() using a "stolen" Mojo pipe to the - // URLLoaderClient. + // performed later in DoDeferred[Script|Update]Write() using a "stolen" Mojo + // pipe to the URLLoaderClient. // // It is valid to have a "deferred" response that never completes before the // test exits. - void RegisterDeferredUpdateResponse(const std::string& url_path) { - base::AutoLock auto_lock(lock_); - CHECK( - deferred_update_responses_map_ - .emplace(url_path, mojo::Remote<network::mojom::URLLoaderClient>()) - .second); + void RegisterDeferredScriptResponse(const std::string& url_path) { + RegisterDeferredResponse(url_path, /*is_update=*/false); } - // Perform the deferred response for `url_path` -- the test fails if the - // client isn't waiting on `url_path` registered with - // RegisterDeferredUpdateResponse(). + // Just like RegisterDeferredResponse(), but for deferred update responses. + void RegisterDeferredUpdateResponse(const std::string& url_path) { + RegisterDeferredResponse(url_path, /*is_update=*/true); + } + + // Checks if there's a deferred response (of any type) for `url_path`. + bool HasPendingResponse(const std::string& url_path) const { + base::AutoLock auto_lock(lock_); + auto it = deferred_responses_map_.find(url_path); + CHECK(it != deferred_responses_map_.end()); + return it->second.url_loader_client.is_bound() && + it->second.url_loader_client.is_connected(); + } + + // Perform the deferred response for `url_path`, using response headers + // associated with scripts -- the test fails if the client isn't waiting on + // `url_path` registered with RegisterDeferredResponse(). + void DoDeferredScriptResponse(const std::string& url_path, + const std::string& response) { + DoDeferredResponse(url_path, response, kFledgeScriptHeaders, + /*expected_is_update=*/false); + } + + // Perform the deferred response for `url_path`, using response headers + // associated with updates -- the test fails if the client isn't waiting on + // `url_path` registered with RegisterDeferredResponse(). void DoDeferredUpdateResponse(const std::string& url_path, const std::string& response) { - base::AutoLock auto_lock(lock_); - auto it = deferred_update_responses_map_.find(url_path); - CHECK(it != deferred_update_responses_map_.end()); - mojo::Remote<network::mojom::URLLoaderClient>& url_loader_client = - it->second; - CHECK(url_loader_client.is_bound()); - URLLoaderInterceptor::WriteResponse(kFledgeUpdateHeaders, response, - url_loader_client.get()); - deferred_update_responses_map_.erase(it); + DoDeferredResponse(url_path, response, kFledgeScriptHeaders, + /*expected_is_update=*/true); } // Registers a URL that, when seen, will have its URLLoaderClient stored in @@ -325,6 +337,18 @@ bool RequestHandler(URLLoaderInterceptor::RequestParams* params) { base::AutoLock auto_lock(lock_); + // Check deferred responses map first. + const auto deferred_it = + deferred_responses_map_.find(params->url_request.url.path()); + if (deferred_it != deferred_responses_map_.end()) { + CHECK(!deferred_it->second.url_loader_client); + deferred_it->second.url_loader_client = std::move(params->client); + if (deferred_it->second.is_update) { + OnUpdateRequestReceived(params); + } + return true; + } + // Cross-origin iframe handling is covered by integration tests, for cases // that request .well-known URLs. if (params->url_request.url.path_piece() == @@ -369,11 +393,7 @@ // Not a non-update error, script request, or report request, so consider // this an update request. - update_count_++; - EXPECT_TRUE(params->url_request.trusted_params); - EXPECT_TRUE(params->url_request.trusted_params->isolation_info - .network_isolation_key() - .IsTransient()); + OnUpdateRequestReceived(params); const auto update_it = json_update_map_.find(params->url_request.url.path()); if (update_it != json_update_map_.end()) { @@ -382,14 +402,6 @@ return true; } - const auto deferred_update_it = - deferred_update_responses_map_.find(params->url_request.url.path()); - if (deferred_update_it != deferred_update_responses_map_.end()) { - CHECK(!deferred_update_it->second); - deferred_update_it->second = std::move(params->client); - return true; - } - if (params->url_request.url.path() == update_error_path_) { CHECK(update_error_ != net::OK); params->client->OnComplete( @@ -413,6 +425,41 @@ std::move(quit_report_wait_loop_callback_).Run(); } + void OnUpdateRequestReceived(URLLoaderInterceptor::RequestParams* params) + EXCLUSIVE_LOCKS_REQUIRED(lock_) { + update_count_++; + EXPECT_TRUE(params->url_request.trusted_params); + EXPECT_TRUE(params->url_request.trusted_params->isolation_info + .network_isolation_key() + .IsTransient()); + } + + void RegisterDeferredResponse(const std::string& url_path, bool is_update) { + base::AutoLock auto_lock(lock_); + CHECK(deferred_responses_map_ + .emplace(url_path, + DeferredResponseInfo{ + mojo::Remote<network::mojom::URLLoaderClient>(), + is_update}) + .second); + } + + void DoDeferredResponse(const std::string& url_path, + const std::string& response, + const std::string headers, + bool expected_is_update) { + base::AutoLock auto_lock(lock_); + auto it = deferred_responses_map_.find(url_path); + CHECK(it != deferred_responses_map_.end()); + EXPECT_EQ(expected_is_update, it->second.is_update); + mojo::Remote<network::mojom::URLLoaderClient>& url_loader_client = + it->second.url_loader_client; + CHECK(url_loader_client.is_bound()); + URLLoaderInterceptor::WriteResponse(headers, response, + url_loader_client.get()); + deferred_responses_map_.erase(it); + } + // Handles network requests for interest group updates and scripts. URLLoaderInterceptor network_interceptor_{ base::BindRepeating(&NetworkResponder::RequestHandler, @@ -435,9 +482,14 @@ // Only saves reporting requests that auctually received responses. std::vector<std::string> sent_reports_ GUARDED_BY(lock_); - // Stores the set of URL paths that will receive deferred updates. + struct DeferredResponseInfo { + mojo::Remote<network::mojom::URLLoaderClient> url_loader_client; + bool is_update = false; + }; + + // Stores the set of URL paths that will receive a deferred response. // - // First, a URL path is registered to receive an update, but the mapped value + // First, a URL path is registered to defer the response, but the mapped value // will not be bound. // // Next, once a request is made for that URL path, the @@ -449,8 +501,8 @@ // // It is valid to have a "deferred" response that never completes before the // test exits. - base::flat_map<std::string, mojo::Remote<network::mojom::URLLoaderClient>> - deferred_update_responses_map_ GUARDED_BY(lock_); + base::flat_map<std::string, DeferredResponseInfo> deferred_responses_map_ + GUARDED_BY(lock_); // Stores the last URL path that was registered with // RegisterStoreUrlLoaderClient(). @@ -4729,54 +4781,6 @@ EXPECT_EQ(base::Seconds(15), base::Time::Now() - start_time); } -// Check that reports are sent (And there's no UAF when invoking the URN -// callback) if the AdAuctionService is deleted before a URN is navigated to. -// -// This isn't a common case, but can happen if an auction runs in an iframe, -// which is then closed, and then the URN is loaded in a fenced frame. -// -// It can also potentially happen when navigating away from a page that run an -// auction is racing against loading a URN in a frame within the page. -// -// It can also happen if a compromised renderer closes the Mojo pipe to its -// AdAuctionService. -TEST_F(AdAuctionServiceImplTest, ReportsSentAfterServiceDestruction) { - network_responder_->RegisterScriptResponse(kBiddingUrlPath, - BasicBiddingReportScript()); - network_responder_->RegisterScriptResponse(kDecisionUrlPath, - BasicSellerReportScript()); - network_responder_->RegisterReportResponse("/report_bidder", /*response=*/""); - network_responder_->RegisterReportResponse("/report_seller", /*response=*/""); - - blink::InterestGroup interest_group = CreateInterestGroup(); - interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath); - interest_group.ads.emplace(); - blink::InterestGroup::Ad ad( - /*render_url=*/GURL("https://example.com/render"), - /*metadata=*/absl::nullopt); - interest_group.ads->emplace_back(std::move(ad)); - JoinInterestGroupAndFlush(interest_group); - EXPECT_EQ(1, GetJoinCount(kOriginA, kInterestGroupName)); - - blink::AuctionConfig auction_config; - auction_config.seller = kOriginA; - auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath); - auction_config.non_shared_params.interest_group_buyers = {kOriginA}; - absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config); - ASSERT_NE(auction_result, absl::nullopt); - - // Destroy the auction service Mojo pipe, and wait for the underlying service - // to be destroyed. - DestroyAdAuctionService(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(network_responder_->ReportCount(), 0u); - - // Invoking the callback should not crash and should result in two reports - // being sent. - InvokeCallbackForURN(*auction_result); - network_responder_->WaitForNumReports(2); -} - // Similar to SendReports() above, but with one report request failed instead of // timed out. Following report requests should still be send after previous ones // failed. @@ -4894,6 +4898,10 @@ absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for the reporting scripts to complete and reporting URLs to be + // requested. Need to do this for each auction to make sure reporting + // scripts complete and requests are made in a consistent order. + task_environment()->RunUntilIdle(); } // There should be one report sent already, since there's no delay for the @@ -4946,6 +4954,9 @@ absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for the reporting scripts to complete and all reporting URLs to be + // requested. + task_environment()->RunUntilIdle(); // Wait for the seller report to be sent. network_responder_->WaitForNumReports(1); @@ -4960,6 +4971,9 @@ auction_result = RunAdAuctionAndFlush(auction_config2); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for the reporting scripts to complete and all reporting URLs to be + // requested. + task_environment()->RunUntilIdle(); // Two more reports are enqueued. EXPECT_EQ(manager_->report_queue_length_for_testing(), 3u); @@ -4983,12 +4997,91 @@ auction_result = RunAdAuctionAndFlush(auction_config3); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for the reporting scripts to complete and all reporting URLs to be + // requested. + task_environment()->RunUntilIdle(); task_environment()->FastForwardBy(base::Seconds(20)); // Two more reports from the third auction are sent. EXPECT_EQ(network_responder_->ReportCount(), 3u); } +// Check that running reporting worklets doesn't block auction completion. To do +// this, the bidding script is set to be deferred. The auction is started, and +// the bid script is supplied. Then the auction completes. This should trigger +// reloading the bidding script to call reportWin(). The second time, a bidding +// script is not supplied. The fact that the auction completes despite the +// second stalled load verifies that running reporting scripts does not block +// completion of an auction. The AdAuctionServiceImpl is destroyed before +// the bidding URL is downloaded the second time, which provides some test +// coverage of that as well. +TEST_F(AdAuctionServiceImplTest, ReportingWorkletsDoNotBlockCompletion) { + network_responder_->RegisterDeferredScriptResponse(kBiddingUrlPath); + network_responder_->RegisterScriptResponse(kDecisionUrlPath, + BasicSellerReportScript()); + network_responder_->RegisterReportResponse("/report_bidder", /*response=*/""); + network_responder_->RegisterReportResponse("/report_seller", /*response=*/""); + + blink::InterestGroup interest_group = CreateInterestGroup(); + interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath); + interest_group.ads.emplace(); + blink::InterestGroup::Ad ad( + /*render_url=*/GURL("https://example.com/render"), + /*metadata=*/absl::nullopt); + interest_group.ads->emplace_back(std::move(ad)); + + JoinInterestGroupAndFlush(interest_group); + EXPECT_EQ(1, GetJoinCount(kOriginA, kInterestGroupName)); + + blink::AuctionConfig auction_config; + auction_config.seller = kOriginA; + auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath); + auction_config.non_shared_params.interest_group_buyers = {kOriginA}; + + AdAuctionServiceImpl::CreateMojoService( + main_rfh(), ad_auction_service_.BindNewPipeAndPassReceiver()); + + // Start the auction. + base::RunLoop run_loop; + absl::optional<blink::FencedFrame::RedactedFencedFrameConfig> maybe_config; + ad_auction_service_->RunAdAuction( + auction_config, mojo::NullReceiver(), + base::BindLambdaForTesting( + [&run_loop, &maybe_config]( + bool manually_aborted, + const absl::optional< + blink::FencedFrame::RedactedFencedFrameConfig>& config) { + EXPECT_FALSE(manually_aborted); + maybe_config = config; + run_loop.Quit(); + })); + + // Wait for the NetworkResponder to see the request for the bidding URL, and + // response with the bidding script. + task_environment()->RunUntilIdle(); + EXPECT_FALSE(run_loop.AnyQuitCalled()); + network_responder_->DoDeferredScriptResponse(kBiddingUrlPath, + BasicBiddingReportScript()); + // Register another deferred response for when the bidding URL is requested + // again to run the reporting script. + network_responder_->RegisterDeferredScriptResponse(kBiddingUrlPath); + + // Complete the auction. It should have a winning ad. + run_loop.Run(); + ASSERT_TRUE(maybe_config); + EXPECT_TRUE(maybe_config->urn_uuid().has_value()); + + // Running until idle should result in the NetworkResponder receiving a + // request for the bidding URL, to run the reporting script. + task_environment()->RunUntilIdle(); + EXPECT_TRUE(network_responder_->HasPendingResponse(kBiddingUrlPath)); + + // Destroy the auction service Mojo pipe, and wait for the underlying service + // to be destroyed, which should not cause a crash. + DestroyAdAuctionService(); + base::RunLoop().RunUntilIdle(); +} + // Run several auctions, some of which have a winner, and some of which do // not. Verify that the auction result UMA is recorded correctly. TEST_F(AdAuctionServiceImplTest, @@ -6005,6 +6098,9 @@ absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for the reporting scripts to complete and reporting URLs to be + // requested, to ensure requests are made in a consistent order. + task_environment()->RunUntilIdle(); } task_environment()->FastForwardBy(base::Seconds(3)); @@ -6362,6 +6458,9 @@ absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config); ASSERT_NE(auction_result, absl::nullopt); InvokeCallbackForURN(*auction_result); + // Wait for reporting to complete - aggregate API usage is only logged if + // aggregation reports are sent. + task_environment()->RunUntilIdle(); } // TODO(crbug.com/1356654): Update when use counter coverage is improved.
diff --git a/content/browser/interest_group/auction_runner.cc b/content/browser/interest_group/auction_runner.cc index 7bb01802..69ce3ca 100644 --- a/content/browser/interest_group/auction_runner.cc +++ b/content/browser/interest_group/auction_runner.cc
@@ -199,7 +199,8 @@ // all bids. std::vector<GURL> debug_win_report_urls; std::vector<GURL> debug_loss_report_urls; - auction_.TakeDebugReportUrls(debug_win_report_urls, debug_loss_report_urls); + auction_.TakeDebugReportUrlsAndFillInPrivateAggregationRequests( + debug_win_report_urls, debug_loss_report_urls); // Shouldn't have any win report URLs if nothing won the auction. DCHECK(debug_win_report_urls.empty()); @@ -296,7 +297,8 @@ std::vector<GURL> debug_win_report_urls; std::vector<GURL> debug_loss_report_urls; - auction_.TakeDebugReportUrls(debug_win_report_urls, debug_loss_report_urls); + auction_.TakeDebugReportUrlsAndFillInPrivateAggregationRequests( + debug_win_report_urls, debug_loss_report_urls); UpdateInterestGroupsPostAuction();
diff --git a/content/browser/interest_group/auction_runner.h b/content/browser/interest_group/auction_runner.h index d209446..3fd8395df 100644 --- a/content/browser/interest_group/auction_runner.h +++ b/content/browser/interest_group/auction_runner.h
@@ -73,6 +73,9 @@ // `debug_win_report_urls` URLs to use for reporting win result to bidders and // the seller. Empty if no report should be sent. // + // `private_aggregation_requests` Requests made to the Private Aggregation + // API. Keyed by reporting origin of the associated requests. + // // `interest_groups_that_bid` is a list of the interest groups that made bids // in the auction. Empty if the auction didn't run to completion. //
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc index 7a1a3a1..a48d517 100644 --- a/content/browser/interest_group/auction_runner_unittest.cc +++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -116,36 +116,48 @@ const auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedGenerateBidPrivateAggregationRequest = auction_worklet::mojom::PrivateAggregationRequest::New( - content::mojom::AggregatableReportHistogramContribution::New( - /*bucket=*/1, - /*value=*/2), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution:: + New( + /*bucket=*/1, + /*value=*/2)), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); const auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedReportWinPrivateAggregationRequest = auction_worklet::mojom::PrivateAggregationRequest::New( - content::mojom::AggregatableReportHistogramContribution::New( - /*bucket=*/3, - /*value=*/4), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution:: + New( + /*bucket=*/3, + /*value=*/4)), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); const auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedScoreAdPrivateAggregationRequest = auction_worklet::mojom::PrivateAggregationRequest::New( - content::mojom::AggregatableReportHistogramContribution::New( - /*bucket=*/5, - /*value=*/6), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution:: + New( + /*bucket=*/5, + /*value=*/6)), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); const auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedReportResultPrivateAggregationRequest = auction_worklet::mojom::PrivateAggregationRequest::New( - content::mojom::AggregatableReportHistogramContribution::New( - /*bucket=*/7, - /*value=*/8), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution:: + New( + /*bucket=*/7, + /*value=*/8)), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); @@ -965,6 +977,35 @@ top_level_signals.made_winning_bid ? "true" : "false", bid)); } +// Builds a PrivateAggregationRequest with histogram contribution using given +// `bucket` and `value`. +const auction_worklet::mojom::PrivateAggregationRequestPtr +BuildPrivateAggregationRequest(absl::uint128 bucket, int value) { + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + bucket, value)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + +auction_worklet::mojom::PrivateAggregationRequestPtr +BuildPrivateAggregationForEventRequest(absl::uint128 bucket, + int value, + std::string event_type) { + auction_worklet::mojom::AggregatableReportForEventContribution contribution( + auction_worklet::mojom::ForEventSignalBucket::NewIdBucket(bucket), + auction_worklet::mojom::ForEventSignalValue::NewIntValue(value), + event_type); + + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(contribution.Clone()), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + // Marks `ad` in `group` k-anonymous, double-checking that its url is `url`. void AuthorizeKAnon(const blink::InterestGroup::Ad& ad, const char* url, @@ -1727,6 +1768,7 @@ explicit AuctionRunnerTest( bool should_enable_private_aggregation = true, + bool should_enable_private_aggregation_fledge_extension = true, auction_worklet::mojom::KAnonymityBidMode kanon_mode = auction_worklet::mojom::KAnonymityBidMode::kNone) : RenderViewHostTestHarness( @@ -1735,21 +1777,32 @@ &AuctionRunnerTest::OnBadMessage, base::Unretained(this))); DebuggableAuctionWorkletTracker::GetInstance()->AddObserver(this); - std::vector<base::test::FeatureRef> enabled_features; + std::vector<base::test::FeatureRefAndParams> enabled_features; std::vector<base::test::FeatureRef> disabled_features; - if (should_enable_private_aggregation) - enabled_features.push_back(content::kPrivateAggregationApi); - else + if (should_enable_private_aggregation) { + if (should_enable_private_aggregation_fledge_extension) { + // Only makes sense to enable fledge extension when + // kPrivateAggregationApi is enabled. + enabled_features.push_back({content::kPrivateAggregationApi, + {{"fledge_extensions_enabled", "true"}}}); + } else { + enabled_features.push_back({content::kPrivateAggregationApi, {}}); + } + } else { disabled_features.push_back(content::kPrivateAggregationApi); + } switch (kanon_mode) { case auction_worklet::mojom::KAnonymityBidMode::kEnforce: - enabled_features.push_back(blink::features::kFledgeConsiderKAnonymity); - enabled_features.push_back(blink::features::kFledgeEnforceKAnonymity); + enabled_features.push_back( + {blink::features::kFledgeConsiderKAnonymity, {}}); + enabled_features.push_back( + {blink::features::kFledgeEnforceKAnonymity, {}}); break; case auction_worklet::mojom::KAnonymityBidMode::kSimulate: - enabled_features.push_back(blink::features::kFledgeConsiderKAnonymity); + enabled_features.push_back( + {blink::features::kFledgeConsiderKAnonymity, {}}); disabled_features.push_back(blink::features::kFledgeEnforceKAnonymity); break; case auction_worklet::mojom::KAnonymityBidMode::kNone: @@ -1758,7 +1811,8 @@ break; } - scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features, + disabled_features); } void TearDown() override { @@ -2045,6 +2099,8 @@ reporter_->Start(base::BindOnce(&AuctionRunnerTest::OnReportingComplete, base::Unretained(this))); + // Invoke callback immediately, so as not to block reporter completion. + reporter_->OnNavigateToWinningAdCallback().Run(); } void OnReportingComplete() { @@ -10267,6 +10323,722 @@ auction_runner_.reset(); } +// An auction with two successful bids. sendHistogramReport() and +// reportContributionForEvent() are both called in all of generateBid(), +// scoreAd(), reportWin() and reportResult(). +TEST_F(AuctionRunnerTest, + PrivateAggregationRequestForEventContributionReservedEvents) { + const char kBidScript[] = R"( + const bid = %d; + function generateBid( + interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, + browserSignals) { + privateAggregation.sendHistogramReport({bucket: 1n, value: 2}); + privateAggregation.reportContributionForEvent( + 'reserved.always', {bucket: 10n, value: 20}); + privateAggregation.reportContributionForEvent( + 'reserved.win', {bucket: 11n, value: 21}); + privateAggregation.reportContributionForEvent( + 'reserved.loss', {bucket: 12n, value: 22}); + return {bid: bid, render: interestGroup.ads[0].renderUrl}; + } + + function reportWin( + auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { + privateAggregation.sendHistogramReport({bucket: 3n, value: 4}); + privateAggregation.reportContributionForEvent( + 'reserved.always', {bucket: 30n, value: 40}); + privateAggregation.reportContributionForEvent( + 'reserved.win', {bucket: 31n, value: 41}); + privateAggregation.reportContributionForEvent( + 'reserved.loss', {bucket: 32n, value: 42}); + } + )"; + + const std::string kSellerScript = R"( + function scoreAd(adMetadata, bid, auctionConfig, browserSignals) { + privateAggregation.sendHistogramReport({bucket: 5n, value: 6}); + privateAggregation.reportContributionForEvent( + 'reserved.always', {bucket: 50n, value: 60}); + privateAggregation.reportContributionForEvent( + 'reserved.win', {bucket: 51n, value: 61}); + privateAggregation.reportContributionForEvent( + 'reserved.loss', {bucket: 52n, value: 62}); + return {desirability: 2 * bid, allowComponentAuction: true}; + } + + function reportResult(auctionConfig, browserSignals) { + privateAggregation.sendHistogramReport({bucket: 7n, value: 8}); + privateAggregation.reportContributionForEvent( + 'reserved.always', {bucket: 70n, value: 80}); + privateAggregation.reportContributionForEvent( + 'reserved.win', {bucket: 71n, value: 81}); + privateAggregation.reportContributionForEvent( + 'reserved.loss', {bucket: 72n, value: 82}); + } + )"; + + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder1Url, + base::StringPrintf(kBidScript, 1)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder2Url, + base::StringPrintf(kBidScript, 2)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, + kSellerScript); + + // Bidder 2 won the auction. + const Result& res = RunStandardAuction(); + EXPECT_FALSE(res.manually_aborted); + EXPECT_EQ(kBidder2Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + + EXPECT_THAT( + res.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + kExpectedGenerateBidPrivateAggregationRequest, + // generateBid() "reserved.always". + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + // generateBid() "reserved.loss". + BuildPrivateAggregationRequest(/*bucket=*/12, /*value=*/22))), + testing::Pair( + kBidder2, + ElementsAreRequests( + kExpectedGenerateBidPrivateAggregationRequest, + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + // generateBid() "reserved.win". + BuildPrivateAggregationRequest(/*bucket=*/11, /*value=*/21), + kExpectedReportWinPrivateAggregationRequest, + // reportWin() "reserved.always". + BuildPrivateAggregationRequest(/*bucket=*/30, /*value=*/40), + // reportWin() "reserved.win". + BuildPrivateAggregationRequest(/*bucket=*/31, /*value=*/41))), + testing::Pair( + kSeller, + ElementsAreRequests( + kExpectedScoreAdPrivateAggregationRequest, + // scoreAd() "reserved.always". + BuildPrivateAggregationRequest(/*bucket=*/50, /*value=*/60), + // scoreAd() "reserved.loss". + BuildPrivateAggregationRequest(/*bucket=*/52, /*value=*/62), + kExpectedScoreAdPrivateAggregationRequest, + BuildPrivateAggregationRequest(/*bucket=*/50, /*value=*/60), + // scoreAd() "reserved.win". + BuildPrivateAggregationRequest(/*bucket=*/51, /*value=*/61), + kExpectedReportResultPrivateAggregationRequest, + // reportResult() "reserved.always". + BuildPrivateAggregationRequest(/*bucket=*/70, /*value=*/80), + // reportResult() "reserved.win". + BuildPrivateAggregationRequest(/*bucket=*/71, + /*value=*/81))))); +} + +// Base values in contribution's bucket. +TEST_F(AuctionRunnerTest, + PrivateAggregationRequestForEventContributionBucketBaseValue) { + const char kBidScript[] = R"( + const bid = %d; + function generateBid( + interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, + browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 1.0, offset: 0n}, + value: 1 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'highestScoringOtherBid', scale: 1.0}, + value: 2 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason', offset: 0n}, + value: 3 + 100 * bid, + }); + return {bid: bid, render: interestGroup.ads[0].renderUrl}; + } + + function reportWin( + auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'winningBid'}, + value: 11 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'highestScoringOtherBid', scale: 1.0, offset: 0n}, + value: 12 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 13 + 100 * browserSignals.bid, + }); + } + )"; + + const std::string kSellerScript = R"( + function scoreAd(adMetadata, bid, auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid'}, + value: 21 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'highestScoringOtherBid'}, + value: 22 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 23 + 100 * bid, + }); + if (bid === 2) return {desirability: -1, rejectReason: 'invalid-bid'}; + return bid; + } + + function reportResult(auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'winningBid'}, + value: 31 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'highestScoringOtherBid'}, + value: 32 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 33 + 100 * browserSignals.bid, + }); + } + )"; + + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder1Url, + base::StringPrintf(kBidScript, 1)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder2Url, + base::StringPrintf(kBidScript, 2)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, + kSellerScript); + + // kBidder2 was rejected by seller, so kBidder1 won the auction. + const Result& res = RunStandardAuction(); + EXPECT_FALSE(res.manually_aborted); + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + + // Post auction signals of this auction: + // winningBid is 1, highestScoringOtherBid is 0, bidRejectReason for kBidder1 + // is kNotAvailable (0), and bidRejectReason for kBidder2 is kInvalidBid (1). + EXPECT_THAT( + res.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/101), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/102), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/103), + // reportWin(). No request for 'bidRejectReason' whose value + // is 113, because it's not a supported base value in + // reportWin(). + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/111), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/112))), + testing::Pair( + kBidder2, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/201), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/202), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/203))), + testing::Pair( + kSeller, + ElementsAreRequests( + // scoreAd() for kBidder1. + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/121), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/122), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/123), + // scoreAd() for kBidder2. + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/221), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/222), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/223), + // reportResult() for kBidder1. No request for + // 'bidRejectReason' whose value is 133, because it's not a + // supported base value in reportResult(). + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/131), + BuildPrivateAggregationRequest(/*bucket=*/0, + /*value=*/132))))); +} + +// Similar to `PrivateAggregationRequestForEventContributionBucketBaseValue()` +// above, but no bid is rejected. +TEST_F(AuctionRunnerTest, + PrivateAggregationRequestForEventContributionTwoBidsNotRejected) { + const char kBidScript[] = R"( + const bid = %d; + function generateBid( + interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, + browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 1.0, offset: 0n}, + value: 1 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'highestScoringOtherBid', scale: 1.0}, + value: 2 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason', offset: 0n}, + value: 3 + 100 * bid, + }); + return {bid: bid, render: interestGroup.ads[0].renderUrl}; + } + + function reportWin( + auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'winningBid'}, + value: 11 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'highestScoringOtherBid', scale: 1.0, offset: 0n}, + value: 12 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 13 + 100 * browserSignals.bid, + }); + } + )"; + + const std::string kSellerScript = R"( + function scoreAd(adMetadata, bid, auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid'}, + value: 21 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'highestScoringOtherBid'}, + value: 22 + 100 * bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 23 + 100 * bid, + }); + return bid; + } + + function reportResult(auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'winningBid'}, + value: 31 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: {baseValue: 'highestScoringOtherBid'}, + value: 32 + 100 * browserSignals.bid, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'bidRejectReason'}, + value: 33 + 100 * browserSignals.bid, + }); + } + )"; + + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder1Url, + base::StringPrintf(kBidScript, 1)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder2Url, + base::StringPrintf(kBidScript, 2)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, + kSellerScript); + + // kBidder2 won the auction. + const Result& res = RunStandardAuction(); + EXPECT_FALSE(res.manually_aborted); + EXPECT_EQ(kBidder2Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad2.com/"), res.ad_url); + + // Post auction signals of this auction: + // winningBid is 2, highestScoringOtherBid is 1, bidRejectReason for both + // bidders are kNotAvailable (0). + EXPECT_THAT( + res.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/2, /*value=*/101), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/102), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/103))), + testing::Pair( + kBidder2, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest( + /*bucket=*/2, /*value=*/201), + BuildPrivateAggregationRequest( + /*bucket=*/1, /*value=*/202), + BuildPrivateAggregationRequest( + /*bucket=*/0, /*value=*/203), + // reportWin(). No request for 'bidRejectReason' whose value + // is 213, because it's not a supported base value in + // reportWin(). + BuildPrivateAggregationRequest(/*bucket=*/2, /*value=*/211), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/212))), + testing::Pair( + kSeller, + ElementsAreRequests( + // scoreAd() for kBidder1. + BuildPrivateAggregationRequest(/*bucket=*/2, /*value=*/121), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/122), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/123), + // scoreAd() for kBidder2. + BuildPrivateAggregationRequest(/*bucket=*/2, /*value=*/221), + BuildPrivateAggregationRequest(/*bucket=*/1, /*value=*/222), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/223), + // reportResult() for kBidder2. No request for + // 'bidRejectReason' whose value is 233, because it's not a + // supported base value in reportResult(). + BuildPrivateAggregationRequest(/*bucket=*/2, /*value=*/231), + BuildPrivateAggregationRequest(/*bucket=*/1, + /*value=*/232))))); +} + +// Similar to PrivateAggregationRequestForEventContributionBucketBaseValue, +// but with contribution's value field as object. +TEST_F(AuctionRunnerTest, + PrivateAggregationRequestForEventContributionValueBaseValue) { + const char kBidScript[] = R"( + const bid = %d; + function generateBid( + interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, + browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(1 + 100 * bid), + value: {baseValue: 'winningBid', scale: 1.0, offset: 0}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(2 + 100 * bid), + value: {baseValue: 'highestScoringOtherBid', scale: 1.0}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(3 + 100 * bid), + value: {baseValue: 'bidRejectReason', offset: 0}, + }); + return {bid: bid, render: interestGroup.ads[0].renderUrl}; + } + + function reportWin( + auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: BigInt(11 + 100 * browserSignals.bid), + value: {baseValue: 'winningBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: BigInt(12 + 100 * browserSignals.bid), + value: {baseValue: 'highestScoringOtherBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(13 + 100 * browserSignals.bid), + value: {baseValue: 'bidRejectReason'}, + }); + } + )"; + + const std::string kSellerScript = R"( + function scoreAd(adMetadata, bid, auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(21 + 100 * bid), + value: {baseValue: 'winningBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(22 + 100 * bid), + value: {baseValue: 'highestScoringOtherBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(23 + 100 * bid), + value: {baseValue: 'bidRejectReason'}, + }); + if (bid === 2) return {desirability: -1, rejectReason: 'invalid-bid'}; + return bid; + } + + function reportResult(auctionConfig, browserSignals) { + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: BigInt(31 + 100 * browserSignals.bid), + value: {baseValue: 'winningBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.win', { + bucket: BigInt(32 + 100 * browserSignals.bid), + value: {baseValue: 'highestScoringOtherBid'}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: BigInt(33 + 100 * browserSignals.bid), + value: {baseValue: 'bidRejectReason'}, + }); + } + )"; + + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder1Url, + base::StringPrintf(kBidScript, 1)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder2Url, + base::StringPrintf(kBidScript, 2)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, + kSellerScript); + + // kBidder2 was rejected by seller, so kBidder1 won the auction. + const Result& res = RunStandardAuction(); + EXPECT_FALSE(res.manually_aborted); + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + + // Post auction signals of this auction: + // winningBid is 1, highestScoringOtherBid is 0, bidRejectReason for kBidder1 + // is kNotAvailable (0), and bidRejectReason for kBidder2 is kInvalidBid (1). + EXPECT_THAT( + res.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/101, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/102, /*value=*/0), + BuildPrivateAggregationRequest(/*bucket=*/103, /*value=*/0), + // reportWin(). + BuildPrivateAggregationRequest(/*bucket=*/111, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/112, /*value=*/0))), + testing::Pair( + kBidder2, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/201, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/202, /*value=*/0), + BuildPrivateAggregationRequest(/*bucket=*/203, /*value=*/1))), + testing::Pair( + kSeller, + ElementsAreRequests( + // scoreAd() for kBidder1. + BuildPrivateAggregationRequest(/*bucket=*/121, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/122, /*value=*/0), + BuildPrivateAggregationRequest(/*bucket=*/123, /*value=*/0), + // scoreAd() for kBidder2. + BuildPrivateAggregationRequest(/*bucket=*/221, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/222, /*value=*/0), + BuildPrivateAggregationRequest(/*bucket=*/223, /*value=*/1), + // reportResult() for kBidder1. + BuildPrivateAggregationRequest(/*bucket=*/131, /*value=*/1), + BuildPrivateAggregationRequest(/*bucket=*/132, + /*value=*/0))))); +} + +TEST_F(AuctionRunnerTest, + PrivateAggregationRequestForEventContributionScaleAndOffset) { + const char kBidScript[] = R"( + const bid = %d; + function reportContributionForEvent() { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 2.1, offset: 10n}, + value: {baseValue: 'winningBid', scale: 2.1, offset: 20}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 0, offset: 10n}, + value: {baseValue: 'winningBid', scale: 0, offset: 20}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: -1, offset: 10n}, + value: {baseValue: 'winningBid', scale: -1, offset: 20}, + }); + // Bucket overflows due to being negative, so will be clamped to 0. + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: -200, offset: 10n}, + value: 1, + }); + } + + function generateBid( + interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals, + browserSignals) { + reportContributionForEvent(); + return {bid: bid, render: interestGroup.ads[0].renderUrl}; + } + + function reportWin( + auctionSignals, perBuyerSignals, sellerSignals, browserSignals) { + reportContributionForEvent(); + send(); + } + )"; + + const std::string kSellerScript = R"( + function reportContributionForEvent() { + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 2.1, offset: 10n}, + value: {baseValue: 'winningBid', scale: 2.1, offset: 20}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: 0, offset: 10n}, + value: {baseValue: 'winningBid', scale: 0, offset: 20}, + }); + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: -1, offset: 10n}, + value: {baseValue: 'winningBid', scale: -1, offset: 20}, + }); + // Bucket overflows due to being negative, so will be clamped to 0. + privateAggregation.reportContributionForEvent('reserved.always', { + bucket: {baseValue: 'winningBid', scale: -200, offset: 10n}, + value: 1, + }); + } + + function scoreAd(adMetadata, bid, auctionConfig, browserSignals) { + reportContributionForEvent(); + return bid; + } + + function reportResult(auctionConfig, browserSignals) { + reportContributionForEvent(); + } + )"; + + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kBidder1Url, + base::StringPrintf(kBidScript, 1)); + auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl, + kSellerScript); + + // Only one bidder, to keep things simple. + const Result& res = RunStandardAuction(); + EXPECT_FALSE(res.manually_aborted); + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), res.ad_url); + + // winningBid is 1. + EXPECT_THAT( + res.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + // generateBid(). + BuildPrivateAggregationRequest(/*bucket=*/12, /*value=*/22), + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + BuildPrivateAggregationRequest(/*bucket=*/9, /*value=*/19), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/1), + // reportWin(). + BuildPrivateAggregationRequest(/*bucket=*/12, /*value=*/22), + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + BuildPrivateAggregationRequest(/*bucket=*/9, /*value=*/19), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/1))), + + testing::Pair( + kSeller, + ElementsAreRequests( + // scoreAd(). + BuildPrivateAggregationRequest(/*bucket=*/12, /*value=*/22), + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + BuildPrivateAggregationRequest(/*bucket=*/9, /*value=*/19), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/1), + // reportResult(). + BuildPrivateAggregationRequest(/*bucket=*/12, /*value=*/22), + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + BuildPrivateAggregationRequest(/*bucket=*/9, /*value=*/19), + BuildPrivateAggregationRequest(/*bucket=*/0, /*value=*/1))))); +} + +TEST_F(AuctionRunnerTest, + PrivateAggregationReportGenerateBidInvalidReservedEventType) { + StartStandardAuctionWithMockService(); + + auto seller_worklet = mock_auction_process_manager_->TakeSellerWorklet(); + ASSERT_TRUE(seller_worklet); + auto bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + ASSERT_TRUE(bidder1_worklet); + auto bidder2_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder2Url); + ASSERT_TRUE(bidder2_worklet); + + // Only Bidder1 bids, to keep things simple. + PrivateAggregationRequests bidder_1_pa_requests; + bidder_1_pa_requests.push_back( + BuildPrivateAggregationForEventRequest( + /*bucket=*/10, /*value=*/20, /*event_type=*/"reserved.always") + .Clone()); + bidder_1_pa_requests.push_back( + BuildPrivateAggregationForEventRequest( + /*bucket=*/11, /*value=*/21, /*event_type=*/"reserved.not-supported") + .Clone()); + + // Bidder1 returns a bid with a private aggregation request whose reserved + // event type is not a supported one. This could only happen when the bidder + // worklet is compromised. + bidder1_worklet->InvokeGenerateBidCallback( + /*bid=*/5, GURL("https://ad1.com"), /*mojo_kanon_bid=*/nullptr, + /*ad_component_urls=*/absl::nullopt, + /*duration=*/base::TimeDelta(), + /*bidding_signals_data_version=*/absl::nullopt, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, + /*pa_requests=*/ + std::move(bidder_1_pa_requests)); + bidder2_worklet->InvokeGenerateBidCallback(/*bid=*/absl::nullopt); + + auto score_ad_params = seller_worklet->WaitForScoreAd(); + EXPECT_EQ(kBidder1, score_ad_params.interest_group_owner); + EXPECT_EQ(5, score_ad_params.bid); + PrivateAggregationRequests score_ad_1_pa_requests; + score_ad_1_pa_requests.push_back( + kExpectedScoreAdPrivateAggregationRequest.Clone()); + mojo::Remote<auction_worklet::mojom::ScoreAdClient>( + std::move(score_ad_params.score_ad_client)) + ->OnScoreAdComplete( + /*score=*/10, + /*reject_reason=*/ + auction_worklet::mojom::RejectReason::kNotAvailable, + auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr(), + /*scoring_signals_data_version=*/0, + /*has_scoring_signals_data_version=*/false, + /*debug_loss_report_url=*/absl::nullopt, + /*debug_win_report_url=*/absl::nullopt, + std::move(score_ad_1_pa_requests), + /*errors=*/{}); + + PrivateAggregationRequests report_win_pa_requests; + report_win_pa_requests.push_back( + kExpectedReportWinPrivateAggregationRequest.Clone()); + PrivateAggregationRequests report_result_pa_requests; + report_result_pa_requests.push_back( + kExpectedReportResultPrivateAggregationRequest.Clone()); + + seller_worklet->WaitForReportResult(); + seller_worklet->InvokeReportResultCallback( + /*report_url=*/absl::nullopt, + /*ad_beacon_map=*/{}, std::move(report_result_pa_requests)); + mock_auction_process_manager_->WaitForWinningBidderReload(); + bidder1_worklet = + mock_auction_process_manager_->TakeBidderWorklet(kBidder1Url); + bidder1_worklet->WaitForReportWin(); + bidder1_worklet->InvokeReportWinCallback( + /*report_url=*/absl::nullopt, + /*ad_beacon_map=*/{}, /*pa_requests=*/std::move(report_win_pa_requests)); + auction_run_loop_->Run(); + + EXPECT_EQ(kBidder1Key, result_.winning_group_id); + EXPECT_EQ(GURL("https://ad1.com/"), result_.ad_url); + EXPECT_THAT(result_.interest_groups_that_bid, + testing::UnorderedElementsAre(kBidder1Key)); + EXPECT_EQ(R"({"render_url":"https://ad1.com/","metadata":{"ads": true}})", + result_.winning_group_ad_metadata); + + EXPECT_THAT( + result_.private_aggregation_requests, + testing::UnorderedElementsAre( + testing::Pair( + kBidder1, + ElementsAreRequests( + BuildPrivateAggregationRequest(/*bucket=*/10, /*value=*/20), + kExpectedReportWinPrivateAggregationRequest)), + testing::Pair(kSeller, + ElementsAreRequests( + kExpectedScoreAdPrivateAggregationRequest, + kExpectedReportResultPrivateAggregationRequest)))); +} + // Enable and test forDebuggingOnly.reportAdAuctionLoss() and // forDebuggingOnly.reportAdAuctionWin() APIs. class AuctionRunnerBiddingAndScoringDebugReportingAPIEnabledTest @@ -12028,8 +12800,10 @@ auction_worklet::mojom::KAnonymityBidMode> { public: AuctionRunnerKAnonTest() - : AuctionRunnerTest(/*should_enable_private_aggregation=*/true, - kanon_mode()) {} + : AuctionRunnerTest( + /*should_enable_private_aggregation=*/true, + /*should_enable_private_aggregation_fledge_extension=*/true, + kanon_mode()) {} auction_worklet::mojom::KAnonymityBidMode kanon_mode() { return GetParam(); } };
diff --git a/content/browser/interest_group/auction_worklet_manager.cc b/content/browser/interest_group/auction_worklet_manager.cc index 6dfac43..5da46af8 100644 --- a/content/browser/interest_group/auction_worklet_manager.cc +++ b/content/browser/interest_group/auction_worklet_manager.cc
@@ -269,10 +269,14 @@ } AuctionWorkletManager::WorkletHandle::~WorkletHandle() { - // The proxy that owns the SubresourceUrlAuthorizations only gets created if a - // process is assigned -- if that never happens, then there aren't isn't any - // SubresourceUrlAuthorizations, so don't report WorkletHandle destruction. - if (worklet_owner_->subresource_url_authorizations()) { + // We register with subresource_url_authorizations() only if + // AuthorizeSubresourceUrls() was called, so deregister if that's the case. + // + // This also must imply that the object should exist --- the proxy that owns + // the SubresourceUrlAuthorizations gets created when a process is assigned, + // and that's a precondition for calling AuthorizeSubresourceUrls(). + if (authorized_subresources_) { + DCHECK(worklet_owner_->subresource_url_authorizations()); worklet_owner_->subresource_url_authorizations() ->OnWorkletHandleDestruction(this); } @@ -295,6 +299,7 @@ const SubresourceUrlAuthorizations& AuctionWorkletManager::WorkletHandle:: GetSubresourceUrlAuthorizationsForTesting() { + DCHECK(authorized_subresources_); DCHECK(worklet_owner_->subresource_url_authorizations()); return *worklet_owner_->subresource_url_authorizations(); } @@ -302,33 +307,23 @@ AuctionWorkletManager::WorkletHandle::WorkletHandle( scoped_refptr<WorkletOwner> worklet_owner, base::OnceClosure worklet_available_callback, - FatalErrorCallback fatal_error_callback, - const SubresourceUrlBuilder& subresource_url_builder) + FatalErrorCallback fatal_error_callback) : worklet_owner_(std::move(worklet_owner)), worklet_available_callback_(std::move(worklet_available_callback)), - fatal_error_callback_(std::move(fatal_error_callback)), - subresource_url_builder_(&subresource_url_builder) { + fatal_error_callback_(std::move(fatal_error_callback)) { DCHECK(worklet_available_callback_); DCHECK(fatal_error_callback_); // Delete `worklet_available_callback_` if worklet is already available, since - // it won't be needed. Also, since the worklet is created, it's now possible - // to authorize subresource URLs -- this should happen now, before the live - // WorkletHandle is returned. + // it won't be needed. if (worklet_owner_->worklet_created()) { worklet_available_callback_.Reset(); - AuthorizeSubresourceUrls(); } worklet_owner_->RegisterHandle(this); } void AuctionWorkletManager::WorkletHandle::OnWorkletAvailable() { - // The proxy owned by WorkletOwner has been created, so it's now possible to - // authorize subresource URLs. This should be done before calling - // `worklet_available_callback_`, as the callback will make the worklet - // request these URLs. - AuthorizeSubresourceUrls(); DCHECK(worklet_available_callback_); std::move(worklet_available_callback_).Run(); } @@ -340,28 +335,35 @@ std::move(fatal_error_callback_).Run(type, errors); } -void AuctionWorkletManager::WorkletHandle::AuthorizeSubresourceUrls() { +void AuctionWorkletManager::WorkletHandle::AuthorizeSubresourceUrls( + const SubresourceUrlBuilder& subresource_url_builder) { + if (authorized_subresources_) { + return; + } + + authorized_subresources_ = true; + DCHECK(worklet_owner_->subresource_url_authorizations()); std::vector<SubresourceUrlBuilder::BundleSubresourceInfo> authorized_subresource_urls; - if (subresource_url_builder_->auction_signals()) { + if (subresource_url_builder.auction_signals()) { authorized_subresource_urls.push_back( - *subresource_url_builder_->auction_signals()); + *subresource_url_builder.auction_signals()); } switch (worklet_owner_->worklet_info().type) { case WorkletType::kBidder: { const url::Origin bidder_origin = url::Origin::Create(worklet_owner_->worklet_info().script_url); - auto it = - subresource_url_builder_->per_buyer_signals().find(bidder_origin); - if (it != subresource_url_builder_->per_buyer_signals().end()) + auto it = subresource_url_builder.per_buyer_signals().find(bidder_origin); + if (it != subresource_url_builder.per_buyer_signals().end()) { authorized_subresource_urls.push_back(it->second); + } break; } case WorkletType::kSeller: { - if (subresource_url_builder_->seller_signals()) { + if (subresource_url_builder.seller_signals()) { authorized_subresource_urls.push_back( - *subresource_url_builder_->seller_signals()); + *subresource_url_builder.seller_signals()); } break; } @@ -398,7 +400,6 @@ const GURL& bidding_logic_url, const absl::optional<GURL>& wasm_url, const absl::optional<GURL>& trusted_bidding_signals_url, - const SubresourceUrlBuilder& subresource_url_builder, absl::optional<uint16_t> experiment_group_id, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, @@ -412,15 +413,13 @@ ? experiment_group_id : absl::nullopt); return RequestWorkletInternal( - std::move(worklet_info), subresource_url_builder, - std::move(worklet_available_callback), std::move(fatal_error_callback), - out_worklet_handle); + std::move(worklet_info), std::move(worklet_available_callback), + std::move(fatal_error_callback), out_worklet_handle); } bool AuctionWorkletManager::RequestSellerWorklet( const GURL& decision_logic_url, const absl::optional<GURL>& trusted_scoring_signals_url, - const SubresourceUrlBuilder& subresource_url_builder, absl::optional<uint16_t> experiment_group_id, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, @@ -433,9 +432,8 @@ /*signals_url=*/trusted_scoring_signals_url, experiment_group_id); return RequestWorkletInternal( - std::move(worklet_info), subresource_url_builder, - std::move(worklet_available_callback), std::move(fatal_error_callback), - out_worklet_handle); + std::move(worklet_info), std::move(worklet_available_callback), + std::move(fatal_error_callback), out_worklet_handle); } AuctionWorkletManager::WorkletInfo::WorkletInfo( @@ -456,7 +454,6 @@ bool AuctionWorkletManager::RequestWorkletInternal( WorkletInfo worklet_info, - const SubresourceUrlBuilder& subresource_url_builder, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, std::unique_ptr<WorkletHandle>& out_worklet_handle) { @@ -472,7 +469,7 @@ } out_worklet_handle.reset(new WorkletHandle( std::move(worklet), std::move(worklet_available_callback), - std::move(fatal_error_callback), subresource_url_builder)); + std::move(fatal_error_callback))); return out_worklet_handle->worklet_created(); }
diff --git a/content/browser/interest_group/auction_worklet_manager.h b/content/browser/interest_group/auction_worklet_manager.h index 5879d32..671deb4 100644 --- a/content/browser/interest_group/auction_worklet_manager.h +++ b/content/browser/interest_group/auction_worklet_manager.h
@@ -120,6 +120,16 @@ WorkletHandle& operator=(const WorkletHandle&) = delete; ~WorkletHandle() override; + // Authorizes subresource bundle subresource URLs that the worklet may + // request as long as this WorkletHandle instance is live (refcounting + // allows multiple WorkletHandle instances to authorize the same URLs). + // + // This must be called manually before the worklet is asked to do anything + // involving fetching those subresources, but after the worklet is + // available. Calls after the first one will be ignored. + void AuthorizeSubresourceUrls( + const SubresourceUrlBuilder& subresource_url_builder); + // Retrieves the corresponding Worklet Mojo interface for the requested // worklet. Only the method corresponding to the worklet type `this` was // created with my be invoked. Once the worklet is created, will never @@ -144,11 +154,9 @@ friend class WorkletOwner; // These are only created by AuctionWorkletManager. - explicit WorkletHandle( - scoped_refptr<WorkletOwner> worklet_owner, - base::OnceClosure worklet_available_callback, - FatalErrorCallback fatal_error_callback, - const SubresourceUrlBuilder& subresource_url_builder); + explicit WorkletHandle(scoped_refptr<WorkletOwner> worklet_owner, + base::OnceClosure worklet_available_callback, + FatalErrorCallback fatal_error_callback); // Both these methods are invoked by WorkletOwner, and call the // corresponding callback. @@ -156,14 +164,6 @@ void OnFatalError(FatalErrorType type, const std::vector<std::string>& errors); - // Authorizes subresource bundle subresource URLs that the worklet may - // request as long as this WorkletHandle instance is live (refcounting - // allows multiple WorkletHandle instances to authorize the same URLs). - // - // Called by OnWorkletAvailable(); requires that the WorkletOwner internal - // proxy instance has been created. - void AuthorizeSubresourceUrls(); - // Returns true if `worklet_owner_` has created a worklet yet. bool worklet_created() const; @@ -174,9 +174,7 @@ FatalErrorCallback fatal_error_callback_; - // Never null, owned by InterestGroupAuction / InterestGroupAuctionReporter. - const raw_ptr<const SubresourceUrlBuilder, DanglingUntriaged> - subresource_url_builder_; + bool authorized_subresources_ = false; }; // `delegate` and `auction_process_manager` must outlive the created @@ -211,7 +209,6 @@ const GURL& bidding_logic_url, const absl::optional<GURL>& wasm_url, const absl::optional<GURL>& trusted_bidding_signals_url, - const SubresourceUrlBuilder& subresource_url_builder, absl::optional<uint16_t> experiment_group_id, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, @@ -219,7 +216,6 @@ [[nodiscard]] bool RequestSellerWorklet( const GURL& decision_logic_url, const absl::optional<GURL>& trusted_scoring_signals_url, - const SubresourceUrlBuilder& subresource_url_builder, absl::optional<uint16_t> experiment_group_id, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, @@ -250,7 +246,6 @@ bool RequestWorkletInternal( WorkletInfo worklet_info, - const SubresourceUrlBuilder& subresource_url_builder, base::OnceClosure worklet_available_callback, FatalErrorCallback fatal_error_callback, std::unique_ptr<WorkletHandle>& out_worklet_handle);
diff --git a/content/browser/interest_group/auction_worklet_manager_unittest.cc b/content/browser/interest_group/auction_worklet_manager_unittest.cc index ee555aa..14dea56 100644 --- a/content/browser/interest_group/auction_worklet_manager_unittest.cc +++ b/content/browser/interest_group/auction_worklet_manager_unittest.cc
@@ -671,11 +671,11 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, - kPopulatedSubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); EXPECT_TRUE(handle->GetBidderWorklet()); + handle->AuthorizeSubresourceUrls(kPopulatedSubresourceBuilder); std::unique_ptr<MockBidderWorklet> bidder_worklet = auction_process_manager_.WaitForBidderWorklet(); @@ -715,11 +715,12 @@ TEST_F(AuctionWorkletManagerTest, SingleSellerWorklet) { std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kPopulatedSubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); EXPECT_TRUE(handle->GetSellerWorklet()); + handle->AuthorizeSubresourceUrls(kPopulatedSubresourceBuilder); std::unique_ptr<MockSellerWorklet> seller_worklet = auction_process_manager_.WaitForSellerWorklet(); @@ -759,11 +760,12 @@ SingleBidderWorkletEmptyDirectFromSellerSignals) { std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); EXPECT_TRUE(handle->GetBidderWorklet()); + handle->AuthorizeSubresourceUrls(kEmptySubresourceBuilder); std::unique_ptr<MockBidderWorklet> bidder_worklet = auction_process_manager_.WaitForBidderWorklet(); @@ -776,11 +778,12 @@ SingleSellerWorkletEmptyDirectFromSellerSignals) { std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); EXPECT_TRUE(handle->GetSellerWorklet()); + handle->AuthorizeSubresourceUrls(kEmptySubresourceBuilder); std::unique_ptr<MockSellerWorklet> seller_worklet = auction_process_manager_.WaitForSellerWorklet(); @@ -809,7 +812,7 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( decision_logic_url, /*wasm_url=*/absl::nullopt, - /*trusted_bidding_signals_url=*/absl::nullopt, kEmptySubresourceBuilder, + /*trusted_bidding_signals_url=*/absl::nullopt, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); @@ -841,7 +844,7 @@ base::RunLoop worklet_available_loop; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_FALSE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, worklet_available_loop.QuitClosure(), NeverInvokedFatalErrorCallback(), handle)); @@ -892,7 +895,6 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( decision_logic_url, /*trusted_scoring_signals_url=*/absl::nullopt, - kEmptySubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); @@ -923,7 +925,7 @@ base::RunLoop worklet_available_loop; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_FALSE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, worklet_available_loop.QuitClosure(), NeverInvokedFatalErrorCallback(), handle)); @@ -958,7 +960,7 @@ // Load a bidder worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle1)); @@ -978,7 +980,7 @@ // reused. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle2)); @@ -998,7 +1000,7 @@ // reused again. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle3)); @@ -1020,7 +1022,7 @@ // be created. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle4; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle4)); @@ -1041,7 +1043,7 @@ // Load a seller worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle1)); @@ -1060,7 +1062,7 @@ // reused. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle2)); @@ -1080,7 +1082,7 @@ // reused again. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle3)); @@ -1102,7 +1104,7 @@ // be created. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle4; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle4)); @@ -1123,7 +1125,7 @@ // Load a bidder worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle1)); @@ -1144,7 +1146,6 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDifferentDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, - kEmptySubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle2)); @@ -1164,7 +1165,7 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDecisionLogicUrl, kWasmUrl, - /*trusted_bidding_signals_url=*/absl::nullopt, kEmptySubresourceBuilder, + /*trusted_bidding_signals_url=*/absl::nullopt, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle3)); @@ -1185,7 +1186,6 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle4; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDecisionLogicUrl, /*wasm_url=*/absl::nullopt, kTrustedSignalsUrl, - kEmptySubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle4)); @@ -1210,9 +1210,9 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, - kExperiment1, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle1)); + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kExperiment1, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle1)); EXPECT_TRUE(handle1->GetBidderWorklet()); std::unique_ptr<MockBidderWorklet> bidder_worklet1 = auction_process_manager_.WaitForBidderWorklet(); @@ -1221,9 +1221,9 @@ // worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, - kExperiment2, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle2)); + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kExperiment2, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle2)); EXPECT_TRUE(handle2->GetBidderWorklet()); std::unique_ptr<MockBidderWorklet> bidder_worklet2 = auction_process_manager_.WaitForBidderWorklet(); @@ -1232,9 +1232,9 @@ // Now try with different trusted signals URL (using WASM url instead). std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kWasmUrl, kEmptySubresourceBuilder, - kExperiment1, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle3)); + kDecisionLogicUrl, kWasmUrl, kWasmUrl, kExperiment1, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle3)); EXPECT_TRUE(handle3->GetBidderWorklet()); std::unique_ptr<MockBidderWorklet> bidder_worklet3 = auction_process_manager_.WaitForBidderWorklet(); @@ -1246,9 +1246,9 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle4; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDecisionLogicUrl, kWasmUrl, - /*trusted_bidding_signals_url=*/absl::nullopt, kEmptySubresourceBuilder, - kExperiment1, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle4)); + /*trusted_bidding_signals_url=*/absl::nullopt, kExperiment1, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle4)); EXPECT_TRUE(handle4->GetBidderWorklet()); std::unique_ptr<MockBidderWorklet> bidder_worklet4 = auction_process_manager_.WaitForBidderWorklet(); @@ -1259,7 +1259,7 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle5; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( kDecisionLogicUrl, kWasmUrl, - /*trusted_bidding_signals_url=*/absl::nullopt, kEmptySubresourceBuilder, + /*trusted_bidding_signals_url=*/absl::nullopt, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle5)); @@ -1272,7 +1272,7 @@ // Load a seller worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle1)); @@ -1291,7 +1291,7 @@ GURL("https://origin.test/different_script"); std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDifferentDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDifferentDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle2)); @@ -1310,7 +1310,6 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( kDecisionLogicUrl, /*trusted_scoring_signals_url=*/absl::nullopt, - kEmptySubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle3)); @@ -1333,9 +1332,9 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle1; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, - kExperiment1, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle1)); + kDecisionLogicUrl, kTrustedSignalsUrl, kExperiment1, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle1)); EXPECT_TRUE(handle1->GetSellerWorklet()); std::unique_ptr<MockSellerWorklet> seller_worklet1 = auction_process_manager_.WaitForSellerWorklet(); @@ -1344,9 +1343,9 @@ // worklet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, - kExperiment2, NeverInvokedWorkletAvailableCallback(), - NeverInvokedFatalErrorCallback(), handle2)); + kDecisionLogicUrl, kTrustedSignalsUrl, kExperiment2, + NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), + handle2)); EXPECT_TRUE(handle2->GetSellerWorklet()); std::unique_ptr<MockSellerWorklet> seller_worklet2 = auction_process_manager_.WaitForSellerWorklet(); @@ -1355,7 +1354,7 @@ // Now try with different trusted signals URL (using WASM url instead). std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle3; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kWasmUrl, kEmptySubresourceBuilder, kExperiment1, + kDecisionLogicUrl, kWasmUrl, kExperiment1, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle3)); EXPECT_TRUE(handle3->GetSellerWorklet()); @@ -1370,9 +1369,8 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle4; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( kDecisionLogicUrl, /*trusted_scoring_signals_url=*/absl::nullopt, - kEmptySubresourceBuilder, kExperiment1, - NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), - handle4)); + kExperiment1, NeverInvokedWorkletAvailableCallback(), + NeverInvokedFatalErrorCallback(), handle4)); EXPECT_TRUE(handle4->GetSellerWorklet()); std::unique_ptr<MockSellerWorklet> seller_worklet4 = auction_process_manager_.WaitForSellerWorklet(); @@ -1383,7 +1381,6 @@ std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle5; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( kDecisionLogicUrl, /*trusted_scoring_signals_url=*/absl::nullopt, - kEmptySubresourceBuilder, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle5)); @@ -1403,7 +1400,7 @@ FatalLoadErrorHelper load_error_helper; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle)); @@ -1430,7 +1427,7 @@ // yet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle2)); @@ -1447,7 +1444,7 @@ FatalLoadErrorHelper load_error_helper; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle)); @@ -1474,7 +1471,7 @@ // yet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle2)); @@ -1489,7 +1486,7 @@ FatalLoadErrorHelper load_error_helper; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle)); @@ -1518,7 +1515,7 @@ // yet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle2)); @@ -1533,7 +1530,7 @@ FatalLoadErrorHelper load_error_helper; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle)); @@ -1562,7 +1559,7 @@ // yet. std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle2; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), load_error_helper.Callback(), handle2)); @@ -1580,7 +1577,7 @@ base::RunLoop run_loop; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), base::BindLambdaForTesting( @@ -1610,7 +1607,7 @@ base::RunLoop run_loop; std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), base::BindLambdaForTesting( @@ -1637,7 +1634,7 @@ TEST_F(AuctionWorkletManagerTest, BidderWorkletUrlRequestProtection) { std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestBidderWorklet( - kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kWasmUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle)); @@ -1699,7 +1696,7 @@ TEST_F(AuctionWorkletManagerTest, SellerWorkletUrlRequestProtection) { std::unique_ptr<AuctionWorkletManager::WorkletHandle> handle; ASSERT_TRUE(auction_worklet_manager_.RequestSellerWorklet( - kDecisionLogicUrl, kTrustedSignalsUrl, kEmptySubresourceBuilder, + kDecisionLogicUrl, kTrustedSignalsUrl, /*experiment_group_id=*/absl::nullopt, NeverInvokedWorkletAvailableCallback(), NeverInvokedFatalErrorCallback(), handle));
diff --git a/content/browser/interest_group/interest_group_auction.cc b/content/browser/interest_group/interest_group_auction.cc index c85e17f..f769db4 100644 --- a/content/browser/interest_group/interest_group_auction.cc +++ b/content/browser/interest_group/interest_group_auction.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <cmath> #include <iterator> +#include <map> #include <memory> #include <string> #include <utility> @@ -37,6 +38,7 @@ #include "content/browser/interest_group/interest_group_auction_reporter.h" #include "content/browser/interest_group/interest_group_k_anonymity_manager.h" #include "content/browser/interest_group/interest_group_manager_impl.h" +#include "content/browser/interest_group/interest_group_pa_report_util.h" #include "content/browser/interest_group/interest_group_priority_util.h" #include "content/browser/interest_group/storage_interest_group.h" #include "content/public/browser/content_browser_client.h" @@ -448,8 +450,8 @@ // `debug_loss_report_urls`, if there are any, filling in report URL template // parameters as needed. // - // `winner` is the BidState associated with the winning bid, if there is one. - // If it's not a BidState managed by `this`, it has no effect. + // `winner` points to the BidState associated with the winning bid, if there + // is one. If it's not a BidState managed by `this`, it has no effect. // // `signals` are the PostAuctionSignals from the auction `this` was a part of. // @@ -461,7 +463,7 @@ const absl::optional<PostAuctionSignals>& top_level_signals, std::vector<GURL>& debug_win_report_urls, std::vector<GURL>& debug_loss_report_urls) { - for (auto& bid_state : bid_states_) { + for (std::unique_ptr<BidState>& bid_state : bid_states_) { if (bid_state.get() == winner) { if (winner->bidder_debug_win_report_url.has_value()) { debug_win_report_urls.emplace_back(FillPostAuctionSignals( @@ -507,6 +509,38 @@ } } + // Returns private aggregation requests, if there are any. Calculate + // bucket/value using `signals` as needed. + // + // `winner` points to the BidState associated with the winning bid, if there + // is one. If it's not a BidState managed by `this`, it has no effect. + // + // `signals` are the PostAuctionSignals from the auction `this` was a part of. + std::map<url::Origin, PrivateAggregationRequests> + TakePrivateAggregationRequests(const BidState* winner, + const PostAuctionSignals& signals) { + std::map<url::Origin, PrivateAggregationRequests> + private_aggregation_requests; + for (std::unique_ptr<BidState>& state : bid_states_) { + bool is_winner = state.get() == winner; + for (auto& [origin, requests] : state->private_aggregation_requests) { + for (auction_worklet::mojom::PrivateAggregationRequestPtr& request : + requests) { + auction_worklet::mojom::PrivateAggregationRequestPtr + converted_request = FillInPrivateAggregationRequest( + std::move(request), signals.winning_bid, + signals.highest_scoring_other_bid, state->reject_reason, + is_winner); + if (converted_request) { + private_aggregation_requests[origin].emplace_back( + std::move(converted_request)); + } + } + } + } + return private_aggregation_requests; + } + void NotifyConfigPromisesResolved() { for (const auto& bid_state : bid_states_) { FinishGenerateBidIfReady(bid_state.get()); @@ -644,6 +678,8 @@ auction_worklet::mojom::KAnonymityBidMode kanon_mode = auction_->kanon_mode(); bid_state->kanon_render_urls = ComputeKAnon(*bid_state->bidder, kanon_mode); + bid_state->worklet_handle->AuthorizeSubresourceUrls( + *auction_->subresource_url_builder_); bid_state->worklet_handle->GetBidderWorklet()->BeginGenerateBid( auction_worklet::mojom::BidderWorkletNonSharedParams::New( interest_group.name, @@ -903,8 +939,8 @@ request_ptr) { return request_ptr.is_null(); })); if (!pa_requests.empty()) { PrivateAggregationRequests& pa_requests_for_bidder = - auction_->private_aggregation_requests_[state->bidder->interest_group - .owner]; + state->private_aggregation_requests[state->bidder->interest_group + .owner]; pa_requests_for_bidder.insert(pa_requests_for_bidder.end(), std::move_iterator(pa_requests.begin()), std::move_iterator(pa_requests.end())); @@ -1584,9 +1620,10 @@ ->bid->bid_role == Bid::BidRole::kBothKAnonModes; } -void InterestGroupAuction::TakeDebugReportUrls( - std::vector<GURL>& debug_win_report_urls, - std::vector<GURL>& debug_loss_report_urls) { +void InterestGroupAuction:: + TakeDebugReportUrlsAndFillInPrivateAggregationRequests( + std::vector<GURL>& debug_win_report_urls, + std::vector<GURL>& debug_loss_report_urls) { if (!all_bids_scored_) return; @@ -1650,12 +1687,25 @@ buyer_helper->TakeDebugReportUrls(winner, signals, top_level_signals, debug_win_report_urls, debug_loss_report_urls); + + std::map<url::Origin, PrivateAggregationRequests> + private_aggregation_requests = + buyer_helper->TakePrivateAggregationRequests(winner, signals); + + for (auto& [origin, requests] : private_aggregation_requests) { + PrivateAggregationRequests& destination_vector = + private_aggregation_requests_[origin]; + destination_vector.insert(destination_vector.end(), + std::move_iterator(requests.begin()), + std::move_iterator(requests.end())); + } } // Retrieve data from component auctions as well. for (auto& component_auction_info : component_auctions_) { - component_auction_info.second->TakeDebugReportUrls(debug_win_report_urls, - debug_loss_report_urls); + component_auction_info.second + ->TakeDebugReportUrlsAndFillInPrivateAggregationRequests( + debug_win_report_urls, debug_loss_report_urls); } } @@ -1973,7 +2023,7 @@ *trace_id_); if (auction_worklet_manager_->RequestSellerWorklet( config_->decision_logic_url, config_->trusted_scoring_signals_url, - *subresource_url_builder_, config_->seller_experiment_group_id, + config_->seller_experiment_group_id, base::BindOnce(&InterestGroupAuction::OnSellerWorkletReceived, base::Unretained(this)), base::BindOnce(&InterestGroupAuction::OnSellerWorkletFatalError, @@ -2148,6 +2198,7 @@ score_ad_receivers_.Add( this, score_ad_remote.InitWithNewPipeAndPassReceiver(), std::move(bid)); DCHECK_EQ(0, config_->non_shared_params.NumPromises()); + seller_worklet_handle_->AuthorizeSubresourceUrls(*subresource_url_builder_); seller_worklet_handle_->GetSellerWorklet()->ScoreAd( bid_raw->ad_metadata, bid_raw->bid, config_->non_shared_params, GetDirectFromSellerSellerSignals(*subresource_url_builder_), @@ -2246,7 +2297,7 @@ if (!pa_requests.empty()) { DCHECK(config_); PrivateAggregationRequests& pa_requests_for_seller = - private_aggregation_requests_[config_->seller]; + bid->bid_state->private_aggregation_requests[config_->seller]; pa_requests_for_seller.insert(pa_requests_for_seller.end(), std::move_iterator(pa_requests.begin()), std::move_iterator(pa_requests.end())); @@ -2260,6 +2311,8 @@ bid->bid_state->seller_debug_win_report_url = std::move(debug_win_report_url); // Ignores reject reason if score > 0. + // TODO(qingxinwu): Set bid_state->reject_reason to nullopt instead of + // kNotAvailable when score > 0. if (score <= 0) bid->bid_state->reject_reason = reject_reason; } else { @@ -2552,9 +2605,9 @@ return auction_worklet_manager_->RequestBidderWorklet( interest_group.bidding_url.value_or(GURL()), interest_group.bidding_wasm_helper_url, - interest_group.trusted_bidding_signals_url, *subresource_url_builder_, - experiment_group_id, std::move(worklet_available_callback), - std::move(fatal_error_callback), bid_state.worklet_handle); + interest_group.trusted_bidding_signals_url, experiment_group_id, + std::move(worklet_available_callback), std::move(fatal_error_callback), + bid_state.worklet_handle); } } // namespace content
diff --git a/content/browser/interest_group/interest_group_auction.h b/content/browser/interest_group/interest_group_auction.h index 7f26cf8..7057eb91 100644 --- a/content/browser/interest_group/interest_group_auction.h +++ b/content/browser/interest_group/interest_group_auction.h
@@ -102,6 +102,9 @@ interest_group_api_operation, const url::Origin& origin)>; + using PrivateAggregationRequests = + std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>; + // Result of an auction or a component auction. Used for histograms. Only // recorded for valid auctions. These are used in histograms, so values of // existing entries must not change when adding/removing values, and obsolete @@ -264,6 +267,14 @@ absl::optional<GURL> top_level_seller_debug_win_report_url; absl::optional<GURL> top_level_seller_debug_loss_report_url; + // Requests made to Private aggregation API in generateBid() and scoreAd(). + // Keyed by reporting origin of the associated requests, i.e., buyer origin + // for generateBid() and seller origin for scoreAd(). + // TODO(qingxinwu): Consider only saving the requests without saving Origin, + // since copying Origin is expensive. + std::map<url::Origin, PrivateAggregationRequests> + private_aggregation_requests; + // The reason this bid was rejected by the auction (i.e., reason why score // was non-positive). auction_worklet::mojom::RejectReason reject_reason = @@ -367,9 +378,6 @@ // Always invoked asynchronously. using AuctionPhaseCompletionCallback = base::OnceCallback<void(bool success)>; - using PrivateAggregationRequests = - std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>; - // All passed in raw pointers must remain valid until the InterestGroupAuction // is destroyed. `config` is typically owned by the AuctionRunner's // `owned_auction_config_` field. `parent` should be the parent @@ -454,10 +462,19 @@ // auction failed for any reason other than the seller rejecting all bids. void GetInterestGroupsThatBid(blink::InterestGroupSet& interest_groups) const; - // Retrieves any debug reporting URLs. May only be called once, since it - // takes ownership of stored reporting URLs. - void TakeDebugReportUrls(std::vector<GURL>& debug_win_report_urls, - std::vector<GURL>& debug_loss_report_urls); + // Retrieves any debug reporting URLs. May only be called once, since it takes + // ownership of stored reporting URLs. + // Note: Temporarily, this function also fills post auction signals to private + // aggregation requests from generateBid() and scoreAd(), so this function + // must be called before TakePrivateAggregationRequests() to make sure that + // function gets private aggregation requests with post auction signals filled + // in. + // TODO(qingxinwu): Refactor this to fill post auction signals to private + // aggregation report in TakePrivateAggregationRequests(), ideally reuse the + // post auction signals calculated from this method. + void TakeDebugReportUrlsAndFillInPrivateAggregationRequests( + std::vector<GURL>& debug_win_report_urls, + std::vector<GURL>& debug_loss_report_urls); // Retrieves all requests to the Private Aggregation API returned by // GenerateBid() and ScoreAd(). The return value is keyed by reporting origin
diff --git a/content/browser/interest_group/interest_group_auction_reporter.cc b/content/browser/interest_group/interest_group_auction_reporter.cc index 3214096..64356f9 100644 --- a/content/browser/interest_group/interest_group_auction_reporter.cc +++ b/content/browser/interest_group/interest_group_auction_reporter.cc
@@ -9,6 +9,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "base/containers/flat_map.h" @@ -24,6 +25,7 @@ #include "content/browser/interest_group/auction_worklet_manager.h" #include "content/browser/interest_group/interest_group_auction.h" #include "content/browser/interest_group/interest_group_k_anonymity_manager.h" +#include "content/browser/interest_group/interest_group_pa_report_util.h" #include "content/browser/interest_group/interest_group_storage.h" #include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom.h" #include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom-forward.h" @@ -91,6 +93,13 @@ /*top_seller_signals=*/absl::nullopt); } +base::RepeatingClosure +InterestGroupAuctionReporter::OnNavigateToWinningAdCallback() { + return base::BindRepeating( + &InterestGroupAuctionReporter::OnNavigateToWinningAd, + weak_ptr_factory_.GetWeakPtr()); +} + void InterestGroupAuctionReporter::RequestSellerWorklet( const SellerWinningBidInfo* seller_info, const absl::optional<std::string>& top_seller_signals) { @@ -101,7 +110,6 @@ if (auction_worklet_manager_->RequestSellerWorklet( seller_info->auction_config->decision_logic_url, seller_info->auction_config->trusted_scoring_signals_url, - *seller_info->subresource_url_builder, seller_info->auction_config->seller_experiment_group_id, base::BindOnce(&InterestGroupAuctionReporter::OnSellerWorkletReceived, base::Unretained(this), base::Unretained(seller_info), @@ -159,6 +167,8 @@ seller_info->component_auction_modified_bid_params->has_bid); } + seller_worklet_handle_->AuthorizeSubresourceUrls( + *seller_info->subresource_url_builder); seller_worklet_handle_->GetSellerWorklet()->ReportResult( seller_info->auction_config->non_shared_params, InterestGroupAuction::GetDirectFromSellerSellerSignals( @@ -194,12 +204,24 @@ pa_requests, [](const auction_worklet::mojom::PrivateAggregationRequestPtr& request_ptr) { return request_ptr.is_null(); })); - if (!pa_requests.empty()) { - PrivateAggregationRequests& pa_requests_for_seller = - private_aggregation_requests_[seller_info->auction_config->seller]; - pa_requests_for_seller.insert(pa_requests_for_seller.end(), - std::move_iterator(pa_requests.begin()), - std::move_iterator(pa_requests.end())); + + const url::Origin& seller = seller_info->auction_config->seller; + for (auction_worklet::mojom::PrivateAggregationRequestPtr& request : + pa_requests) { + // reportResult() only gets executed for seller when there was an auction + // winner so we consider is_winner to be true, which results in + // "reserved.loss" reports not being reported. Bid reject reason is not + // meaningful thus not supported in reportResult(), so it is set to + // absl::nullopt. + auction_worklet::mojom::PrivateAggregationRequestPtr converted_request = + FillInPrivateAggregationRequest(std::move(request), seller_info->bid, + seller_info->highest_scoring_other_bid, + /*reject_reason=*/absl::nullopt, + /*is_winner=*/true); + if (converted_request) { + private_aggregation_requests_[seller].emplace_back( + std::move(converted_request)); + } } if (!seller_ad_beacon_map.empty()) { @@ -281,8 +303,7 @@ if (auction_worklet_manager_->RequestBidderWorklet( interest_group.bidding_url.value_or(GURL()), interest_group.bidding_wasm_helper_url, - interest_group.trusted_bidding_signals_url, - *bidder_auction.subresource_url_builder, experiment_group_id, + interest_group.trusted_bidding_signals_url, experiment_group_id, base::BindOnce(&InterestGroupAuctionReporter::OnBidderWorkletReceived, base::Unretained(this), signals_for_winner), base::BindOnce( @@ -335,6 +356,8 @@ } } + bidder_worklet_handle_->AuthorizeSubresourceUrls( + *seller_info.subresource_url_builder); bidder_worklet_handle_->GetBidderWorklet()->ReportWin( group_name, auction_config->non_shared_params.auction_signals.maybe_json(), @@ -390,13 +413,25 @@ pa_requests, [](const auction_worklet::mojom::PrivateAggregationRequestPtr& request_ptr) { return request_ptr.is_null(); })); - if (!pa_requests.empty()) { - PrivateAggregationRequests& pa_requests_for_bidder = - private_aggregation_requests_[winning_bid_info_.storage_interest_group - ->interest_group.owner]; - pa_requests_for_bidder.insert(pa_requests_for_bidder.end(), - std::move_iterator(pa_requests.begin()), - std::move_iterator(pa_requests.end())); + + const url::Origin& bidder = + winning_bid_info_.storage_interest_group->interest_group.owner; + const SellerWinningBidInfo& seller_info = GetBidderAuction(); + for (auction_worklet::mojom::PrivateAggregationRequestPtr& request : + pa_requests) { + // Only winner's reportWin() gets executed, so is_winner is true, which + // results in "reserved.loss" reports not being reported. Bid reject reason + // is not meaningful thus not supported in reportWin(), so it is set to + // absl::nullopt. + auction_worklet::mojom::PrivateAggregationRequestPtr converted_request = + FillInPrivateAggregationRequest( + std::move(request), winning_bid_info_.bid, + /*highest_scoring_other_bid=*/seller_info.highest_scoring_other_bid, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true); + if (converted_request) { + private_aggregation_requests_[bidder].emplace_back( + std::move(converted_request)); + } } if (!bidder_ad_beacon_map.empty()) { @@ -440,7 +475,23 @@ TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "auction", top_level_seller_winning_bid_info_.trace_id); errors_.insert(errors_.end(), errors.begin(), errors.end()); - std::move(callback_).Run(); + reporting_complete_ = true; + MaybeInvokeCallback(); +} + +void InterestGroupAuctionReporter::OnNavigateToWinningAd() { + if (navigated_to_winning_ad_) { + return; + } + navigated_to_winning_ad_ = true; + MaybeInvokeCallback(); +} + +void InterestGroupAuctionReporter::MaybeInvokeCallback() { + DCHECK(callback_); + if (reporting_complete_ && navigated_to_winning_ad_) { + std::move(callback_).Run(); + } } const InterestGroupAuctionReporter::SellerWinningBidInfo&
diff --git a/content/browser/interest_group/interest_group_auction_reporter.h b/content/browser/interest_group/interest_group_auction_reporter.h index 4a80112..485192a2 100644 --- a/content/browser/interest_group/interest_group_auction_reporter.h +++ b/content/browser/interest_group/interest_group_auction_reporter.h
@@ -125,8 +125,18 @@ InterestGroupAuctionReporter& operator=(const InterestGroupAuctionReporter&) = delete; + // Starts running reporting scripts. `callback` will be invoked once all + // reporting scripts have completed, and the callback returned by + // OnNavigateToWinningAdCallback() has been invoked, at which point reports + // should be sent, and the reporter can be destroyed. void Start(base::OnceClosure callback); + // Returns a callback that should be invoked once a fenced frame has been + // navigated to the winning ad. May be invoked multiple times, safe to invoke + // after destruction. `this` will not invoke the callback passed to Start() + // until the callback this method returns has been invoked at least once. + base::RepeatingClosure OnNavigateToWinningAdCallback(); + // Accessors so the owner can pass along the results of the auction. // // TODO(mmenke): Remove these, and make the reporter use them itself (or maybe @@ -199,10 +209,19 @@ PrivateAggregationRequests pa_requests, const std::vector<std::string>& errors); - // Invokes `callback_`. + // Sets `reporting_complete_` to true an invokes MaybeCompleteCallback(). void OnReportingComplete( const std::vector<std::string>& errors = std::vector<std::string>()); + // Invoked when the winning ad has been navigated to. If + // `navigated_to_winning_ad_` is false, sets it to true and invokes + // MaybeInvokeCallback(). Otherwise, does nothing. + void OnNavigateToWinningAd(); + + // Invokes callback passed in to Start() if both OnReportingComplete() and + // OnNavigateToWinningAd() have been invoked. + void MaybeInvokeCallback(); + // Retrieves the SellerWinningBidInfo of the auction the bidder was // participating in - i.e., for the component auction, if the bidder was in a // component auction, and for the top level auction, otherwise. @@ -246,6 +265,9 @@ std::vector<GURL> report_urls_; + bool reporting_complete_ = false; + bool navigated_to_winning_ad_ = false; + base::WeakPtrFactory<InterestGroupAuctionReporter> weak_ptr_factory_{this}; };
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc index bed9247..9be608e 100644 --- a/content/browser/interest_group/interest_group_browsertest.cc +++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -444,29 +444,37 @@ InterestGroupManagerImpl::InterestGroupObserverInterface::AccessType, std::string, std::string>; + void OnInterestGroupAccessed( const base::Time& access_time, InterestGroupManagerImpl::InterestGroupObserverInterface::AccessType type, const std::string& owner_origin, const std::string& name) override { - accesses.emplace_back(Entry{type, owner_origin, name}); + accesses_.emplace_back(type, owner_origin, name); - if (run_loop_.running() && accesses.size() >= expected_.size()) { - run_loop_.Quit(); + if (run_loop_ && accesses_.size() >= expected_.size()) { + run_loop_->Quit(); } } + void WaitForAccesses(const std::vector<Entry>& expected) { - if (accesses.size() < expected.size()) { + DCHECK(!run_loop_); + if (accesses_.size() < expected.size()) { + run_loop_ = std::make_unique<base::RunLoop>(); expected_ = expected; - run_loop_.Run(); + run_loop_->Run(); + run_loop_.reset(); } - EXPECT_EQ(expected, accesses); + EXPECT_EQ(expected, accesses_); + + // Clear accesses so can be reused. + accesses_.clear(); } - std::vector<Entry> accesses; private: + std::vector<Entry> accesses_; std::vector<Entry> expected_; - base::RunLoop run_loop_; + std::unique_ptr<base::RunLoop> run_loop_; }; class InterestGroupBrowserTest : public ContentBrowserTest { @@ -911,7 +919,7 @@ // Wrapper around RunAuctionAndWait that assumes the result is a URN URL and // returns the mapped URL. - [[nodiscard]] std::string RunAuctionAndWaitForURL( + [[nodiscard]] std::string RunAuctionAndWaitForUrl( const std::string& auction_config_json, const absl::optional<ToRenderFrameHost> execution_target = absl::nullopt) { @@ -1037,7 +1045,7 @@ // `url`'s hostname is replaced with "127.0.0.1", since the embedded test // server always claims requests were for 127.0.0.1, rather than revealing the // hostname that was actually associated with a request. - void WaitForURL(const GURL& url) { + void WaitForUrl(const GURL& url) { GURL::Replacements replacements; replacements.SetHostStr("127.0.0.1"); GURL wait_for_url = url.ReplaceComponents(replacements); @@ -1384,7 +1392,7 @@ // fenced frame actually made the request and, in the MPArch case, to make // sure the load actually started. On regression, this is likely to hang. if (expected_url.SchemeIs(url::kHttpsScheme)) { - WaitForURL(expected_url); + WaitForUrl(expected_url); } else { // The only other URLs this should be used with are about:blank URLs. ASSERT_EQ(GURL(url::kAboutBlankURL), expected_url); @@ -4288,12 +4296,11 @@ for (const auto& expected_report_url : kExpectedReportUrls) { SCOPED_TRACE(expected_report_url); - // Wait for the report URL to be fetched, which only happens after the - // auction has completed. - WaitForURL(expected_report_url); + // Make sure the report URL was actually fetched over the network. + WaitForUrl(expected_report_url); absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_url); + url_loader_monitor.WaitForUrl(expected_report_url); ASSERT_TRUE(request); EXPECT_EQ(network::mojom::CredentialsMode::kOmit, request->credentials_mode); @@ -4678,12 +4685,11 @@ for (const auto& expected_report_url : kExpectedReportUrls) { SCOPED_TRACE(expected_report_url); - // Wait for the report URL to be fetched, which only happens after the - // auction has completed. - WaitForURL(expected_report_url); + // Make sure the report URL was actually fetched over the network. + WaitForUrl(expected_report_url); absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_url); + url_loader_monitor.WaitForUrl(expected_report_url); ASSERT_TRUE(request); EXPECT_EQ(network::mojom::CredentialsMode::kOmit, request->credentials_mode); @@ -4720,8 +4726,6 @@ // All bidders' genereteBid() failed so no bid was made, thus no render url. IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionWithDebugReportingNoBid) { - URLLoaderMonitor url_loader_monitor; - GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html"); ASSERT_TRUE(NavigateToURL(shell(), test_url)); url::Origin test_origin = url::Origin::Create(test_url); @@ -4778,14 +4782,7 @@ for (const auto& expected_report_url : kExpectedReportUrls) { SCOPED_TRACE(expected_report_url); - - // Wait for the report URL to be fetched, which only happens after the - // auction has completed. - WaitForURL(expected_report_url); - - absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_url); - ASSERT_TRUE(request); + WaitForUrl(expected_report_url); } } @@ -4896,12 +4893,11 @@ for (const auto& expected_report_url : kExpectedReportUrls) { SCOPED_TRACE(expected_report_url); - // Wait for the report URL to be fetched, which only happens after the - // auction has completed. - WaitForURL(expected_report_url); + // Make sure the report URL was actually fetched over the network. + WaitForUrl(expected_report_url); absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_url); + url_loader_monitor.WaitForUrl(expected_report_url); ASSERT_TRUE(request); EXPECT_EQ(network::mojom::CredentialsMode::kOmit, request->credentials_mode); @@ -5015,7 +5011,7 @@ AttachInterestGroupObserver(); GURL ad_url = https_server_->GetURL( - "a.test", "/fenced_frames/ad_that_leaves_interest_group.html"); + "b.test", "/set-header?Supports-Loading-Mode: fenced-frame"); EXPECT_EQ( kSuccess, JoinInterestGroupAndVerify( @@ -5036,7 +5032,7 @@ rfh1)); GURL ad_url2 = https_server_->GetURL( - "b.test", "/fenced_frames/ad_that_leaves_interest_group.html"); + "a.test", "/set-header?Supports-Loading-Mode: fenced-frame"); EXPECT_EQ( kSuccess, JoinInterestGroupAndVerify( @@ -5067,10 +5063,23 @@ https_server_->GetURL("a.test", "/interest_group/decision_logic.js")), rfh1)); - // Wait for leave to be committed to the database. - while (GetJoinCount(test_origin, "cars") > 0) { - base::RunLoop().RunUntilIdle(); - } + // InterestGroupAccessObserver should see the join and auction. + WaitForAccessObserved({ + {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "trucks"}, + {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"}, + {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"}, + {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"}, + }); + + // Try to leave the winning interest group, which should fail, since the ad is + // on b.test, but the IG owner is a.test. Do the failed leave case first so + // that subsequent WaitForAccessObserved() calls would likely catch an + // unexpected leave event. + EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh1), + "navigator.leaveAdInterestGroup()")); ASSERT_NO_FATAL_FAILURE(RunAuctionAndNavigateFencedFrame( ad_url2, @@ -5087,30 +5096,32 @@ https_server_->GetURL("a.test", "/interest_group/decision_logic.js")), rfh2)); - // InterestGroupAccessObserver should see the join, auction, and implicit - // leave. Note that the implicit leave for "trucks" does not succeed because - // leaveAdInterestGroup is not called from the Interest Group owner's frame. + // For the second auction, InterestGroupAccessObserver should see the two + // groups loaded, but just the truck group win. Do this before the leave + // attempt, as updating the data is potentially racy with the navigation + // committing, so the leave event could appear out of order. WaitForAccessObserved( - {{InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "trucks"}, - {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"}, + {{InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"}, {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"}, - {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"}, {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"}, {InterestGroupTestObserver::kWin, test_origin.Serialize(), "trucks"}}); - // The ad should have left the "cars" interest group when the page was shown. + // Try to leave the winning interest group, which should succeed this time. Do + // it by calling Javascript directly instead of loading a page that does this + // to avoid races with logging kBin or kWin. + EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh2), + "navigator.leaveAdInterestGroup()")); + WaitForAccessObserved( + {{InterestGroupTestObserver::kLeave, test_origin.Serialize(), "trucks"}}); + + // Only the "truck" interest group should have been left. auto groups = GetAllInterestGroups(); ASSERT_EQ(1u, groups.size()); - EXPECT_EQ("trucks", groups[0].name); + EXPECT_EQ("cars", groups[0].name); } // Runs ad auction with fenced frames enabled. The auction should succeed and -// be loaded in a fenced frames. The displayed ad leaves the interest group +// be loaded in a fenced frame. The displayed ad leaves the interest group // from a nested iframe. // // TODO(crbug.com/1320438): Re-enable the test. @@ -5125,7 +5136,7 @@ AttachInterestGroupObserver(); GURL inner_url = https_server_->GetURL( - "a.test", "/fenced_frames/ad_that_leaves_interest_group.html"); + "a.test", "/set-header?Supports-Loading-Mode: fenced-frame"); GURL ad_url = https_server_->GetURL( "b.test", "/fenced_frames/outer_inner_frame_as_param.html"); GURL::Replacements rep; @@ -5162,14 +5173,22 @@ https_server_->GetURL("a.test", "/interest_group/decision_logic.js")))); - // InterestGroupAccessObserver should see the join, auction, and implicit - // leave. + // InterestGroupAccessObserver should see the join and auction. WaitForAccessObserved( {{InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"}, {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"}, {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"}}); + {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"}}); + + // Leave the interest group and wait to observe the event. Do this after the + // above WaitForAccessObserved() call, as leaving is racy with recording the + // result of an auction. + EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(web_contents()) + ->child_at(0) + ->current_frame_host(), + "navigator.leaveAdInterestGroup()")); + WaitForAccessObserved( + {{InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"}}); // The ad should have left the interest group when the page was shown. EXPECT_EQ(0u, GetAllInterestGroups().size()); @@ -5304,10 +5323,10 @@ }); // Reporting urls should be fetched after an auction succeeded. - WaitForURL(https_server_->GetURL("/echoall?report_seller")); - WaitForURL(https_server_->GetURL("/echoall?report_bidder")); + WaitForUrl(https_server_->GetURL("/echoall?report_seller")); + WaitForUrl(https_server_->GetURL("/echoall?report_bidder")); // Double-check that the trusted scoring signals URL was requested as well. - WaitForURL(https_server_->GetURL(base::StringPrintf( + WaitForUrl(https_server_->GetURL(base::StringPrintf( "/trusted_scoring_signals.json" "?hostname=a.test" "&renderUrls=%s", @@ -5362,7 +5381,7 @@ }); // Wait for the component to load. - WaitForURL(component_url); + WaitForUrl(component_url); } // Make sure correct topFrameHostname is passed in. Check auctions from top @@ -5428,7 +5447,7 @@ GURL seller_logic_url = https_server_->GetURL(kOtherHost, test_case.seller_path); ASSERT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( R"( { seller: $1, @@ -5569,8 +5588,8 @@ // Seller and winning bidder should get reports, and other bidders shouldn't // get reports. - WaitForURL(https_server_->GetURL("/echoall?report_seller")); - WaitForURL(https_server_->GetURL( + WaitForUrl(https_server_->GetURL("/echoall?report_seller")); + WaitForUrl(https_server_->GetURL( "/echoall?report_bidder_stop_bidding_after_win&cars")); base::AutoLock auto_lock(requests_lock_); EXPECT_FALSE(base::Contains(received_https_test_server_requests_, @@ -5989,6 +6008,9 @@ EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count, 0); + // Start observer after joins. + AttachInterestGroupObserver(); + std::string auction_config = JsReplace( R"({ seller: $1, @@ -6000,10 +6022,22 @@ origin); // Run an ad auction. Interest group cars of owner `test_url` wins. RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); + // Wait for interest groups to be updated. Interest groups are updated + // during/after commit, so this test is potentially racy without this. + WaitForAccessObserved( + {{InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kBid, origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kWin, origin.Serialize(), "cars"}}); // `prev_wins` of `test_url`'s interest group cars is updated in storage. storage_interest_groups = GetInterestGroupsForOwner(origin); storage_interest_groups2 = GetInterestGroupsForOwner(origin2); + // Remove the above two loads from the observer. + WaitForAccessObserved( + {{InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}}); EXPECT_EQ( storage_interest_groups.front().bidding_browser_signals->prev_wins.size(), 1u); @@ -6022,14 +6056,22 @@ EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count, 1); - // Start observer in the middle. - AttachInterestGroupObserver(); - // Run auction again. Interest group shoes of owner `test_url2` wins. RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url); + // Need to wait again. + WaitForAccessObserved( + {{InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"}}); + // `test_url2`'s interest group shoes has one `prev_wins` in storage. storage_interest_groups = GetInterestGroupsForOwner(origin); storage_interest_groups2 = GetInterestGroupsForOwner(origin2); + // Remove the above two loads from the observer. + WaitForAccessObserved( + {{InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, + {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}}); EXPECT_EQ( storage_interest_groups.front().bidding_browser_signals->prev_wins.size(), 1u); @@ -6056,6 +6098,13 @@ origin2, https_server_->GetURL("b.test", "/interest_group/decision_logic.js")); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url); + // Need to wait again. + WaitForAccessObserved({ + {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"}, + {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"}, + }); + // `test_url2`'s interest group shoes has two `prev_wins` in storage. storage_interest_groups = GetInterestGroupsForOwner(origin); storage_interest_groups2 = GetInterestGroupsForOwner(origin2); @@ -6074,20 +6123,6 @@ 1); EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count, 3); - // Observer was not active for joins and first auction. - WaitForAccessObserved({ - {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"}, - {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"}, - {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}, - }); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, ReportingMultipleAuctions) { @@ -6145,6 +6180,16 @@ // Run an ad auction. Interest group cars of owner `test_url_a` wins. RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); + // Wait for database to be updated with the win, which may happen after the + // auction completes. + WaitForInterestGroupsSatisfying( + origin_a, + base::BindLambdaForTesting( + [](const std::vector<StorageInterestGroup>& groups) -> bool { + EXPECT_EQ(1u, groups.size()); + return groups[0].bidding_browser_signals->prev_wins.size() == 1u; + })); + // Run auction again on the same page. Interest group shoes of owner // `test_url2` wins. auction_config = JsReplace( @@ -6158,6 +6203,16 @@ origin_a); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url); + // Wait for database to be updated with the win, which may happen after the + // auction completes. + WaitForInterestGroupsSatisfying( + origin_b, + base::BindLambdaForTesting( + [](const std::vector<StorageInterestGroup>& groups) -> bool { + EXPECT_EQ(1u, groups.size()); + return groups[0].bidding_browser_signals->prev_wins.size() == 1u; + })); + // Run the third auction on another page c.test, and only interest group // "shoes" of c.test bids this time. GURL test_url_c = https_server_->GetURL("c.test", "/page_with_iframe.html"); @@ -6192,7 +6247,7 @@ // Check ResourceRequest structs of report requests. // The URLs must not have the same path with different hostnames, because - // WaitForURL() always replaces hostnames with "127.0.0.1", thus only waits + // WaitForUrl() always replaces hostnames with "127.0.0.1", thus only waits // for the first URL among URLs with the same path. const struct ExpectedReportRequest { GURL url; @@ -6238,11 +6293,11 @@ for (const auto& expected_report_request : kExpectedReportRequests) { SCOPED_TRACE(expected_report_request.url); - // Wait for the report URL to be fetched. - WaitForURL(expected_report_request.url); + // Make sure the report URL was actually fetched over the network. + WaitForUrl(expected_report_request.url); absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_request.url); + url_loader_monitor.WaitForUrl(expected_report_request.url); ASSERT_TRUE(request); EXPECT_EQ(network::mojom::CredentialsMode::kOmit, request->credentials_mode); @@ -6502,7 +6557,7 @@ // Wait for the URL to be requested, to make sure the fenced frame actually // made the request and, in the MPArch case, to make sure the load actually // started. - WaitForURL(new_url); + WaitForUrl(new_url); // Wait for the load to complete. observer.Wait(); @@ -7343,11 +7398,11 @@ // don't want to send a random request to port 80 on localhost, which is what // example.com is mapped to. observer.on_navigate_callback().Run(); - WaitForURL(https_server_->GetURL(kTopLevelSellerHost, + WaitForUrl(https_server_->GetURL(kTopLevelSellerHost, "/echo?report_top_level_seller")); - WaitForURL(https_server_->GetURL(kComponentSellerHost, + WaitForUrl(https_server_->GetURL(kComponentSellerHost, "/echo?report_component_seller")); - WaitForURL(https_server_->GetURL(kBidderHost, "/echo?report_bidder")); + WaitForUrl(https_server_->GetURL(kBidderHost, "/echo?report_bidder")); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, @@ -8006,7 +8061,7 @@ )", hanging_origin, hanging_url)); - WaitForURL(https_server_->GetURL("/hung")); + WaitForUrl(https_server_->GetURL("/hung")); } // These tests validate the `dailyUpdateUrl` and @@ -8326,7 +8381,7 @@ })"; EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( kAuctionConfigTemplate, url::Origin::Create(seller_logic_url), seller_logic_url, https_server_->GetURL( @@ -8335,10 +8390,10 @@ // Make sure that the right trusted signals URLs got fetched, incorporating // the experiment group ID. - WaitForURL(https_server_->GetURL( + WaitForUrl(https_server_->GetURL( "/interest_group/trusted_bidding_signals.json?hostname=a.test&keys=key1" "&interestGroupNames=cars&experimentGroupId=3498")); - WaitForURL(https_server_->GetURL( + WaitForUrl(https_server_->GetURL( "/interest_group/trusted_scoring_signals.json?hostname=a.test" "&renderUrls=https%3A%2F%2Fexample.com%2Frender&experimentGroupId=8349")); } @@ -8403,16 +8458,16 @@ })"; EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( kAuctionConfigTemplate, url::Origin::Create(seller_logic_url), seller_logic_url, bidder_origin, bidder2_origin))); // Make sure that the right trusted signals URLs got fetched, incorporating // the experiment group IDs. - WaitForURL(https_server_->GetURL( + WaitForUrl(https_server_->GetURL( "/interest_group/trusted_bidding_signals.json?hostname=a.test&keys=key1" "&interestGroupNames=cars&experimentGroupId=3498")); - WaitForURL(https_server_->GetURL( + WaitForUrl(https_server_->GetURL( "/interest_group/trusted_bidding_signals.json?hostname=a.test&keys=key2" "&interestGroupNames=cars_and_trucks&experimentGroupId=1203")); } @@ -8719,15 +8774,15 @@ seller_debug_win_report_url}) { SCOPED_TRACE(report_url.spec()); EXPECT_EQ(network::mojom::IPAddressSpace::kPublic, - url_loader_monitor.GetRequestInfo(report_url) - ->trusted_params->client_security_state->ip_address_space); + url_loader_monitor.WaitForUrl(report_url) + .trusted_params->client_security_state->ip_address_space); } // Check that all reports reached the server. - WaitForURL(bidder_report_to_url); - WaitForURL(seller_report_to_url); - WaitForURL(bidder_debug_win_report_url); - WaitForURL(seller_debug_win_report_url); + WaitForUrl(bidder_report_to_url); + WaitForUrl(seller_report_to_url); + WaitForUrl(bidder_debug_win_report_url); + WaitForUrl(seller_debug_win_report_url); } // Make sure that the IPAddressSpace of the frame that triggers the update is @@ -9251,7 +9306,7 @@ execution_target)); EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL( + RunAuctionAndWaitForUrl( JsReplace( R"( { @@ -9414,7 +9469,7 @@ execution_target)); EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL( + RunAuctionAndWaitForUrl( JsReplace( R"( { @@ -9531,7 +9586,7 @@ // Interest group APIs fail and run ad auction succeeds for iframe_ad_auction. ExpectNotAllowedToJoinOrUpdateInterestGroup(other_origin, iframe_ad_auction); EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL( + RunAuctionAndWaitForUrl( JsReplace( R"( { @@ -9643,7 +9698,7 @@ // Only the `send_reports` == true case should have sent a report. Wait for // it, and then check that the report URL for the first case was not seen. - WaitForURL(kTestCases[1].report_url); + WaitForUrl(kTestCases[1].report_url); EXPECT_FALSE(HasServerSeenUrl(kTestCases[0].report_url)); } @@ -9705,7 +9760,7 @@ blink::InterestGroup::ExecutionMode::kCompatibilityMode ? "/echo?1" : "/echo?10"), - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( R"({ seller: $1, decisionLogicUrl: $2, @@ -9820,7 +9875,7 @@ // 1st auction -- before navigations EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( R"({ seller: $1, decisionLogicUrl: $2, @@ -9840,7 +9895,7 @@ // 2nd auction -- after navigations EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( R"({ seller: $1, decisionLogicUrl: $2, @@ -9891,7 +9946,7 @@ // 1st auction -- in main frame EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL(JsReplace( + RunAuctionAndWaitForUrl(JsReplace( R"({ seller: $1, decisionLogicUrl: $2, @@ -9903,7 +9958,7 @@ // 2nd auction -- in cross-origin iframe EXPECT_EQ("https://example.com/render", - RunAuctionAndWaitForURL( + RunAuctionAndWaitForUrl( JsReplace( R"({ seller: $1, @@ -9949,8 +10004,6 @@ IN_PROC_BROWSER_TEST_F( InterestGroupBiddingAndScoringDebugReportingAPIDisabledBrowserTest, RunAdAuctionWithDebugReporting) { - URLLoaderMonitor url_loader_monitor; - GURL test_url = https_server_->GetURL("a.test", "/page_with_iframe.html"); ASSERT_TRUE(NavigateToURL(shell(), test_url)); url::Origin test_origin = url::Origin::Create(test_url); @@ -10001,14 +10054,7 @@ for (const auto& expected_report_url : kExpectedReportUrls) { SCOPED_TRACE(expected_report_url); - - // Wait for the report URL to be fetched, which only happens after the - // auction has completed. - WaitForURL(expected_report_url); - - absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(expected_report_url); - ASSERT_TRUE(request); + WaitForUrl(expected_report_url); } // No requests should be sent to forDebuggingOnly reporting URLs when @@ -10023,9 +10069,7 @@ // Debugging report URL from seller for win report. https_server_->GetURL("a.test", "/echo?seller_debug_report_win/winner")}; for (const auto& debugging_report_url : kDebuggingReportUrls) { - absl::optional<network::ResourceRequest> request = - url_loader_monitor.GetRequestInfo(debugging_report_url); - ASSERT_FALSE(request); + EXPECT_FALSE(HasServerSeenUrl(debugging_report_url)); } }
diff --git a/content/browser/interest_group/interest_group_pa_report_util.cc b/content/browser/interest_group/interest_group_pa_report_util.cc new file mode 100644 index 0000000..4138a26 --- /dev/null +++ b/content/browser/interest_group/interest_group_pa_report_util.cc
@@ -0,0 +1,267 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/interest_group/interest_group_pa_report_util.h" + +#include <stdint.h> + +#include <cmath> +#include <string> +#include <utility> +#include <vector> + +#include "base/check.h" +#include "base/containers/flat_map.h" +#include "base/notreached.h" +#include "base/numerics/clamped_math.h" +#include "content/common/aggregatable_report.mojom.h" +#include "content/common/content_export.h" +#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h" +#include "content/services/auction_worklet/public/mojom/seller_worklet.mojom.h" +#include "third_party/abseil-cpp/absl/numeric/int128.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/origin.h" + +namespace content { + +const char kReservedAlways[] = "reserved.always"; +const char kReservedWin[] = "reserved.win"; +const char kReservedLoss[] = "reserved.loss"; + +namespace { + +// Returns the actual value of `base_value` with corresponding post auction +// signal such as `winning_bid`. Returns absl::nullopt if corresponding signal +// is not available. +// TODO(crbug.com/1385549): Pass in signals for script run time and signals +// fetch time. +absl::optional<double> GetBaseValue( + auction_worklet::mojom::BaseValue base_value, + double winning_bid, + double highest_scoring_other_bid, + const absl::optional<auction_worklet::mojom::RejectReason> reject_reason) { + // The mojom API declaration should ensure base_value is one of these cases. + switch (base_value) { + case auction_worklet::mojom::BaseValue::kWinningBid: + return winning_bid; + case auction_worklet::mojom::BaseValue::kHighestScoringOtherBid: + return highest_scoring_other_bid; + case auction_worklet::mojom::BaseValue::kScriptRunTime: + return absl::nullopt; + case auction_worklet::mojom::BaseValue::kSignalsFetchTime: + return absl::nullopt; + case auction_worklet::mojom::BaseValue::kBidRejectReason: + // reportWin() and reportResult() have no reject reason, so their private + // aggregation requests with "bidRejectReason" base value are not sent. + // If scoreAd() doesn't return a reject reason, it's reported as + // kNotAvailable, instead of not being reported. + if (reject_reason.has_value()) { + return static_cast<int>(reject_reason.value()); + } + return absl::nullopt; + } + NOTREACHED(); + return absl::nullopt; +} + +// Returns contribution's bucket calculated from `base`, and `bucket_obj`'s +// scale and offset. Returns absl::nullopt if `base` is absl::nullopt, or base +// or scale is NaN/infinity. Applies saturation arithmetic (in which all +// operations are limited to a fixed range) to uint128 bucket (also applied to +// intermediate results when they are too large to fit into a uint128). The +// fixed range is 0 to absl::Uint128Max(). +absl::optional<absl::uint128> CalculateBucket( + const auction_worklet::mojom::SignalBucketPtr& bucket_obj, + absl::optional<double> base) { + if (!base.has_value()) { + // Once kScriptRunTime and kSignalsFetchTime are supported, this should not + // happen. + return absl::nullopt; + } + + // The multiplication of base value with scale is performed using double + // precision floating point numbers, as specified in the explainer. + // https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md + double scaled_base_value = base.value() * bucket_obj->scale; + + // Returns absl::nullopt if scaled_base_value is NaN. + // TODO(crbug.com/1410339): Throw a bad message if scale is NaN or infinity. + if (std::isnan(scaled_base_value)) { + return absl::nullopt; + } + + bool scaled_base_value_is_negative = std::signbit(scaled_base_value); + if (std::isinf(scaled_base_value) || + std::abs(scaled_base_value) >= std::ldexp(1.0L, 128)) { + // Clamps to max value of uint128 when it overflows due to too high a + // result, or clamps to 0 if it is negative i.e., base.value() * scale is + // not finite or cannot fit into uint128. Also returns it since adding the + // offset to an overflow number doesn't make sense. + return scaled_base_value_is_negative ? 0 : absl::Uint128Max(); + } + + // May truncate the floating point result when converting to an integer. + absl::uint128 abs_scaled_base_value = + absl::uint128(std::abs(scaled_base_value)); + + auction_worklet::mojom::BucketOffsetPtr offset = + std::move(bucket_obj->offset); + if (!offset) { + return scaled_base_value_is_negative ? 0 : abs_scaled_base_value; + } + + if (offset->is_negative) { + return (scaled_base_value_is_negative || + abs_scaled_base_value < offset->value) + ? 0 + : abs_scaled_base_value - offset->value; + } + + if (scaled_base_value_is_negative) { + // Clamps if offset - abs_scale_base_value < 0. + return offset->value < abs_scaled_base_value + ? 0 + : offset->value - abs_scaled_base_value; + } + + // Clamps if the sum of abs_scale_base_value and offset overflows due to too + // big. + return abs_scaled_base_value > absl::Uint128Max() - offset->value + ? absl::Uint128Max() + : offset->value + abs_scaled_base_value; +} + +// Returns contribution's value calculated from `base`, and `value_obj`'s scale +// and offset. Returns absl::nullopt if `base` is absl::nullopt, or base or +// scale being NaN/infinity +absl::optional<int32_t> CalculateValue( + const auction_worklet::mojom::SignalValuePtr& value_obj, + absl::optional<double> base) { + if (!base.has_value()) { + // Once kScriptRunTime and kSignalsFetchTime are supported, this should not + // happen. + return absl::nullopt; + } + + double scaled_base_value = base.value() * value_obj->scale; + // Returns absl::nullopt if the product of base and scale is NaN. + // TODO(crbug.com/1410339): Throw a bad message if scale is NaN or infinity. + if (std::isnan(scaled_base_value)) { + return absl::nullopt; + } + + // Note: truncates the floating point result, without losing precision since + // doubles can store all 32-bit integers exactly. Saturating as needed. + // Mojom should guarantee offset being int32. + // TODO(crbug.com/1410402): Clamp negative value to 0. + base::ClampedNumeric<int32_t> value = scaled_base_value + value_obj->offset; + return value; +} + +// Calculates given for-event `contribution`'s bucket and value with given post +// auction signals such as `winning_bid`, and returns a histogram contribution +// with calculated bucket and value. Returns nullptr if +// `contribution`'s bucket cannot be calculated to a valid uint128 number, or +// `contribution`'s value cannot be calculated to a valid integer. +auction_worklet::mojom::AggregatableReportContributionPtr +CalculateContributionBucketAndValue( + auction_worklet::mojom::AggregatableReportForEventContributionPtr + contribution, + double winning_bid, + double highest_scoring_other_bid, + const absl::optional<auction_worklet::mojom::RejectReason> reject_reason) { + absl::uint128 bucket; + int value; + + if (contribution->bucket->is_id_bucket()) { + bucket = contribution->bucket->get_id_bucket(); + } else { + auction_worklet::mojom::SignalBucketPtr& bucket_obj = + contribution->bucket->get_signal_bucket(); + absl::optional<absl::uint128> bucket_opt = CalculateBucket( + bucket_obj, GetBaseValue(bucket_obj->base_value, winning_bid, + highest_scoring_other_bid, reject_reason)); + if (!bucket_opt.has_value()) { + return nullptr; + } + bucket = bucket_opt.value(); + } + + if (contribution->value->is_int_value()) { + // TODO(crbug.com/1410402): Clamp negative value to 0. + value = contribution->value->get_int_value(); + } else { + const auction_worklet::mojom::SignalValuePtr& value_obj = + contribution->value->get_signal_value(); + absl::optional<int> value_opt = CalculateValue( + value_obj, GetBaseValue(value_obj->base_value, winning_bid, + highest_scoring_other_bid, reject_reason)); + if (!value_opt.has_value()) { + return nullptr; + } + value = value_opt.value(); + } + + return auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New(bucket, + value)); +} + +} // namespace + +auction_worklet::mojom::PrivateAggregationRequestPtr +FillInPrivateAggregationRequest( + auction_worklet::mojom::PrivateAggregationRequestPtr request, + double winning_bid, + double highest_scoring_other_bid, + const absl::optional<auction_worklet::mojom::RejectReason> reject_reason, + bool is_winner) { + DCHECK(request); + if (request->contribution->is_histogram_contribution()) { + return request; + } + + auction_worklet::mojom::AggregatableReportContributionPtr contribution = + std::move(request->contribution); + + // The mojom API declaration should ensure `contribution` being a + // for-event contribution if not a histogram contribution. + DCHECK(contribution->is_for_event_contribution()); + const std::string event_type = + contribution->get_for_event_contribution()->event_type; + if (!base::StartsWith(event_type, "reserved.")) { + // TODO(crbug.com/1410340): Supports requests with non-reserved event types. + return nullptr; + } + + // Rejects invalid reserved event type. The worklet code should prevent this, + // but the process may be compromised. This is largely preventing the owner + // from messing up its own private aggregation reporting function. + // + // Note that the data received here has no effect on the result of the + // auction, so just reject the data and continue with the auction to keep + // the code simple. + if (event_type != kReservedWin && event_type != kReservedLoss && + event_type != kReservedAlways) { + return nullptr; + } + + if ((is_winner && event_type == kReservedLoss) || + (!is_winner && event_type == kReservedWin)) { + return nullptr; + } + auction_worklet::mojom::AggregatableReportContributionPtr + calculated_contribution = CalculateContributionBucketAndValue( + std::move(contribution->get_for_event_contribution()), winning_bid, + highest_scoring_other_bid, reject_reason); + if (!calculated_contribution) { + return nullptr; + } + return auction_worklet::mojom::PrivateAggregationRequest::New( + std::move(calculated_contribution), request->aggregation_mode, + std::move(request->debug_mode_details)); +} + +} // namespace content
diff --git a/content/browser/interest_group/interest_group_pa_report_util.h b/content/browser/interest_group/interest_group_pa_report_util.h new file mode 100644 index 0000000..b7cf345e --- /dev/null +++ b/content/browser/interest_group/interest_group_pa_report_util.h
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_PA_REPORT_UTIL_H_ +#define CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_PA_REPORT_UTIL_H_ + +#include "content/common/content_export.h" +#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom-forward.h" +#include "content/services/auction_worklet/public/mojom/seller_worklet.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace content { + +// Reserved event types for aggregatable report's for-event contribution. +CONTENT_EXPORT extern const char kReservedAlways[]; +CONTENT_EXPORT extern const char kReservedWin[]; +CONTENT_EXPORT extern const char kReservedLoss[]; + +// If request's contribution is an AggregatableReportForEventContribution, fills +// the contribution in with post-auction signals such as winning_bid, converts +// it to an AggregatableReportHistogramContribution and returns the resulting +// PrivateAggregationRequest. Returns nullptr in case of an error, or the +// request should not be sent (e.g., it's for a losing bidder but request's +// event type is "reserved.win"). Simply returns request if it's contribution is +// an AggregatableReportHistogramContribution. +CONTENT_EXPORT auction_worklet::mojom::PrivateAggregationRequestPtr +FillInPrivateAggregationRequest( + auction_worklet::mojom::PrivateAggregationRequestPtr request, + double winning_bid, + double highest_scoring_other_bid, + const absl::optional<auction_worklet::mojom::RejectReason> reject_reason, + bool is_winner); + +} // namespace content + +#endif // CONTENT_BROWSER_INTEREST_GROUP_INTEREST_GROUP_PA_REPORT_UTIL_H_
diff --git a/content/browser/interest_group/interest_group_pa_report_util_unittest.cc b/content/browser/interest_group/interest_group_pa_report_util_unittest.cc new file mode 100644 index 0000000..8bc4283 --- /dev/null +++ b/content/browser/interest_group/interest_group_pa_report_util_unittest.cc
@@ -0,0 +1,555 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/interest_group/interest_group_pa_report_util.h" + +#include <stdint.h> +#include <string> +#include <utility> + +#include "content/common/aggregatable_report.mojom.h" +#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/numeric/int128.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace content { +namespace { + +const auto kExpectedRequest = + auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + /*bucket=*/123, + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + +auction_worklet::mojom::SignalBucketPtr CreateSignalBucket( + double scale, + absl::uint128 offset_value, + bool is_negative, + auction_worklet::mojom::BaseValue base_value = + auction_worklet::mojom::BaseValue::kWinningBid) { + return auction_worklet::mojom::SignalBucket::New( + base_value, scale, + /*offset=*/ + auction_worklet::mojom::BucketOffset::New(offset_value, is_negative)); +} + +auction_worklet::mojom::SignalValuePtr CreateSignalValue( + double scale, + int32_t offset, + auction_worklet::mojom::BaseValue base_value = + auction_worklet::mojom::BaseValue::kWinningBid) { + return auction_worklet::mojom::SignalValue::New(base_value, scale, offset); +} + +// Creates a PrivateAggregationRequest with histogram contribution using +// uint128 `bucket` and int `value`. +auction_worklet::mojom::PrivateAggregationRequestPtr CreateHistogramRequest( + absl::uint128 bucket, + int32_t value) { + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + bucket, value)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + +// Creates a PrivateAggregationRequest with ForEvent contribution using +// uint128 `bucket` and int `value`. +auction_worklet::mojom::PrivateAggregationRequestPtr CreateForEventRequest( + absl::uint128 bucket, + int32_t value, + const std::string& event_type) { + auto contribution = + auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::ForEventSignalBucket::NewIdBucket(bucket), + auction_worklet::mojom::ForEventSignalValue::NewIntValue(value), + event_type); + + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(std::move(contribution)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + +// Creates a PrivateAggregationRequest with ForEvent contribution using +// `bucket` object and int `value`. +auction_worklet::mojom::PrivateAggregationRequestPtr +CreateForEventRequestWithBucketObject( + auction_worklet::mojom::SignalBucketPtr bucket, + int32_t value, + const std::string& event_type) { + auto contribution = + auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::ForEventSignalBucket::NewSignalBucket( + std::move(bucket)), + auction_worklet::mojom::ForEventSignalValue::NewIntValue(value), + event_type); + + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(std::move(contribution)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + +// Creates a PrivateAggregationRequest with ForEvent contribution using +// uint128 `bucket` and `value` object. +auction_worklet::mojom::PrivateAggregationRequestPtr +CreateForEventRequestWithValueObject( + absl::uint128 bucket, + auction_worklet::mojom::SignalValuePtr value, + const std::string& event_type) { + auto contribution = + auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::ForEventSignalBucket::NewIdBucket(bucket), + auction_worklet::mojom::ForEventSignalValue::NewSignalValue( + std::move(value)), + event_type); + + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(std::move(contribution)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); +} + +} // namespace + +class InterestGroupPaReportUtilTest : public testing::Test { + public: + InterestGroupPaReportUtilTest() = default; + + ~InterestGroupPaReportUtilTest() override = default; +}; + +// Expects FillInPrivateAggregationRequest() returns the same request if its +// input `request` is a HistogramContribution, regardless of is_winner being +// true or false. +TEST_F(InterestGroupPaReportUtilTest, HistogramContribution) { + auction_worklet::mojom::PrivateAggregationRequest request( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + /*bucket=*/123, + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + request.Clone(), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + request.Clone(), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/false)); +} + +// FillInPrivateAggregationRequest() sets returned request's +// aggregation_mode and debug_mode_details correctly. +TEST_F(InterestGroupPaReportUtilTest, AggregationModeAndDebugMode) { + auction_worklet::mojom::PrivateAggregationRequest request( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + /*bucket=*/123, + /*value=*/45)), + content::mojom::AggregationServiceMode::kExperimentalPoplar, + content::mojom::DebugModeDetails::New( + /*is_enabled=*/true, + /*debug_key=*/content::mojom::DebugKey::New(1234u))); + + EXPECT_EQ(request.Clone(), + FillInPrivateAggregationRequest( + request.Clone(), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionReservedEventType) { + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedAlways), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedAlways), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/false)); + + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + EXPECT_FALSE(FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/false)); + + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedLoss), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/false)); + EXPECT_FALSE(FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedLoss), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + EXPECT_FALSE(FillInPrivateAggregationRequest( + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/"reserved.not-supported"), + /*winning_bid=*/1, /*highest_scoring_other_bid=*/2, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionBaseValueWinningBid) { + // Bucket should be uint128(10 * 10) + 23 = 123. + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + CreateSignalBucket(/*scale=*/10, /*offset_value=*/23, + /*is_negative=*/false), + /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/10, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + // Value should be int(2.2 * 10) + 23 = 45. + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, + /*value=*/CreateSignalValue(/*scale=*/10, /*offset=*/23), + /*event_type=*/kReservedWin), + /*winning_bid=*/2.2, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, + ForEventContributionBaseValueHighestScoringOtherBid) { + // Bucket should be uint128(14.6 * 10) - 23 = 123. + EXPECT_EQ( + kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/CreateSignalBucket( + /*scale=*/10.0, /*offset_value=*/23, /*is_negative=*/true, + /*base_value=*/ + auction_worklet::mojom::BaseValue::kHighestScoringOtherBid), + /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/15, /*highest_scoring_other_bid=*/14.6, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + // Value should be int(6.8 * 10) - 23 = 45. + EXPECT_EQ( + kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, /*value=*/ + CreateSignalValue( + /*scale=*/10.0, /*offset=*/-23, /*base_value=*/ + auction_worklet::mojom::BaseValue::kHighestScoringOtherBid), + /*event_type=*/kReservedWin), + /*winning_bid=*/15, /*highest_scoring_other_bid=*/6.8, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, + ForEventContributionBaseValueRejectReason) { + auction_worklet::mojom::SignalBucket signal_bucket( + /*base_value=*/auction_worklet::mojom::BaseValue::kBidRejectReason, + /*scale=*/39.0, + /*offset=*/ + auction_worklet::mojom::BucketOffset::New(/*value=*/6, + /*is_negative=*/false)); + + // kPendingApprovalByExchange is 3. Bucket should be uint128(3 * 39) + 6 = + // 123. + EXPECT_EQ( + kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/signal_bucket.Clone(), /*value=*/45, + /*event_type=*/kReservedLoss), + /*winning_bid=*/0, /*highest_scoring_other_bid=*/0, + /*reject_reason=*/ + auction_worklet::mojom::RejectReason::kPendingApprovalByExchange, + /*is_winner=*/false)); + + // kInvalidBid is 1. Value should be int(1 * 39) + 6 = 45. + EXPECT_EQ( + kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, /*value=*/ + CreateSignalValue( + /*scale=*/39.0, /*offset=*/6, /*base_value=*/ + auction_worklet::mojom::BaseValue::kBidRejectReason), + /*event_type=*/kReservedLoss), + /*winning_bid=*/0, /*highest_scoring_other_bid=*/0, + /*reject_reason=*/auction_worklet::mojom::RejectReason::kInvalidBid, + /*is_winner=*/false)); + + // kNotAvailable is also reported. kNotAvailable is 0, so bucket is 0 * 39 + 6 + EXPECT_EQ( + auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution( + content::mojom::AggregatableReportHistogramContribution::New( + /*bucket=*/6, + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()), + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/signal_bucket.Clone(), /*value=*/45, + /*event_type=*/kReservedLoss), + /*winning_bid=*/2, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/auction_worklet::mojom::RejectReason::kNotAvailable, + /*is_winner=*/false)); + + // FillInPrivateAggregationRequest() should return nullptr when its + // reject_reason parameter is empty and request's base_value is + // kBidRejectReason. + EXPECT_FALSE(FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/signal_bucket.Clone(), /*value=*/45, + /*event_type=*/kReservedLoss), + /*winning_bid=*/0, /*highest_scoring_other_bid=*/0, + /*reject_reason=*/absl::nullopt, /*is_winner=*/false)); +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionNoScaleOrOffset) { + // No scale is provided to bucket. + auction_worklet::mojom::SignalBucket bucket; + bucket.base_value = auction_worklet::mojom::BaseValue::kWinningBid; + + // Default scale is 1.0. Bucket should be 123 * 1.0 = 123. + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/bucket.Clone(), /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/123, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + // No scale or offset are provided to value. + auction_worklet::mojom::SignalValue value; + value.base_value = auction_worklet::mojom::BaseValue::kWinningBid; + + // Default scale is 1.0 and default offset is 0. Value should be 45 * 1.0 + 0 + EXPECT_EQ(kExpectedRequest, + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, value.Clone(), + /*event_type=*/kReservedWin), + /*winning_bid=*/45, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionZeroScale) { + auction_worklet::mojom::SignalBucket bucket( + /*base_value=*/auction_worklet::mojom::BaseValue::kWinningBid, + /*scale=*/0, + /*offset=*/nullptr); + + // Bucket should be 123 * 0 + EXPECT_EQ(CreateHistogramRequest(/*bucket=*/0, /*value=*/45), + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + /*bucket=*/bucket.Clone(), + /*value=*/45, + /*event_type=*/kReservedWin), + /*winning_bid=*/123, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + + auction_worklet::mojom::SignalValue value( + /*base_value=*/auction_worklet::mojom::BaseValue::kWinningBid, + /*scale=*/0, + /*offset=*/0); + + // Value should be 45 * 0 + 0 + EXPECT_EQ(CreateHistogramRequest(/*bucket=*/123, /*value=*/0), + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, + /*value=*/value.Clone(), + /*event_type=*/kReservedWin), + /*winning_bid=*/45, /*highest_scoring_other_bid=*/1, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionCalculateBucket) { + struct { + double base; + double scale; + absl::uint128 offset; + bool offset_is_negative; + absl::optional<absl::uint128> expected_bucket; + } test_cases[] = { + // Overflow in base*scale. It shouldn't matter whether the base or scale + // or the two combined cause the overflow. Overflows due to the value is + // too big should go to Uint128Max. Overflows due to the value is negative + // go to 0. + // 1 * pow(2,128) => absl::Uint128Max() + {1, std::ldexp(1, 128), 0, false, absl::Uint128Max()}, + // pow(2,128) * 1 => absl::Uint128Max() + {std::ldexp(1, 128), 1, 0, false, absl::Uint128Max()}, + // 2 * pow(2,127)=> absl::Uint128Max() + {2, std::ldexp(1, 127), 0, false, absl::Uint128Max()}, + // pow(2,127) * 2 => absl::Uint128Max() + {std::ldexp(1, 127), 2, 0, false, absl::Uint128Max()}, + // -1 * pow(2,128) => 0 + {-1, std::ldexp(1, 128), 0, false, 0}, + // pow(2,128) * -1 => 0 + {std::ldexp(1, 128), -1, 0, false, 0}, + // 2 * -pow(2,127) => 0 + {2, -std::ldexp(1, 127), 0, false, 0}, + // -pow(2,127) * 2 => 0 + {-std::ldexp(1, 127), 2, 0, false, 0}, + // -1 * -pow(2,128) => absl::Uint128Max() + {-1, -std::ldexp(1, 128), 0, false, absl::Uint128Max()}, + // -pow(2,128) * -1 => absl::Uint128Max() + {-std::ldexp(1, 128), -1, 0, false, absl::Uint128Max()}, + // inf * 1 => absl::Uint128Max() + {std::numeric_limits<double>::infinity(), 1, 0, false, + absl::Uint128Max()}, + // 1 * inf => absl::Uint128Max() + {1, std::numeric_limits<double>::infinity(), 0, false, + absl::Uint128Max()}, + // -inf * 1 => 0 + {-std::numeric_limits<double>::infinity(), 1, 0, false, 0}, + // -1 * inf => 0 + {-1, std::numeric_limits<double>::infinity(), 0, false, 0}, + // NaN * 1 => absl::nullopt + {std::numeric_limits<double>::quiet_NaN(), 1, 0, false, absl::nullopt}, + // 1 * NaN => absl::nullopt + {1, std::numeric_limits<double>::quiet_NaN(), 0, false, absl::nullopt}, + // NaN * -1 => absl::nullopt + {std::numeric_limits<double>::quiet_NaN(), -1, 0, false, absl::nullopt}, + // -1 * NaN => absl::nullopt + {-1, std::numeric_limits<double>::quiet_NaN(), 0, false, absl::nullopt}, + + // Overflow from adding/subtracting offset. + // 1 * 1 + absl::Uint128Max() => absl::Uint128Max() + {1, 1, absl::Uint128Max(), false, absl::Uint128Max()}, + // -1 * 1 - 1 => 0 + {-1, 1, 1, true, 0}, + // 1 * 1 - 2 => 0 + {-1, 1, 2, true, 0}, + + // Result does not overflow. + // 1.9 * 2.0 - 1 => 2 + {1.9, 2.0, 1, true, 2}, + // 1 * 2 - 1 => 1 + {1, 2, 1, true, 1}, + // 1 * -1 + 2 => 1 + {1, -1, 2, false, 1}, + // 1 * 1 + 1 => 2 + {1, 1, 1, false, 2}, + }; + for (const auto& test_case : test_cases) { + EXPECT_EQ(test_case.expected_bucket.has_value() + ? CreateHistogramRequest(test_case.expected_bucket.value(), + /*value=*/45) + : nullptr, + FillInPrivateAggregationRequest( + CreateForEventRequestWithBucketObject( + CreateSignalBucket(test_case.scale, test_case.offset, + test_case.offset_is_negative), + /*value=*/45, + /*event_type=*/kReservedAlways), + /*winning_bid=*/test_case.base, + /*highest_scoring_other_bid=*/0, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + } +} + +TEST_F(InterestGroupPaReportUtilTest, ForEventContributionCalculateValue) { + struct { + double base; + double scale; + int32_t offset; + absl::optional<int32_t> expected_value; + } test_cases[] = { + // Result overflows. + // INT32_MAX * 1 + 1 => INT32_MAX + {1, INT32_MAX, INT32_MAX, INT32_MAX}, + // 2 * INT32_MAX + 1 => INT32_MAX + {2, INT32_MAX, INT32_MAX, INT32_MAX}, + // 1 * 1 + INT32_MAX => INT32_MAX + {1, 1, INT32_MAX, INT32_MAX}, + // INT32_MIN * 1 - 1 => INT32_MIN + {INT32_MIN, 1, -1, INT32_MIN}, + // INT32_MAX * -1 - 1 => INT32_MIN + {INT32_MAX, -1, -1, INT32_MIN}, + // INT32_MIN * -1 + 0 => INT32_MAX + {INT32_MIN, -1, 0, INT32_MAX}, + + // inf * 1 => INT32_MAX + {std::numeric_limits<double>::infinity(), 1, 0, INT32_MAX}, + // 1 * inf => INT32_MAX + {1, std::numeric_limits<double>::infinity(), 0, INT32_MAX}, + // -inf * 1 => INT32_MIN + {-std::numeric_limits<double>::infinity(), 1, 0, INT32_MIN}, + // -1 * inf => INT32_MIN + {-1, std::numeric_limits<double>::infinity(), 0, INT32_MIN}, + // NaN * 1 => absl::nullopt + {std::numeric_limits<double>::quiet_NaN(), 1, 0, absl::nullopt}, + // 1 * NaN => absl::nullopt + {1, std::numeric_limits<double>::quiet_NaN(), 0, absl::nullopt}, + // NaN * -1 => absl::nullopt + {std::numeric_limits<double>::quiet_NaN(), -1, 0, absl::nullopt}, + // -1 * NaN => absl::nullopt + {-1, std::numeric_limits<double>::quiet_NaN(), 0, absl::nullopt}, + + // Result does not overflow. Double result will be truncated to int32 if + // necessary. + // INT32_MIN * -1 - 2 => INT32_MAX - 1 + {INT32_MIN, -1, -2, INT32_MAX - 1}, + // 1.9 * 2.0 - 1 => 2 + {1.9, 2.0, -1, 2}, + // 1.9 * -2.0 + 2 => -1 + {1.9, -2.0, 2, -1}, + // 1.9 * -2.0 + 4 => 0 + {1.9, -2.0, 4, 0}, + }; + for (const auto& test_case : test_cases) { + EXPECT_EQ(test_case.expected_value.has_value() + ? CreateHistogramRequest(/*bucket=*/123, + test_case.expected_value.value()) + : nullptr, + FillInPrivateAggregationRequest( + CreateForEventRequestWithValueObject( + /*bucket=*/123, + CreateSignalValue(test_case.scale, test_case.offset), + /*event_type=*/kReservedAlways), + /*winning_bid=*/test_case.base, + /*highest_scoring_other_bid=*/0, + /*reject_reason=*/absl::nullopt, /*is_winner=*/true)); + } +} + +} // namespace content
diff --git a/content/browser/loader/url_loader_throttles.cc b/content/browser/loader/url_loader_throttles.cc index 714828e..3ee50720 100644 --- a/content/browser/loader/url_loader_throttles.cc +++ b/content/browser/loader/url_loader_throttles.cc
@@ -11,6 +11,7 @@ #include "content/browser/client_hints/critical_client_hints_throttle.h" #include "content/browser/origin_trials/critical_origin_trials_throttle.h" #include "content/browser/reduce_accept_language/reduce_accept_language_throttle.h" +#include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/webid/webid_utils.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/client_hints_controller_delegate.h" @@ -28,6 +29,7 @@ #include "services/network/public/cpp/resource_request.h" #include "services/network/public/mojom/parsed_headers.mojom-forward.h" #include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" namespace content { @@ -76,9 +78,12 @@ } } + // Handle Critical Origin Trial headers if the context supports it and this + // is a navigation request. OriginTrialsControllerDelegate* origin_trials_delegate = browser_context->GetOriginTrialsControllerDelegate(); - if (origin_trials_delegate) { + if (origin_trials_delegate && + CriticalOriginTrialsThrottle::IsNavigationRequest(request)) { // Critical Origin Trials may restart the network request, so only allow on // safe methods, since the origin trials in question may change request // headers or other aspects of the network request. We want to avoid servers @@ -86,8 +91,22 @@ // headers are changed, any idempotent method is still allowed to make // further changes to server state. if (net::HttpUtil::IsMethodSafe(request.method) && origin_trials_delegate) { + absl::optional<url::Origin> top_origin = absl::nullopt; + // frame_tree_node_id may be invalid if we are loading the first frame + // of the tab. + if (frame_tree_node_id != FrameTreeNode::kFrameTreeNodeInvalidId) { + FrameTreeNode* frame_tree_node = + FrameTreeNode::GloballyFindByID(frame_tree_node_id); + // The throttle should only use a top-frame origin for partitioning if + // this is not the outermost frame. + if (frame_tree_node->GetParentOrOuterDocument()) { + top_origin = frame_tree_node->GetParentOrOuterDocument() + ->GetOutermostMainFrame() + ->GetLastCommittedOrigin(); + } + } throttles.push_back(std::make_unique<CriticalOriginTrialsThrottle>( - *origin_trials_delegate)); + *origin_trials_delegate, std::move(top_origin))); } }
diff --git a/content/browser/media/capture/aura_window_to_mojo_device_adapter.cc b/content/browser/media/capture/aura_window_to_mojo_device_adapter.cc index d5de2dc..61c2d1e 100644 --- a/content/browser/media/capture/aura_window_to_mojo_device_adapter.cc +++ b/content/browser/media/capture/aura_window_to_mojo_device_adapter.cc
@@ -60,7 +60,7 @@ void AuraWindowToMojoDeviceAdapter::SetPhotoOptions( media::mojom::PhotoSettingsPtr settings, SetPhotoOptionsCallback callback) { - media::mojom::ImageCapture::SetOptionsCallback scoped_callback = + media::mojom::ImageCapture::SetPhotoOptionsCallback scoped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( media::BindToCurrentLoop(std::move(callback)), false); device_->SetPhotoOptions(std::move(settings), std::move(scoped_callback));
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc index a1d0ee0..e11d358a 100644 --- a/content/browser/media/encrypted_media_browsertest.cc +++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -17,6 +17,7 @@ #include "media/base/media.h" #include "media/base/media_switches.h" #include "media/base/test_data_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "media/mojo/buildflags.h" @@ -55,13 +56,6 @@ namespace content { -// Available key systems. -const char kClearKeyKeySystem[] = "org.w3.clearkey"; - -#if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL) -const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; -#endif - // EME-specific test results and errors. const char16_t kEmeKeyError[] = u"KEYERROR"; const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR"; @@ -193,23 +187,23 @@ INSTANTIATE_TEST_SUITE_P(SRC_ClearKey, EncryptedMediaTest, - Combine(Values(kClearKeyKeySystem), + Combine(Values(media::kClearKeyKeySystem), Values(SrcType::SRC))); INSTANTIATE_TEST_SUITE_P(MSE_ClearKey, EncryptedMediaTest, - Combine(Values(kClearKeyKeySystem), + Combine(Values(media::kClearKeyKeySystem), Values(SrcType::MSE))); #if defined(SUPPORTS_EXTERNAL_CLEAR_KEY_IN_CONTENT_SHELL) INSTANTIATE_TEST_SUITE_P(SRC_ExternalClearKey, EncryptedMediaTest, - Combine(Values(kExternalClearKeyKeySystem), + Combine(Values(media::kExternalClearKeyKeySystem), Values(SrcType::SRC))); INSTANTIATE_TEST_SUITE_P(MSE_ExternalClearKey, EncryptedMediaTest, - Combine(Values(kExternalClearKeyKeySystem), + Combine(Values(media::kExternalClearKeyKeySystem), Values(SrcType::MSE))); #endif
diff --git a/content/browser/origin_trials/critical_origin_trials_throttle.cc b/content/browser/origin_trials/critical_origin_trials_throttle.cc index 72fddd823..e4462975 100644 --- a/content/browser/origin_trials/critical_origin_trials_throttle.cc +++ b/content/browser/origin_trials/critical_origin_trials_throttle.cc
@@ -20,9 +20,20 @@ using blink::mojom::ResourceType; +// static +bool CriticalOriginTrialsThrottle::IsNavigationRequest( + const network::ResourceRequest& request) { + ResourceType request_resource_type = + static_cast<ResourceType>(request.resource_type); + return request_resource_type == ResourceType::kMainFrame || + request_resource_type == ResourceType::kSubFrame; +} + CriticalOriginTrialsThrottle::CriticalOriginTrialsThrottle( - OriginTrialsControllerDelegate& origin_trials_delegate) - : origin_trials_delegate_(origin_trials_delegate) {} + OriginTrialsControllerDelegate& origin_trials_delegate, + absl::optional<url::Origin> top_frame_origin) + : origin_trials_delegate_(origin_trials_delegate), + top_frame_origin_(std::move(top_frame_origin)) {} CriticalOriginTrialsThrottle::~CriticalOriginTrialsThrottle() = default; @@ -30,13 +41,9 @@ network::ResourceRequest* request, bool* defer) { // Right now, Persistent Origin Trials are only supported on navigation - // requests, but this throttle is called for all network loads. Until support - // is implemented for other request types, we need to only intercept - // navigation requests. - ResourceType request_resource_type = - static_cast<ResourceType>(request->resource_type); - is_navigation_request_ = request_resource_type == ResourceType::kMainFrame || - request_resource_type == ResourceType::kSubFrame; + // requests. Until support is implemented for other request types, we need to + // only intercept navigation requests. + is_navigation_request_ = IsNavigationRequest(*request); if (is_navigation_request_) SetPreRequestFields(request->url); @@ -113,8 +120,10 @@ if (needs_restart) { // Persist the trials that were set, so we can try again. + url::Origin partition_origin = top_frame_origin_.value_or(request_origin); origin_trials_delegate_->PersistTrialsFromTokens( - request_origin, origin_trial_tokens, base::Time::Now()); + request_origin, partition_origin, origin_trial_tokens, + base::Time::Now()); restarted_origins_.insert(request_origin); delegate_->RestartWithURLResetAndFlags(0); } @@ -123,9 +132,12 @@ void CriticalOriginTrialsThrottle::SetPreRequestFields( const GURL& request_url) { request_url_ = request_url; + url::Origin partition_origin = + top_frame_origin_.value_or(url::Origin::Create(request_url_)); original_persisted_trials_ = origin_trials_delegate_->GetPersistedTrialsForOrigin( - url::Origin::Create(request_url_), base::Time::Now()); + url::Origin::Create(request_url_), partition_origin, + base::Time::Now()); } } // namespace content
diff --git a/content/browser/origin_trials/critical_origin_trials_throttle.h b/content/browser/origin_trials/critical_origin_trials_throttle.h index 66649586..f044206f 100644 --- a/content/browser/origin_trials/critical_origin_trials_throttle.h +++ b/content/browser/origin_trials/critical_origin_trials_throttle.h
@@ -9,6 +9,7 @@ #include "base/memory/raw_ref.h" #include "content/common/content_export.h" #include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "url/gurl.h" @@ -19,8 +20,15 @@ class CONTENT_EXPORT CriticalOriginTrialsThrottle : public blink::URLLoaderThrottle { public: - explicit CriticalOriginTrialsThrottle( - OriginTrialsControllerDelegate& origin_trials_delegate); + // Create a throttle using the passed |origin_trials_delegate| for token + // validation and the |top_frame_origin| as the partition origin. An empty + // optional should be passed for |top_frame_origin| if the request is a main + // frame navigation request. + // TODO(https://crbug.com/1410180): Switch |top_frame_origin| to use Cookie + // partitioning. + CriticalOriginTrialsThrottle( + OriginTrialsControllerDelegate& origin_trials_delegate, + absl::optional<url::Origin> top_frame_origin); ~CriticalOriginTrialsThrottle() override; @@ -39,12 +47,19 @@ net::HttpRequestHeaders* modified_request_headers, net::HttpRequestHeaders* modified_cors_exempt_request_headers) override; + // This throttle only handles navigation requests. Use this method to + // determine if the throttle will handle the passed-in |request| before + // constructing a throttle. + static bool IsNavigationRequest(const network::ResourceRequest& request); + private: // The delegate is owned by the BrowserContext, and is expected to outlive // this throttle. raw_ref<OriginTrialsControllerDelegate, DanglingUntriaged> origin_trials_delegate_; + absl::optional<url::Origin> top_frame_origin_; + bool is_navigation_request_ = false; // Ensure that there's only one restart per origin.
diff --git a/content/browser/origin_trials/critical_origin_trials_throttle_unittest.cc b/content/browser/origin_trials/critical_origin_trials_throttle_unittest.cc index 49b515d..469f34f 100644 --- a/content/browser/origin_trials/critical_origin_trials_throttle_unittest.cc +++ b/content/browser/origin_trials/critical_origin_trials_throttle_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <string> +#include <utility> #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" @@ -59,6 +60,7 @@ base::flat_set<std::string> GetPersistedTrialsForOrigin( const url::Origin& origin, + const url::Origin& top_level_origin, base::Time current_time) override { get_persisted_trials_count_++; const auto& it = persisted_trials_.find(origin); @@ -70,6 +72,7 @@ } bool IsTrialPersistedForOrigin(const url::Origin& origin, + const url::Origin& top_level_origin, const base::StringPiece trial_name, const base::Time current_time) override { is_trial_persisted_count_++; @@ -79,6 +82,7 @@ void PersistTrialsFromTokens( const url::Origin& origin, + const url::Origin& top_level_origin, const base::span<const std::string> header_tokens, const base::Time current_time) override { persist_trials_from_tokens_count_++; @@ -111,7 +115,9 @@ class CriticalOriginTrialsThrottleTest : public ::testing::Test { public: CriticalOriginTrialsThrottleTest() - : origin_trials_delegate_(), throttle_(origin_trials_delegate_) { + : origin_trials_delegate_(), + throttle_(origin_trials_delegate_, + url::Origin::Create(GURL(kExampleURL))) { throttle_.set_delegate(&throttle_delegate_); }
diff --git a/content/browser/preloading/prefetch/prefetch_service.cc b/content/browser/preloading/prefetch/prefetch_service.cc index 5d0e4d5..415a049 100644 --- a/content/browser/preloading/prefetch/prefetch_service.cc +++ b/content/browser/preloading/prefetch/prefetch_service.cc
@@ -251,12 +251,22 @@ DCHECK(prefetch_container); auto prefetch_container_key = prefetch_container->GetPrefetchContainerKey(); - // If the user has disabled pre* actions, then don't prefetch. - if (delegate_ && !delegate_->IsSomePreloadingEnabled()) { - return; - } - if (delegate_) { + // If pre* actions are disabled then don't prefetch. + switch (delegate_->IsSomePreloadingEnabled()) { + case PreloadingEligibility::kEligible: + break; + case PreloadingEligibility::kDataSaverEnabled: + OnGotEligibilityResult( + prefetch_container, false, + PrefetchStatus::kPrefetchNotEligibleDataSaverEnabled); + return; + default: + // TODO(crbug.com/1382315): determine if kPreloadingDisabled or + // kBatterySaverEnabled should be handled. + return; + } + const auto& prefetch_type = prefetch_container->GetPrefetchType(); if (prefetch_type.IsProxyRequired() && !prefetch_type.IsProxyBypassedForTesting()) { @@ -317,13 +327,6 @@ return; } - if (GetContentClient()->browser()->IsDataSaverEnabled(browser_context_)) { - std::move(result_callback) - .Run(prefetch_container, false, - PrefetchStatus::kPrefetchNotEligibleDataSaverEnabled); - return; - } - // While a registry-controlled domain could still resolve to a non-publicly // routable IP, this allows hosts which are very unlikely to work via the // proxy to be discarded immediately.
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index 7b79c05..731e2d26 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -97,7 +97,7 @@ ON_CALL(*this, DisableDecoysBasedOnUserSettings) .WillByDefault(testing::Return(false)); ON_CALL(*this, IsSomePreloadingEnabled) - .WillByDefault(testing::Return(true)); + .WillByDefault(testing::Return(PreloadingEligibility::kEligible)); ON_CALL(*this, IsExtendedPreloadingEnabled) .WillByDefault(testing::Return(false)); ON_CALL(*this, IsDomainInPrefetchAllowList(testing::_)) @@ -127,7 +127,7 @@ MOCK_METHOD(bool, IsOriginOutsideRetryAfterWindow, (const GURL&), (override)); MOCK_METHOD(void, ClearData, (), (override)); MOCK_METHOD(bool, DisableDecoysBasedOnUserSettings, (), (override)); - MOCK_METHOD(bool, IsSomePreloadingEnabled, (), (override)); + MOCK_METHOD(PreloadingEligibility, IsSomePreloadingEnabled, (), (override)); MOCK_METHOD(bool, IsExtendedPreloadingEnabled, (), (override)); MOCK_METHOD(bool, IsDomainInPrefetchAllowList, (const GURL&), (override)); MOCK_METHOD(void, OnPrefetchLikely, (WebContents*), (override)); @@ -150,25 +150,12 @@ EXPECT_EQ(this, SetBrowserClientForTesting(old_browser_client_)); } - void SetDataSaverEnabledForTesting(bool data_saver_enabled) { - data_saver_enabled_ = data_saver_enabled; - } - // ContentBrowserClient. std::unique_ptr<PrefetchServiceDelegate> CreatePrefetchServiceDelegate( BrowserContext*) override { return std::move(mock_prefetch_service_delegate_); } - bool IsDataSaverEnabled(BrowserContext*) override { - return data_saver_enabled_; - } - - void OverrideWebkitPrefs(WebContents*, - blink::web_pref::WebPreferences* prefs) override { - prefs->data_saver_enabled = data_saver_enabled_; - } - void UseOffTheRecordContextForStoragePartition(bool use) { use_off_the_record_context_for_storage_paritition_ = use; } @@ -193,7 +180,6 @@ // `use_off_the_record_context_for_storage_paritition_` is set to true. std::unique_ptr<TestBrowserContext> off_the_record_context_; bool use_off_the_record_context_for_storage_paritition_{false}; - bool data_saver_enabled_{false}; }; // This is only used to test the proxy lookup. @@ -725,7 +711,7 @@ // prefetch at all. EXPECT_CALL(*mock_prefetch_service_delegate, IsSomePreloadingEnabled) .Times(1) - .WillOnce(testing::Return(false)); + .WillOnce(testing::Return(PreloadingEligibility::kPreloadingDisabled)); MakePrefetchService(std::move(mock_prefetch_service_delegate)); @@ -1208,9 +1194,17 @@ TEST_F(PrefetchServiceTest, NotEligibleDataSaverEnabled) { base::HistogramTester histogram_tester; - MakePrefetchService( - std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); - test_content_browser_client()->SetDataSaverEnabledForTesting(true); + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>( + /*num_on_prefetch_likely_calls=*/0); + + // When data saver is enabled, then |PrefetchService| doesn't start the + // prefetch at all. + EXPECT_CALL(*mock_prefetch_service_delegate, IsSomePreloadingEnabled) + .Times(1) + .WillOnce(testing::Return(PreloadingEligibility::kDataSaverEnabled)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); MakePrefetchOnMainFrame( GURL("https://example.com"),
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index adc14af..f4fce45 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -6625,10 +6625,6 @@ public testing::WithParamInterface<BackForwardCacheType> { public: PrerenderWithBackForwardCacheBrowserTest() { - // Set up the common params for the BFCache. - base::FieldTrialParams feature_params; - feature_params["TimeToLiveInBackForwardCacheInSeconds"] = "3600"; - // Allow the BFCache for all devices regardless of their memory. std::vector<base::test::FeatureRef> disabled_features{ features::kBackForwardCacheMemoryControls}; @@ -6639,7 +6635,10 @@ break; case BackForwardCacheType::kEnabled: feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, feature_params}}, disabled_features); + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, + disabled_features); break; } }
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 799ef74..4b99025 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -557,27 +557,20 @@ base::TimeDelta BackForwardCacheImpl::GetTimeToLiveInBackForwardCache() { // We use the following order of priority if multiple values exist: - // - The programmatical value set in params. Used in specific tests. - // The TTL set in BackForwardCacheTimeToLiveControl takes precedence over - // the TTL set in the main BackForwardCache feature if both are present. + // - The TTL set in `kBackForwardCacheTimeToLiveControl` takes precedence over + // the default value. // - Infinite if kBackForwardCacheNoTimeEviction is enabled. // - Default value otherwise, kDefaultTimeToLiveInBackForwardCacheInSeconds. - if (base::FeatureList::IsEnabled(kBackForwardCacheTimeToLiveControl)) { + if (base::FeatureList::IsEnabled( + features::kBackForwardCacheTimeToLiveControl)) { absl::optional<int> time_to_live = GetFieldTrialParamByFeatureAsOptionalInt( - kBackForwardCacheTimeToLiveControl, "time_to_live_seconds"); + features::kBackForwardCacheTimeToLiveControl, "time_to_live_seconds"); if (time_to_live.has_value()) { return base::Seconds(time_to_live.value()); } } - absl::optional<int> old_time_to_live = - GetFieldTrialParamByFeatureAsOptionalInt( - features::kBackForwardCache, "TimeToLiveInBackForwardCacheInSeconds"); - if (old_time_to_live.has_value()) { - return base::Seconds(old_time_to_live.value()); - } - if (base::FeatureList::IsEnabled(kBackForwardCacheNoTimeEviction)) { return base::TimeDelta::Max(); }
diff --git a/content/browser/renderer_host/back_forward_cache_impl.h b/content/browser/renderer_host/back_forward_cache_impl.h index e3f7301..d6dffd3 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.h +++ b/content/browser/renderer_host/back_forward_cache_impl.h
@@ -64,13 +64,6 @@ "CacheControlNoStoreEnterBackForwardCache", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables controlling the time to live for pages in the backforward cache. -// The time to live is defined by the param 'time_to_live_seconds'; if this -// param is not specified then this feature is ignored and the default is used. -BASE_FEATURE(kBackForwardCacheTimeToLiveControl, - "BackForwardCacheTimeToLiveControl", - base::FEATURE_DISABLED_BY_DEFAULT); - CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheSize); CONTENT_EXPORT extern const base::FeatureParam<int> kBackForwardCacheSizeCacheSize;
diff --git a/content/browser/renderer_host/browsing_context_group_swap_browsertest.cc b/content/browser/renderer_host/browsing_context_group_swap_browsertest.cc index f3bd1fa..4823644 100644 --- a/content/browser/renderer_host/browsing_context_group_swap_browsertest.cc +++ b/content/browser/renderer_host/browsing_context_group_swap_browsertest.cc
@@ -36,8 +36,9 @@ // Enable BackForwardCache: if (IsBackForwardCacheEnabled()) { feature_list_for_back_forward_cache_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); } else {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 764575b7..e7258d8 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -88,8 +88,6 @@ namespace { -static const char* kBrowser = "Browser"; - // NOINLINE to make sure crashes use this for magic signature. NOINLINE void FatalSurfaceFailure() { LOG(FATAL) << "Fatal surface initialization failure"; @@ -955,7 +953,6 @@ BrowserGpuChannelHostFactory::instance()->GetGpuMemoryBufferManager(); params.pipes.compositor_frame_sink_associated_remote = std::move(sink_remote); params.pipes.client_receiver = std::move(client_receiver); - params.client_name = kBrowser; auto layer_tree_frame_sink = std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( std::move(context_provider), nullptr, ¶ms);
diff --git a/content/browser/renderer_host/document_user_data_browsertest.cc b/content/browser/renderer_host/document_user_data_browsertest.cc index f929e8a..3af418cd 100644 --- a/content/browser/renderer_host/document_user_data_browsertest.cc +++ b/content/browser/renderer_host/document_user_data_browsertest.cc
@@ -969,11 +969,12 @@ public: DocumentUserDataWithBackForwardCacheTest() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, // Set a very long TTL before expiration (longer than the test // timeout) so tests that are expecting deletion don't pass when // they shouldn't. - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc deleted file mode 100644 index f121022..0000000 --- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win_unittest.cc +++ /dev/null
@@ -1,241 +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 "content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h" - -#include <string> -#include <utility> -#include <vector> - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/raw_ptr.h" -#include "base/path_service.h" -#include "base/task/sequenced_task_runner.h" -#include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "content/public/common/content_features.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h" - -namespace content { - -namespace { - -struct FontExpectation { - const char font_name[64]; - uint16_t ttc_index; -}; - -constexpr FontExpectation kExpectedTestFonts[] = {{"CambriaMath", 1}, - {"Ming-Lt-HKSCS-ExtB", 2}, - {"NSimSun", 1}, - {"calibri-bolditalic", 0}}; - -constexpr base::TimeDelta kTestingTimeout = base::Seconds(10); - -class DWriteFontLookupTableBuilderTest : public testing::Test { - public: - DWriteFontLookupTableBuilderTest() { - feature_list_.InitAndEnableFeature(features::kFontSrcLocalMatching); - } - - void SetUp() override { - font_lookup_table_builder_ = DWriteFontLookupTableBuilder::GetInstance(); - font_lookup_table_builder_->OverrideDWriteVersionChecksForTesting(); - font_lookup_table_builder_->ResetLookupTableForTesting(); - bool temp_dir_created = scoped_temp_dir_.CreateUniqueTempDir(); - ASSERT_TRUE(temp_dir_created); - font_lookup_table_builder_->SetCacheDirectoryForTesting( - scoped_temp_dir_.GetPath()); - } - - void TearDown() override { - font_lookup_table_builder_->ResetStateForTesting(); - } - - void TestMatchFonts() { - base::ReadOnlySharedMemoryRegion font_table_memory = - font_lookup_table_builder_->DuplicateMemoryRegion(); - blink::FontTableMatcher font_table_matcher(font_table_memory.Map()); - - for (auto& test_font_name_index : kExpectedTestFonts) { - absl::optional<blink::FontTableMatcher::MatchResult> match_result = - font_table_matcher.MatchName(test_font_name_index.font_name); - ASSERT_TRUE(match_result) << "No font matched for font name: " - << test_font_name_index.font_name; - base::File unique_font_file( - base::FilePath::FromUTF8Unsafe(match_result->font_path), - base::File::FLAG_OPEN | base::File::FLAG_READ); - ASSERT_TRUE(unique_font_file.IsValid()); - ASSERT_GT(unique_font_file.GetLength(), 0); - ASSERT_EQ(test_font_name_index.ttc_index, match_result->ttc_index); - } - } - - protected: - base::test::ScopedFeatureList feature_list_; - base::test::TaskEnvironment task_environment_; - raw_ptr<DWriteFontLookupTableBuilder> font_lookup_table_builder_; - base::ScopedTempDir scoped_temp_dir_; -}; - -class DWriteFontLookupTableBuilderTimeoutTest - : public DWriteFontLookupTableBuilderTest, - public ::testing::WithParamInterface< - DWriteFontLookupTableBuilder::SlowDownMode> {}; - -} // namespace - -// Run a test similar to DWriteFontProxyImplUnitTest, TestFindUniqueFont but -// without going through Mojo and running it on the DWRiteFontLookupTableBuilder -// class directly. -TEST_F(DWriteFontLookupTableBuilderTest, TestFindUniqueFontDirect) { - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - bool test_callback_executed = false; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting( - [this, &test_callback_executed](base::ReadOnlySharedMemoryRegion) { - TestMatchFonts(); - test_callback_executed = true; - })); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); -} - -TEST_P(DWriteFontLookupTableBuilderTimeoutTest, TestTimeout) { - font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout( - GetParam(), kTestingTimeout); - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - bool test_callback_executed = false; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting([this, &test_callback_executed]( - base::ReadOnlySharedMemoryRegion - font_table_memory) { - blink::FontTableMatcher font_table_matcher(font_table_memory.Map()); - - for (auto& test_font_name_index : kExpectedTestFonts) { - absl::optional<blink::FontTableMatcher::MatchResult> match_result = - font_table_matcher.MatchName(test_font_name_index.font_name); - ASSERT_TRUE(!match_result); - } - if (GetParam() == - DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask) - font_lookup_table_builder_->ResumeFromHangForTesting(); - test_callback_executed = true; - })); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); -} - -INSTANTIATE_TEST_SUITE_P( - All, - DWriteFontLookupTableBuilderTimeoutTest, - ::testing::Values( - DWriteFontLookupTableBuilder::SlowDownMode::kDelayEachTask, - DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask)); - -TEST_F(DWriteFontLookupTableBuilderTest, TestReadyEarly) { - font_lookup_table_builder_->SetSlowDownIndexingForTestingWithTimeout( - DWriteFontLookupTableBuilder::SlowDownMode::kHangOneTask, - kTestingTimeout); - - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - bool test_callback_executed = false; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting( - [this, &test_callback_executed](base::ReadOnlySharedMemoryRegion) { - ASSERT_TRUE(font_lookup_table_builder_->FontUniqueNameTableReady()); - test_callback_executed = true; - })); - ASSERT_FALSE(font_lookup_table_builder_->FontUniqueNameTableReady()); - font_lookup_table_builder_->ResumeFromHangForTesting(); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); -} - -TEST_F(DWriteFontLookupTableBuilderTest, RepeatedScheduling) { - for (unsigned i = 0; i < 3; ++i) { - font_lookup_table_builder_->ResetLookupTableForTesting(); - font_lookup_table_builder_->SetCachingEnabledForTesting(false); - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - bool test_callback_executed = false; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting( - [&test_callback_executed](base::ReadOnlySharedMemoryRegion) { - test_callback_executed = true; - })); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); - } -} - -TEST_F(DWriteFontLookupTableBuilderTest, FontsHash) { - ASSERT_GT( - font_lookup_table_builder_->ComputePersistenceHash("6.0.1.2").size(), 0u); - // Validate an empty string doesn't cause problems. - ASSERT_GT(font_lookup_table_builder_->ComputePersistenceHash("").size(), 0u); -} - -TEST_F(DWriteFontLookupTableBuilderTest, HandleCorruptCacheFile) { - // Cycle once to build cache file. - font_lookup_table_builder_->ResetLookupTableForTesting(); - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - - bool test_callback_executed = false; - base::File cache_file; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting([this, &cache_file, &test_callback_executed]( - base::ReadOnlySharedMemoryRegion) { - ASSERT_TRUE(font_lookup_table_builder_->FontUniqueNameTableReady()); - // Truncate table for testing - base::FilePath cache_file_path = scoped_temp_dir_.GetPath().Append( - FILE_PATH_LITERAL("font_unique_name_table.pb")); - // Use FLAG_WIN_EXCLUSIVE_WRITE to block file and make persisting the - // cache fail as well, use FLAG_OPEN to ensure it got created by the - // table builder implementation. - cache_file = base::File(cache_file_path, - base::File::FLAG_OPEN | base::File::FLAG_READ | - base::File::FLAG_WRITE | - base::File::FLAG_WIN_EXCLUSIVE_WRITE); - // Ensure the cache file was created in the empty scoped_temp_dir_ - // and has a non-zero length. - ASSERT_TRUE(cache_file.IsValid()); - ASSERT_TRUE(cache_file.GetLength() > 0); - ASSERT_TRUE(cache_file.SetLength(cache_file.GetLength() / 2)); - ASSERT_TRUE(cache_file.SetLength(cache_file.GetLength() * 2)); - test_callback_executed = true; - })); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); - - // Reload the cache file. - font_lookup_table_builder_->ResetLookupTableForTesting(); - font_lookup_table_builder_->SchedulePrepareFontUniqueNameTableIfNeeded(); - - test_callback_executed = false; - font_lookup_table_builder_->QueueShareMemoryRegionWhenReady( - base::SequencedTaskRunner::GetCurrentDefault(), - base::BindLambdaForTesting( - [this, &test_callback_executed](base::ReadOnlySharedMemoryRegion) { - TestMatchFonts(); - test_callback_executed = true; - })); - - task_environment_.RunUntilIdle(); - ASSERT_TRUE(test_callback_executed); - - // Ensure that the table is still valid even though persisting has failed - // due to the exclusive write lock on the file. - ASSERT_TRUE(font_lookup_table_builder_->FontUniqueNameTableReady()); -} - -} // namespace content
diff --git a/content/browser/renderer_host/embedding_token_browsertest.cc b/content/browser/renderer_host/embedding_token_browsertest.cc index 4861712..1ddc3f85 100644 --- a/content/browser/renderer_host/embedding_token_browsertest.cc +++ b/content/browser/renderer_host/embedding_token_browsertest.cc
@@ -26,11 +26,12 @@ void SetUpCommandLine(base::CommandLine* command_line) override { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, // Set a very long TTL before expiration (longer than the test // timeout) so tests that are expecting deletion don't pass when // they shouldn't. - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls});
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc index ec88cbb..f2ccd9d 100644 --- a/content/browser/renderer_host/frame_tree_browsertest.cc +++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -1650,13 +1650,13 @@ const blink::StorageKey third_party = blink::StorageKey::CreateWithOptionalNonce( origin, net::SchemefulSite(GURL("https://notexample.com")), nullptr, - blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit::kCrossSite); const url::Origin opaque_origin = url::Origin(); const blink::StorageKey opaque_first_party = blink::StorageKey(opaque_origin); const blink::StorageKey opaque_third_party = blink::StorageKey::CreateWithOptionalNonce( opaque_origin, net::SchemefulSite(GURL("https://notexample.com")), - nullptr, blink::mojom::AncestorChainBit::kSameSite); + nullptr, blink::mojom::AncestorChainBit::kCrossSite); EXPECT_NE(first_party, third_party); EXPECT_NE(opaque_first_party, opaque_third_party); FrameTree& frame_tree = static_cast<WebContentsImpl*>(shell()->web_contents()) @@ -1684,14 +1684,14 @@ blink::StorageKey::CreateWithOptionalNonce( url::Origin::Create(GURL("https://example.com")), net::SchemefulSite(GURL("https://notexample.com")), nullptr, - blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit::kCrossSite); const blink::StorageKey dt_first_party = blink::StorageKey::CreateFromStringForTesting("https://example.com"); const blink::StorageKey random_third_party = blink::StorageKey::CreateWithOptionalNonce( url::Origin::Create(GURL("https://otherexample.com")), net::SchemefulSite(GURL("https://notexample.com")), nullptr, - blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit::kCrossSite); EXPECT_NE(dt_third_party, dt_first_party); // Load a page without the origin trial token.
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc index 73bc88e..5026267 100644 --- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc +++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -92,10 +92,6 @@ #if BUILDFLAG(ENABLE_SCREEN_CAPTURE) #if BUILDFLAG(IS_MAC) -BASE_FEATURE(kDesktopCaptureMacV2, - "DesktopCaptureMacV2", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kScreenCaptureKitMac, "ScreenCaptureKitMac", base::FEATURE_DISABLED_BY_DEFAULT); @@ -208,9 +204,8 @@ if ((device_out = CreateScreenCaptureKitDeviceMac(desktop_id))) return kScreenCaptureKitDeviceMac; } - if ((base::FeatureList::IsEnabled(kDesktopCaptureMacV2))) { - if ((device_out = CreateDesktopCaptureDeviceMac(desktop_id))) - return kDesktopCaptureDeviceMac; + if ((device_out = CreateDesktopCaptureDeviceMac(desktop_id))) { + return kDesktopCaptureDeviceMac; } #endif if ((device_out = DesktopCaptureDevice::Create(desktop_id))) {
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index a9a8df80..6b76f86 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -44,8 +44,8 @@ // TODO(https://crbug.com/1406985): Investigate whether there's a better way // to accomplish this (without using UnguessableToken::Deserialize). static const base::UnguessableToken fake_session_id( - base::UnguessableToken::Deserialize2(0xFFFFFFFFFFFFFFFFU, - 0xFFFFFFFFFFFFFFFFU) + base::UnguessableToken::Deserialize(0xFFFFFFFFFFFFFFFFU, + 0xFFFFFFFFFFFFFFFFU) .value()); return fake_session_id; }
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc index 440747c..4015546a 100644 --- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -18619,8 +18619,9 @@ protected: void SetUp() override { feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); NavigationControllerBrowserTest::SetUp();
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 61b47ad..76c8470 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -1043,6 +1043,7 @@ // that correspond to persistent origin trials, provided the tokens are valid. void PersistOriginTrialsFromHeaders( const url::Origin& origin, + const url::Origin& partition_origin, const network::mojom::URLResponseHead* response, BrowserContext* browser_context) { if (!base::FeatureList::IsEnabled(features::kPersistentOriginTrials)) @@ -1065,8 +1066,8 @@ std::vector<std::string> tokens = GetOriginTrialHeaderValues(response->headers.get()); - origin_trials_delegate->PersistTrialsFromTokens(origin, tokens, - base::Time::Now()); + origin_trials_delegate->PersistTrialsFromTokens(origin, partition_origin, + tokens, base::Time::Now()); } } // namespace @@ -1477,6 +1478,7 @@ render_frame_host->ComputeTopFrameOrigin(origin); // If the `nonce` is set the `top_level_site` must be the same as `origin` and // the `ancestor_chain_bit` must be kSameSite. + // TODO(https://crbug.com/1410254): Cleanup this logic. if (nonce) { navigation_request->commit_params_->storage_key = blink::StorageKey::CreateWithOptionalNonce( @@ -1487,7 +1489,8 @@ navigation_request->commit_params_->storage_key = blink::StorageKey::CreateWithOptionalNonce( origin, top_level_site, nullptr, - (render_frame_host->ComputeSiteForCookies().IsNull() && + ((render_frame_host->ComputeSiteForCookies().IsNull() || + net::SchemefulSite(origin) != top_level_site) && !top_level_site.opaque()) ? blink::mojom::AncestorChainBit::kCrossSite : blink::mojom::AncestorChainBit::kSameSite); @@ -5302,8 +5305,19 @@ common_params_->url, client_hints_delegate, response(), commit_params_->enabled_client_hints, frame_tree_node_); } + // Navigation requests should use the new origin as the partition origin + // except if embedded in an outer frame. + url::Origin partition_origin = origin; + bool is_top_level = frame_tree_node()->GetParentOrOuterDocument() == nullptr; + if (!is_top_level) { + partition_origin = frame_tree_node() + ->GetParentOrOuterDocument() + ->GetOutermostMainFrame() + ->GetLastCommittedOrigin(); + } - PersistOriginTrialsFromHeaders(origin, response(), browser_context); + PersistOriginTrialsFromHeaders(origin, partition_origin, response(), + browser_context); // Update the reduced accept-language to commit if it's empty, and stop // persisting the accepted language if the final response do not have a valid
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc index 63ea2f2f..57650a9e 100644 --- a/content/browser/renderer_host/navigation_request_unittest.cc +++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -969,12 +969,14 @@ void PersistTrialsFromTokens( const url::Origin& origin, + const url::Origin& partition_origin, const base::span<const std::string> header_tokens, const base::Time current_time) override { persisted_tokens_[origin] = std::vector<std::string>(header_tokens.begin(), header_tokens.end()); } bool IsTrialPersistedForOrigin(const url::Origin& origin, + const url::Origin& partition_origin, const base::StringPiece trial_name, const base::Time current_time) override { DCHECK(false) << "Method not implemented for test."; @@ -983,6 +985,7 @@ base::flat_set<std::string> GetPersistedTrialsForOrigin( const url::Origin& origin, + const url::Origin& partition_origin, base::Time current_time) override { DCHECK(false) << "Method not implemented for test."; return base::flat_set<std::string>();
diff --git a/content/browser/renderer_host/page_impl_browsertest.cc b/content/browser/renderer_host/page_impl_browsertest.cc index 506a57b4..8f471ab8 100644 --- a/content/browser/renderer_host/page_impl_browsertest.cc +++ b/content/browser/renderer_host/page_impl_browsertest.cc
@@ -528,11 +528,12 @@ public: PageImplWithBackForwardCacheTest() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, // Set a very long TTL before expiration (longer than the test // timeout) so tests that are expecting deletion don't pass when // they shouldn't. - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/renderer_host/pending_beacon_browsertest.cc b/content/browser/renderer_host/pending_beacon_browsertest.cc index d9520bf8..73c1c37 100644 --- a/content/browser/renderer_host/pending_beacon_browsertest.cc +++ b/content/browser/renderer_host/pending_beacon_browsertest.cc
@@ -454,8 +454,9 @@ {{"PendingBeaconMaxBackgroundTimeoutInMs", "60000"}, // Don't force sending out beacons on pagehide. {"send_on_navigation", "false"}}}, - {features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "5"}}}, + {features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "5"}}}, // Forces BFCache to work in low memory device. {features::kBackForwardCacheMemoryControls, {{"memory_threshold_for_back_forward_cache_in_mb", "0"}}}}; @@ -695,8 +696,9 @@ {blink::features::kPendingBeaconAPI, {// Don't force sending out beacons on pagehide. {"send_on_navigation", "false"}}}, - {features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "60"}}}, + {features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "60"}}}, // Forces BFCache to work in low memory device. {features::kBackForwardCacheMemoryControls, {{"memory_threshold_for_back_forward_cache_in_mb", "0"}}}}; @@ -787,8 +789,9 @@ {blink::features::kPendingBeaconAPI, {{"PendingBeaconMaxBackgroundTimeoutInMs", "60000"}, {"send_on_navigation", "true"}}}, - {features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "60"}}}, + {features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "60"}}}, // Forces BFCache to work in low memory device. {features::kBackForwardCacheMemoryControls, {{"memory_threshold_for_back_forward_cache_in_mb", "0"}}}};
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 337aab0..8f6481b 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4010,6 +4010,7 @@ const base::UnguessableToken* nonce) { // If the nonce is set the `top_level_site` must be the same as // `new_rfh_origin` and the `ancestor_chain_bit` must be kSameSite. + // TODO(https://crbug.com/1410254): Cleanup this logic. if (nonce) { return blink::StorageKey::CreateWithOptionalNonce( new_rfh_origin, net::SchemefulSite(new_rfh_origin), nonce, @@ -4057,18 +4058,18 @@ // Compute the AncestorChainBit. It represents whether every ancestors are // all same-site or not. If `top_level_site` is opaque the bit must be // kSameSite as this is the default value (which won't be serialized). - auto site_for_cookies = net::SiteForCookies::FromOrigin(new_rfh_origin); blink::mojom::AncestorChainBit ancestor_chain_bit = blink::mojom::AncestorChainBit::kSameSite; if (!top_level_site.opaque()) { for (auto* ancestor : ancestor_chain) { - if (!site_for_cookies.IsFirstParty(origin(ancestor).GetURL())) { + if (top_level_site != net::SchemefulSite(origin(ancestor))) { ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite; break; } } } + // TODO(https://crbug.com/1410254): Cleanup this logic. return blink::StorageKey::CreateWithOptionalNonce( new_rfh_origin, top_level_site, nullptr, ancestor_chain_bit); }
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc index 1c91262..b32226f 100644 --- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -7116,8 +7116,9 @@ public: RenderFrameHostImplBrowserTestWithBFCache() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc index 53d6f7b..b9b3356 100644 --- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc +++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -3582,9 +3582,10 @@ public: RenderFrameHostManagerTestWithBackForwardCache() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, { - {"TimeToLiveInBackForwardCacheInSeconds", "3600"}, + {"time_to_live_seconds", "3600"}, }}}, // Allow BackForwardCache for all devices regardless of their memory. /*disabled_features=*/{features::kBackForwardCacheMemoryControls});
diff --git a/content/browser/scheduler/browser_task_executor.cc b/content/browser/scheduler/browser_task_executor.cc index 15c5b18..6006db17 100644 --- a/content/browser/scheduler/browser_task_executor.cc +++ b/content/browser/scheduler/browser_task_executor.cc
@@ -13,6 +13,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/task/task_traits_extension.h" +#include "base/threading/threading_features.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" @@ -353,14 +354,18 @@ base::Thread::Options options; options.message_pump_type = base::MessagePumpType::IO; options.delegate = std::move(browser_io_thread_delegate); -// TODO(1329208): Consider doing this on Windows as well. The platform +// TODO(1329208): Align Win ThreadType with other platforms. The platform // discrepancy stems from organic evolution of the thread priorities on each // platform and while it might make sense not to bump the priority of the IO // thread per Windows' priority boosts capabilities on MessagePumpForIO, this // should at least be aligned with what platform_thread_win.cc does for // ThreadType::kDisplayCritical (IO pumps in other processes) and it currently // does not. -#if !BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_WIN) + if (base::FeatureList::IsEnabled(base::kAboveNormalCompositingBrowserWin)) { + options.thread_type = base::ThreadType::kCompositing; + } +#else // Up the priority of the |io_thread_| as some of its IPCs relate to // display tasks. options.thread_type = base::ThreadType::kCompositing;
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 4937126..5c6bce4 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -2343,8 +2343,8 @@ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status()); // Validate checksums for each script, and ServiceWorkerVersion's one. - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - version->script_cache_map()->GetResources(&resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources = + version->script_cache_map()->GetResources(); std::set<std::string> expected_checksums; for (auto& sw_script : sw_scripts) { expected_checksums.insert(sw_script.second.second); @@ -2376,8 +2376,8 @@ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, updated_version->running_status()); // Validate updated checksums for each script, and ServiceWorkerVersion's one. - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> updated_resources; - updated_version->script_cache_map()->GetResources(&updated_resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> + updated_resources = updated_version->script_cache_map()->GetResources(); std::set<std::string> updated_expected_checksums; for (auto& sw_script : updated_sw_scripts) { updated_expected_checksums.insert(sw_script.second.second); @@ -2423,8 +2423,8 @@ EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status()); // Validate checksums for each script, and ServiceWorkerVersion's one. - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - version->script_cache_map()->GetResources(&resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources = + version->script_cache_map()->GetResources(); std::set<std::string> expected_checksums; for (auto& sw_script : sw_scripts) { expected_checksums.insert(sw_script.second.second); @@ -3676,9 +3676,10 @@ protected: ServiceWorkerBackForwardCacheAndKeepActiveFreezingBrowserTest() { feature_list_.InitWithFeaturesAndParameters( - {{{features::kBackForwardCache, - {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, - {"process_binding_strength", "NORMAL"}}}}}, + {{features::kBackForwardCache, + {{"process_binding_strength", "NORMAL"}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, {features::kBackForwardCacheMemoryControls}); }
diff --git a/content/browser/service_worker/service_worker_container_host_unittest.cc b/content/browser/service_worker/service_worker_container_host_unittest.cc index a81eff5..7f11634 100644 --- a/content/browser/service_worker/service_worker_container_host_unittest.cc +++ b/content/browser/service_worker/service_worker_container_host_unittest.cc
@@ -1263,16 +1263,13 @@ public: ServiceWorkerContainerHostTestWithBackForwardCache() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, {GetFeatureParams()}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. /*disabled_features=*/{features::kBackForwardCacheMemoryControls}); } - protected: - base::FieldTrialParams GetFeatureParams() { - return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}; - } - private: base::test::ScopedFeatureList scoped_feature_list_; };
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc index bff78eab9c..ee781050 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc +++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -33,8 +33,8 @@ ServiceWorkerInstalledScriptsSender::CreateInfoAndBind() { DCHECK_EQ(State::kNotStarted, state_); - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - owner_->script_cache_map()->GetResources(&resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources = + owner_->script_cache_map()->GetResources(); std::vector<GURL> installed_urls; for (const auto& resource : resources) { installed_urls.emplace_back(resource->url);
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc index 2e11f3c..a7d100eb 100644 --- a/content/browser/service_worker/service_worker_register_job.cc +++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -617,8 +617,8 @@ ServiceWorkerVersion* version_to_update = registration()->GetNewestVersion(); base::TimeDelta time_since_last_check = base::Time::Now() - registration()->last_update_check(); - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - version_to_update->script_cache_map()->GetResources(&resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources = + version_to_update->script_cache_map()->GetResources(); int64_t script_resource_id = version_to_update->script_cache_map()->LookupResourceId(script_url_); DCHECK_NE(script_resource_id, blink::mojom::kInvalidServiceWorkerResourceId);
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc index 97dd50b..145208d 100644 --- a/content/browser/service_worker/service_worker_registry.cc +++ b/content/browser/service_worker/service_worker_registry.cc
@@ -456,9 +456,7 @@ .ToMojoPolicyContainerPolicies() : blink::mojom::PolicyContainerPolicies::New(); - ResourceList resources; - version->script_cache_map()->GetResources(&resources); - + ResourceList resources = version->script_cache_map()->GetResources(); if (resources.empty()) { RunSoon(FROM_HERE, base::BindOnce(std::move(callback), @@ -523,9 +521,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); installing_registrations_.erase(registration->id()); if (status != blink::ServiceWorkerStatusCode::kOk && version) { - ResourceList resources; - version->script_cache_map()->GetResources(&resources); - + ResourceList resources = version->script_cache_map()->GetResources(); std::vector<int64_t> resource_ids; for (const auto& resource : resources) resource_ids.push_back(resource->resource_id);
diff --git a/content/browser/service_worker/service_worker_script_cache_map.cc b/content/browser/service_worker/service_worker_script_cache_map.cc index 0fffee9..6a14667 100644 --- a/content/browser/service_worker/service_worker_script_cache_map.cc +++ b/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -77,15 +77,14 @@ } } -void ServiceWorkerScriptCacheMap::GetResources( - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr>* resources) - const { - DCHECK(resources->empty()); - for (ResourceMap::const_iterator it = resource_map_.begin(); - it != resource_map_.end(); - ++it) { - resources->push_back(it->second->Clone()); +std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> +ServiceWorkerScriptCacheMap::GetResources() const { + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; + for (const auto& it : resource_map_) { + resources.push_back(it.second->Clone()); } + + return resources; } void ServiceWorkerScriptCacheMap::SetResources(
diff --git a/content/browser/service_worker/service_worker_script_cache_map.h b/content/browser/service_worker/service_worker_script_cache_map.h index 59cee354..2c57a7fb 100644 --- a/content/browser/service_worker/service_worker_script_cache_map.h +++ b/content/browser/service_worker/service_worker_script_cache_map.h
@@ -48,8 +48,8 @@ const std::string& status_message); // Used to retrieve the results of the initial run of a new version. - void GetResources(std::vector<storage::mojom::ServiceWorkerResourceRecordPtr>* - resources) const; + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> GetResources() + const; // Used when loading an existing version. void SetResources(
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 687803e6..6e1f91fe 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -215,8 +215,8 @@ const ServiceWorkerScriptCacheMap& script_cache_map) { const std::unique_ptr<crypto::SecureHash> checksum = crypto::SecureHash::Create(crypto::SecureHash::SHA256); - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - script_cache_map.GetResources(&resources); + std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources = + script_cache_map.GetResources(); // Sort |resources| by |sha256_checksum| value not to make the merged value // inconsistent based on the script order. std::sort(resources.begin(), resources.end(), @@ -2703,14 +2703,11 @@ case ServiceWorkerRegistration::Status::kIntact: break; case ServiceWorkerRegistration::Status::kUninstalling: - case ServiceWorkerRegistration::Status::kUninstalled: { - std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources; - script_cache_map_.GetResources(&resources); - for (auto& resource : resources) { + case ServiceWorkerRegistration::Status::kUninstalled: + for (auto& resource : script_cache_map_.GetResources()) { purgeable_resources.push_back(resource->resource_id); } break; - } } remote_reference_.reset();
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 4d2eae8f..aac6514 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -1788,7 +1788,7 @@ base::RunLoop run_loop; partition->ClearData( StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED, 0, - blink::StorageKey(source.common_info().source_origin()), now, now, + blink::StorageKey(source.common_info().reporting_origin()), now, now, run_loop.QuitClosure()); run_loop.Run(); @@ -1855,7 +1855,7 @@ auto impression = *SuitableOrigin::Deserialize( base::StringPrintf("https://imp-%d.com/", i)); auto reporter = *SuitableOrigin::Deserialize( - base::StringPrintf("https://reporter-%d.com/", i)); + base::StringPrintf("https://rep-%d.com/", i)); auto conv = *SuitableOrigin::Deserialize( base::StringPrintf("https://conv-%d.com/", i)); attribution_manager->HandleSource(SourceBuilder(now) @@ -1872,7 +1872,7 @@ EXPECT_EQ(5u, GetAttributionReportsForTesting(attribution_manager).size()); - // Match against enough Origins to delete three of the imp/conv pairs. + // Only those with a matching reporting origin should be deleted. base::RunLoop run_loop; auto filter_builder = BrowsingDataFilterBuilder::Create( BrowsingDataFilterBuilder::Mode::kPreserve); @@ -1884,16 +1884,14 @@ storage_key == blink::StorageKey::CreateFromStringForTesting( "https://conv-3.com/") || storage_key == blink::StorageKey::CreateFromStringForTesting( - "https://rep-4.com/") || - storage_key == blink::StorageKey::CreateFromStringForTesting( - "https://imp-4.com/"); + "https://rep-4.com/"); }); partition->ClearData( StoragePartition::REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED, 0, filter_builder.get(), func, nullptr, false, now, now, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_EQ(2u, GetAttributionReportsForTesting(attribution_manager).size()); + EXPECT_EQ(4u, GetAttributionReportsForTesting(attribution_manager).size()); } TEST_F(StoragePartitionImplTest, DataRemovalObserver) {
diff --git a/content/browser/tracing/background_tracing_config_unittest.cc b/content/browser/tracing/background_tracing_config_unittest.cc index dbb942e14..40cbf4e 100644 --- a/content/browser/tracing/background_tracing_config_unittest.cc +++ b/content/browser/tracing/background_tracing_config_unittest.cc
@@ -220,15 +220,14 @@ EXPECT_EQ(config->rules().size(), 1u); EXPECT_EQ(RuleToString(config->rules()[0]), "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\"," - "\"histogram_repeat\":true,\"histogram_upper_value\":2147483647," + "\"histogram_upper_value\":2147483647," "\"rule\":\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}"); config = ReadFromJSONString( "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": " "\"BENCHMARK_STARTUP\",\"configs\": [{\"rule\": " "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", " - "\"histogram_name\":\"foo\", \"histogram_value\": 1, " - "\"histogram_repeat\":false}]}"); + "\"histogram_name\":\"foo\", \"histogram_value\": 1}]}"); EXPECT_TRUE(config); EXPECT_EQ(config->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE); EXPECT_EQ(config->category_preset(), @@ -236,7 +235,7 @@ EXPECT_EQ(config->rules().size(), 1u); EXPECT_EQ(RuleToString(config->rules()[0]), "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\"," - "\"histogram_repeat\":false,\"histogram_upper_value\":2147483647," + "\"histogram_upper_value\":2147483647," "\"rule\":\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}"); config = ReadFromJSONString( @@ -252,7 +251,7 @@ EXPECT_EQ(config->rules().size(), 1u); EXPECT_EQ(RuleToString(config->rules()[0]), "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\"," - "\"histogram_repeat\":true,\"histogram_upper_value\":2,\"rule\":" + "\"histogram_upper_value\":2,\"rule\":" "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}"); config = ReadFromJSONString( @@ -260,7 +259,7 @@ "\"BENCHMARK_STARTUP\",\"configs\": [{\"rule\": " "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", " "\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, " - "\"histogram_upper_value\": 2, \"histogram_repeat\":false}]}"); + "\"histogram_upper_value\": 2}]}"); EXPECT_TRUE(config); EXPECT_EQ(config->tracing_mode(), BackgroundTracingConfig::PREEMPTIVE); EXPECT_EQ(config->category_preset(), @@ -268,7 +267,7 @@ EXPECT_EQ(config->rules().size(), 1u); EXPECT_EQ(RuleToString(config->rules()[0]), "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\"," - "\"histogram_repeat\":false,\"histogram_upper_value\":2,\"rule\":" + "\"histogram_upper_value\":2,\"rule\":" "\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}"); config = ReadFromJSONString( @@ -283,7 +282,7 @@ EXPECT_EQ(config->rules().size(), 1u); EXPECT_EQ(RuleToString(config->rules()[0]), "{\"histogram_lower_value\":1,\"histogram_name\":\"foo\"," - "\"histogram_repeat\":true,\"histogram_upper_value\":2147483647," + "\"histogram_upper_value\":2147483647," "\"rule\":\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\"}"); config = ReadFromJSONString( @@ -445,7 +444,7 @@ EXPECT_EQ( ConfigToString(config.get()), "{\"category\":\"BENCHMARK_STARTUP\",\"configs\":[{\"histogram_lower_" - "value\":1,\"histogram_name\":\"foo\",\"histogram_repeat\":true," + "value\":1,\"histogram_name\":\"foo\"," "\"histogram_upper_value\":2,\"rule\":\"MONITOR_AND_DUMP_WHEN_" "SPECIFIC_HISTOGRAM_AND_VALUE\"}],\"mode\":\"PREEMPTIVE_TRACING_" "MODE\"}"); @@ -467,7 +466,7 @@ EXPECT_EQ( ConfigToString(config.get()), "{\"category\":\"BENCHMARK_STARTUP\",\"configs\":[{\"histogram_lower_" - "value\":1,\"histogram_name\":\"foo\",\"histogram_repeat\":true," + "value\":1,\"histogram_name\":\"foo\"," "\"histogram_upper_value\":2,\"rule\":\"MONITOR_AND_DUMP_WHEN_" "SPECIFIC_HISTOGRAM_AND_VALUE\",\"trigger_delay\":10}],\"mode\":" "\"PREEMPTIVE_TRACING_MODE\"}");
diff --git a/content/browser/tracing/background_tracing_rule.cc b/content/browser/tracing/background_tracing_rule.cc index 04ebfc5..20d3d748 100644 --- a/content/browser/tracing/background_tracing_rule.cc +++ b/content/browser/tracing/background_tracing_rule.cc
@@ -41,7 +41,6 @@ const char kConfigRuleHistogramValueOldKey[] = "histogram_value"; const char kConfigRuleHistogramValue1Key[] = "histogram_lower_value"; const char kConfigRuleHistogramValue2Key[] = "histogram_upper_value"; -const char kConfigRuleHistogramRepeatKey[] = "histogram_repeat"; const char kConfigRuleTypeMonitorNamed[] = "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED"; @@ -178,12 +177,10 @@ private: HistogramRule(const std::string& histogram_name, int histogram_lower_value, - int histogram_upper_value, - bool repeat) + int histogram_upper_value) : histogram_name_(histogram_name), histogram_lower_value_(histogram_lower_value), histogram_upper_value_(histogram_upper_value), - repeat_(repeat), installed_(false) {} public: @@ -194,9 +191,6 @@ if (!histogram_name) return nullptr; - // Optional parameter, so we don't need to check if the key exists. - bool repeat = dict.FindBool(kConfigRuleHistogramRepeatKey).value_or(true); - absl::optional<int> histogram_lower_value = dict.FindInt(kConfigRuleHistogramValue1Key); if (!histogram_lower_value) { @@ -212,9 +206,8 @@ if (*histogram_lower_value > histogram_upper_value) return nullptr; - std::unique_ptr<BackgroundTracingRule> rule( - new HistogramRule(*histogram_name, *histogram_lower_value, - histogram_upper_value, repeat)); + std::unique_ptr<BackgroundTracingRule> rule(new HistogramRule( + *histogram_name, *histogram_lower_value, histogram_upper_value)); return rule; } @@ -232,7 +225,7 @@ histogram_name_, base::BindRepeating(&HistogramRule::OnHistogramChangedCallback, base::Unretained(this), histogram_lower_value_, - histogram_upper_value_, repeat_)); + histogram_upper_value_)); BackgroundTracingManagerImpl::GetInstance().AddAgentObserver(this); installed_ = true; } @@ -243,7 +236,6 @@ dict.Set(kConfigRuleHistogramNameKey, histogram_name_.c_str()); dict.Set(kConfigRuleHistogramValue1Key, histogram_lower_value_); dict.Set(kConfigRuleHistogramValue2Key, histogram_upper_value_); - dict.Set(kConfigRuleHistogramRepeatKey, repeat_); return dict; } @@ -282,7 +274,7 @@ // BackgroundTracingManagerImpl::AgentObserver implementation void OnAgentAdded(tracing::mojom::BackgroundTracingAgent* agent) override { agent->SetUMACallback(histogram_name_, histogram_lower_value_, - histogram_upper_value_, repeat_); + histogram_upper_value_); } void OnAgentRemoved(tracing::mojom::BackgroundTracingAgent* agent) override { @@ -291,14 +283,11 @@ void OnHistogramChangedCallback(base::Histogram::Sample reference_lower_value, base::Histogram::Sample reference_upper_value, - bool repeat, const char* histogram_name, uint64_t name_hash, base::Histogram::Sample actual_value) { if (reference_lower_value > actual_value || reference_upper_value < actual_value) { - if (!repeat) - AbortTracing(); return; } @@ -333,7 +322,6 @@ std::string histogram_name_; int histogram_lower_value_; int histogram_upper_value_; - bool repeat_; bool installed_; std::unique_ptr<base::StatisticsRecorder::ScopedHistogramSampleObserver> histogram_sample_callback_;
diff --git a/content/browser/web_contents/color_chooser_unittest.cc b/content/browser/web_contents/color_chooser_unittest.cc index 47dc1f93..1c3e669e 100644 --- a/content/browser/web_contents/color_chooser_unittest.cc +++ b/content/browser/web_contents/color_chooser_unittest.cc
@@ -107,16 +107,13 @@ public: ColorChooserTestWithBackForwardCache() { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, {GetFeatureParams()}}}, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, + {{"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. /*disabled_features=*/{features::kBackForwardCacheMemoryControls}); } - protected: - base::FieldTrialParams GetFeatureParams() { - return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}}; - } - private: base::test::ScopedFeatureList scoped_feature_list_; };
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc index 0b824b8..5933d6b 100644 --- a/content/browser/web_contents/web_contents_android.cc +++ b/content/browser/web_contents/web_contents_android.cc
@@ -260,6 +260,16 @@ destruction_observers_.RemoveObserver(observer); } +// static +void WebContentsAndroid::ReportDanglingPtrToBrowserContext( + JNIEnv* env, + WebContents* web_contents) { + if (base::android::ScopedJavaLocalRef<jthrowable> java_creator = + web_contents->GetJavaCreatorLocation()) { + Java_WebContentsImpl_reportDanglingPtrToBrowserContext(env, java_creator); + } +} + base::android::ScopedJavaLocalRef<jobject> WebContentsAndroid::GetTopLevelNativeWindow(JNIEnv* env) { ui::WindowAndroid* window_android = web_contents_->GetTopLevelNativeWindow();
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h index 7c0d0c43..8f18c83 100644 --- a/content/browser/web_contents/web_contents_android.h +++ b/content/browser/web_contents/web_contents_android.h
@@ -25,6 +25,7 @@ namespace content { +class WebContents; class WebContentsImpl; // Android wrapper around WebContents that provides safer passage from java and @@ -215,6 +216,12 @@ void AddDestructionObserver(DestructionObserver* observer); void RemoveDestructionObserver(DestructionObserver* observer); + // Adds a crash report, like DumpWithoutCrashing(), including the Java stack + // trace from which `web_contents` was created. This is meant to help debug + // cases where BrowserContext is destroyed before its WebContents. + static void ReportDanglingPtrToBrowserContext(JNIEnv* env, + WebContents* web_contents); + private: void OnFinishDownloadImage(const base::android::JavaRef<jobject>& obj, const base::android::JavaRef<jobject>& callback,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 720156a..c4db6519 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -908,6 +908,10 @@ if (web_contents_set_.empty()) return; // Everything is okay - nothing to warn about. +#if BUILDFLAG(IS_ANDROID) + JNIEnv* env = base::android::AttachCurrentThread(); +#endif // BUILDFLAG(IS_ANDROID) + // Any remaining WebContents contain dangling pointers to the // BrowserContext being destroyed. Such WebContents (and their // RenderFrameHosts, SiteInstances, etc.) risk causing @@ -919,6 +923,14 @@ ->GetCreatorLocation() .ToString(); SCOPED_CRASH_KEY_STRING256("shutdown", "web_contents/creator", creator); + +#if BUILDFLAG(IS_ANDROID) + // On Android, also report the Java stack trace from WebContents's + // creation. + WebContentsAndroid::ReportDanglingPtrToBrowserContext( + env, web_contents_with_dangling_ptr_to_browser_context); +#endif // BUILDFLAG(IS_ANDROID) + NOTREACHED() << "BrowserContext is getting destroyed without first closing all " << "WebContents (for more info see https://crbug.com/1376879#c44); " @@ -3123,6 +3135,9 @@ TRACE_EVENT0("content", "WebContentsImpl::Init"); creator_location_ = params.creator_location; +#if BUILDFLAG(IS_ANDROID) + java_creator_location_ = params.java_creator_location; +#endif // BUILDFLAG(IS_ANDROID) // An initial aspect ratio of 0.0 implies that the website did not set one and // therefore we should use a default value. We will also use a default value @@ -8345,6 +8360,11 @@ return GetWebContentsAndroid()->GetJavaObject(); } +base::android::ScopedJavaLocalRef<jthrowable> +WebContentsImpl::GetJavaCreatorLocation() { + return base::android::ScopedJavaLocalRef<jthrowable>(java_creator_location_); +} + WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() { if (!web_contents_android_) { web_contents_android_ = std::make_unique<WebContentsAndroid>(this); @@ -8527,6 +8547,8 @@ if (RenderWidgetHost* render_widget_host = GetPrimaryMainFrame()->GetRenderWidgetHost()) render_widget_host->SynchronizeVisualProperties(); + + view_->UpdateWindowControlsOverlay(bounding_rect); } BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index ae95a44..e433ca5f 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -550,6 +550,8 @@ void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; #if BUILDFLAG(IS_ANDROID) base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override; + base::android::ScopedJavaLocalRef<jthrowable> GetJavaCreatorLocation() + override; WebContentsAndroid* GetWebContentsAndroid(); void ClearWebContentsAndroid(); void ActivateNearestFindResult(float x, float y) override; @@ -2326,9 +2328,14 @@ // TODO(1231679): Remove/reevaluate after the PCScan experiment is finished. std::unique_ptr<StarScanLoadObserver> star_scan_load_observer_; - // Stores WebContents::CreateParams::creator_location_. + // Stores WebContents::CreateParams::creator_location. base::Location creator_location_; +#if BUILDFLAG(IS_ANDROID) + // Stores WebContents::CreateParams::java_creator_location. + base::android::ScopedJavaGlobalRef<jthrowable> java_creator_location_; +#endif // BUILDFLAG(IS_ANDROID) + // The initial aspect ratio (only used for WebContents associated with a // PictureInPicture window). This value is either the parameter given in // WebContents::CreateParams::initial_picture_in_picture_aspect_ratio, or a
diff --git a/content/browser/web_contents/web_contents_view.h b/content/browser/web_contents/web_contents_view.h index 031dd5e..ddf2538 100644 --- a/content/browser/web_contents/web_contents_view.h +++ b/content/browser/web_contents/web_contents_view.h
@@ -114,6 +114,11 @@ #endif virtual void FullscreenStateChanged(bool is_fullscreen) = 0; + + // Intended for desktop PWAs with manifest entry of window-controls-overlay, + // this informs the view of which area at the top of the view is available for + // web contents. + virtual void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) = 0; }; // Factory function to create `WebContentsView`s. Implemented in the platform
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index 5342d51..a9665d9 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -294,6 +294,9 @@ select_popup_->HideMenu(); } +void WebContentsViewAndroid::UpdateWindowControlsOverlay( + const gfx::Rect& bounding_rect) {} + void WebContentsViewAndroid::ShowContextMenu(RenderFrameHost& render_frame_host, const ContextMenuParams& params) { if (is_active_drag_ && drag_exceeded_movement_threshold_)
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h index a979dd2..6ab6a3d 100644 --- a/content/browser/web_contents/web_contents_view_android.h +++ b/content/browser/web_contents/web_contents_view_android.h
@@ -84,6 +84,7 @@ void SetOverscrollControllerEnabled(bool enabled) override; void OnCapturerCountChanged() override; void FullscreenStateChanged(bool is_fullscreen) override; + void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; // Backend implementation of RenderViewHostDelegateView. void ShowContextMenu(RenderFrameHost& render_frame_host,
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 78ce9650..37b75ad 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1132,6 +1132,9 @@ void WebContentsViewAura::FullscreenStateChanged(bool is_fullscreen) {} +void WebContentsViewAura::UpdateWindowControlsOverlay( + const gfx::Rect& bounding_rect) {} + //////////////////////////////////////////////////////////////////////////////// // WebContentsViewAura, RenderViewHostDelegateView implementation:
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index 450fa961..dc30852 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -198,6 +198,7 @@ void SetOverscrollControllerEnabled(bool enabled) override; void OnCapturerCountChanged() override; void FullscreenStateChanged(bool is_fullscreen) override; + void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; // Overridden from RenderViewHostDelegateView: void ShowContextMenu(RenderFrameHost& render_frame_host,
diff --git a/content/browser/web_contents/web_contents_view_child_frame.cc b/content/browser/web_contents/web_contents_view_child_frame.cc index 14b04eef..59dc078 100644 --- a/content/browser/web_contents/web_contents_view_child_frame.cc +++ b/content/browser/web_contents/web_contents_view_child_frame.cc
@@ -129,6 +129,9 @@ void WebContentsViewChildFrame::FullscreenStateChanged(bool is_fullscreen) {} +void WebContentsViewChildFrame::UpdateWindowControlsOverlay( + const gfx::Rect& bounding_rect) {} + void WebContentsViewChildFrame::RestoreFocus() { NOTREACHED(); }
diff --git a/content/browser/web_contents/web_contents_view_child_frame.h b/content/browser/web_contents/web_contents_view_child_frame.h index 7cbd8f3..4228448c 100644 --- a/content/browser/web_contents/web_contents_view_child_frame.h +++ b/content/browser/web_contents/web_contents_view_child_frame.h
@@ -59,6 +59,7 @@ #endif void OnCapturerCountChanged() override; void FullscreenStateChanged(bool is_fullscreen) override; + void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; // Backend implementation of RenderViewHostDelegateView. void ShowContextMenu(RenderFrameHost& render_frame_host,
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h index 57d8bf4..6b3ee7d 100644 --- a/content/browser/web_contents/web_contents_view_mac.h +++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -91,6 +91,7 @@ bool CloseTabAfterEventTrackingIfNeeded() override; void OnCapturerCountChanged() override; void FullscreenStateChanged(bool is_fullscreen) override; + void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect) override; // RenderViewHostDelegateView: void StartDragging(const DropData& drop_data,
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index 7c6fc893..73fb7a8 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -145,6 +145,15 @@ void WebContentsViewMac::FullscreenStateChanged(bool is_fullscreen) {} +void WebContentsViewMac::UpdateWindowControlsOverlay( + const gfx::Rect& bounding_rect) { + if (remote_ns_view_) { + remote_ns_view_->UpdateWindowControlsOverlay(bounding_rect); + } else { + in_process_ns_view_bridge_->UpdateWindowControlsOverlay(bounding_rect); + } +} + void WebContentsViewMac::StartDragging( const DropData& drop_data, DragOperationsMask allowed_operations,
diff --git a/content/common/web_contents_ns_view_bridge.mojom b/content/common/web_contents_ns_view_bridge.mojom index 1215b372..8639759 100644 --- a/content/common/web_contents_ns_view_bridge.mojom +++ b/content/common/web_contents_ns_view_bridge.mojom
@@ -40,6 +40,11 @@ gfx.mojom.ImageSkia? image, gfx.mojom.Vector2d image_offset); + // Intended for desktop PWAs with manifest entry of window-controls-overlay, + // this informs the view of which area at the top of the view is available for + // web contents. + UpdateWindowControlsOverlay(gfx.mojom.Rect bounding_rect); + // TODO(https://crbug.com/1327478): This is a work around for a bug in mojo // where close notifications for associated messages pipes can sometimes be // delivered later than they should. This method is called before closing the
diff --git a/content/common/webid/identity_url_loader_throttle.cc b/content/common/webid/identity_url_loader_throttle.cc index 552663ea..558ffa5a 100644 --- a/content/common/webid/identity_url_loader_throttle.cc +++ b/content/common/webid/identity_url_loader_throttle.cc
@@ -26,7 +26,7 @@ static constexpr char kIdpSigninStatusHeader[] = "IdP-SignIn-Status"; static constexpr char kIdpHeaderValueSignin[] = "action=signin"; -static constexpr char kIdpHeaderValueSignout[] = "action=signout"; +static constexpr char kIdpHeaderValueSignout[] = "action=signout-all"; bool IsFedCmIdpSigninStatusThrottleEnabled() { return GetFieldTrialParamByFeatureAsBool(
diff --git a/content/common/webid/identity_url_loader_throttle_unittest.cc b/content/common/webid/identity_url_loader_throttle_unittest.cc index 91aa830..6fa8cc5 100644 --- a/content/common/webid/identity_url_loader_throttle_unittest.cc +++ b/content/common/webid/identity_url_loader_throttle_unittest.cc
@@ -83,7 +83,7 @@ } else { base::SStringPrintf( &header, "idp-signin-status: action=sign%s", - signin_status == IdpSigninStatus::kSignedIn ? "in" : "out"); + signin_status == IdpSigninStatus::kSignedIn ? "in" : "out-all"); } network::mojom::URLResponseHead response_head;
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index 337b37c..943a5cc 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -21,6 +21,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import org.chromium.base.JavaExceptionReporter; import org.chromium.base.Log; import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; @@ -446,6 +447,22 @@ frames[index] = frame; } + /** + * Thrown by reportDanglingPtrToBrowserContext(), indicating that WebContentsImpl is deleted + * after its BrowserContext. + */ + private static class DanglingPointerException extends RuntimeException { + DanglingPointerException(String msg, Throwable causedBy) { + super(msg, causedBy); + } + } + + @CalledByNative + private static void reportDanglingPtrToBrowserContext(Throwable creator) { + JavaExceptionReporter.reportException(new DanglingPointerException( + "Dangling pointer to BrowserContext in WebContents", creator)); + } + @Override public @Nullable RenderWidgetHostViewImpl getRenderWidgetHostView() { if (mNativeWebContentsAndroid == 0) return null;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java index 582c52f..d7ab25e9 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java
@@ -1092,7 +1092,7 @@ Assert.assertEquals(4294967295L, mTestObject.waitForLongArray()[0]); mActivityTestRule.executeJavaScript("testObject.setFloatArray(uint32_array);"); - Assert.assertEquals((new Long(4294967295L)).floatValue(), + Assert.assertEquals((Long.valueOf(4294967295L)).floatValue(), mTestObject.waitForFloatArray()[0], ASSERTION_DELTA); mActivityTestRule.executeJavaScript("testObject.setDoubleArray(uint32_array);");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java index 18269cb4..75ed60f8 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -101,7 +101,6 @@ import org.chromium.ui.test.util.UiRestriction; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -154,12 +153,8 @@ // ContentFeatureList maps used for various tests. private static final Map<String, Boolean> ON_DEMAND_ON_COMPUTE_ON = - new HashMap<String, Boolean>() { - { - put(ContentFeatureList.ON_DEMAND_ACCESSIBILITY_EVENTS, true); - put(ContentFeatureList.COMPUTE_AX_MODE, true); - } - }; + Map.of(ContentFeatureList.ON_DEMAND_ACCESSIBILITY_EVENTS, true, + ContentFeatureList.COMPUTE_AX_MODE, true); // Constant values for unit tests private static final int UNSUPPRESSED_EXPECTED_COUNT = 15;
diff --git a/content/public/browser/attribution_data_model.cc b/content/public/browser/attribution_data_model.cc index 6d0216b..9035a15 100644 --- a/content/public/browser/attribution_data_model.cc +++ b/content/public/browser/attribution_data_model.cc
@@ -8,23 +8,18 @@ #include <utility> #include "base/check.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" namespace content { -AttributionDataModel::DataKey::DataKey( - url::Origin reporting_origin, - absl::optional<url::Origin> source_origin, - absl::optional<url::Origin> destination_origin) +AttributionDataModel::DataKey::DataKey(url::Origin reporting_origin, + url::Origin context_origin, + Scope scope) : reporting_origin_(std::move(reporting_origin)), - source_origin_(std::move(source_origin)), - destination_origin_(std::move(destination_origin)) { + context_origin_(std::move(context_origin)), + scope_(scope) { DCHECK(!reporting_origin_.opaque()); - - DCHECK(!source_origin_.has_value() || !source_origin_->opaque()); - - DCHECK(!destination_origin_.has_value() || !destination_origin_->opaque()); + DCHECK(!context_origin_.opaque()); } AttributionDataModel::DataKey::DataKey(const DataKey&) = default; @@ -41,9 +36,14 @@ bool AttributionDataModel::DataKey::operator<( const AttributionDataModel::DataKey& other) const { - return std::tie(reporting_origin_, source_origin_, destination_origin_) < - std::tie(other.reporting_origin_, other.source_origin_, - other.destination_origin_); + return std::tie(reporting_origin_, context_origin_, scope_) < + std::tie(other.reporting_origin_, other.context_origin_, other.scope_); +} + +bool AttributionDataModel::DataKey::operator==( + const AttributionDataModel::DataKey& other) const { + return std::tie(reporting_origin_, context_origin_, scope_) == + std::tie(other.reporting_origin_, other.context_origin_, other.scope_); } } // namespace content \ No newline at end of file
diff --git a/content/public/browser/attribution_data_model.h b/content/public/browser/attribution_data_model.h index dbc2b73..82980bc 100644 --- a/content/public/browser/attribution_data_model.h +++ b/content/public/browser/attribution_data_model.h
@@ -9,18 +9,22 @@ #include "base/functional/callback_forward.h" #include "content/common/content_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" namespace content { class CONTENT_EXPORT AttributionDataModel { public: - class DataKey { + class CONTENT_EXPORT DataKey { public: + enum class Scope { + kSource, + kReport, + }; + DataKey(url::Origin reporting_origin, - absl::optional<url::Origin> source_origin, - absl::optional<url::Origin> destination_origin); + url::Origin context_origin, + Scope scope); DataKey(const DataKey&); DataKey(DataKey&&); @@ -32,22 +36,20 @@ const url::Origin& reporting_origin() const { return reporting_origin_; } - const absl::optional<url::Origin>& source_origin() const { - return source_origin_; - } + const url::Origin& context_origin() const { return context_origin_; } - const absl::optional<url::Origin>& destination_origin() const { - return destination_origin_; - } + Scope scope() const { return scope_; } bool operator<(const DataKey&) const; + bool operator==(const DataKey&) const; + private: url::Origin reporting_origin_; - absl::optional<url::Origin> source_origin_; + url::Origin context_origin_; - absl::optional<url::Origin> destination_origin_; + Scope scope_; }; virtual ~AttributionDataModel() = default;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 28afdb7..75dbea1b 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -670,10 +670,6 @@ return std::string(); } -base::FilePath ContentBrowserClient::GetFontLookupTableCacheDir() { - return base::FilePath(); -} - base::FilePath ContentBrowserClient::GetShaderDiskCacheDirectory() { return base::FilePath(); }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 174a8d9..868dd48 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1083,11 +1083,6 @@ // else we should do with the file. virtual std::string GetDefaultDownloadName(); - // Returns the path to the font lookup table cache directory in which - on - // Windows 7 & 8 - we cache font name meta information to perform @font-face { - // src: local() } lookups. - virtual base::FilePath GetFontLookupTableCacheDir(); - // Returns the path to the browser shader disk cache root. virtual base::FilePath GetShaderDiskCacheDirectory();
diff --git a/content/public/browser/navigation_controller.cc b/content/public/browser/navigation_controller.cc index 9c27e49..d9b40d6 100644 --- a/content/public/browser/navigation_controller.cc +++ b/content/public/browser/navigation_controller.cc
@@ -14,7 +14,7 @@ namespace content { NavigationController::LoadURLParams::LoadURLParams(const GURL& url) - : url(url), is_renderer_initiated(false) {} + : url(url) {} NavigationController::LoadURLParams::LoadURLParams( NavigationController::LoadURLParams&&) = default;
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h index addb8106..58930dc 100644 --- a/content/public/browser/navigation_controller.h +++ b/content/public/browser/navigation_controller.h
@@ -209,7 +209,7 @@ // True for renderer-initiated navigations. This is // important for tracking whether to display pending URLs. - bool is_renderer_initiated; + bool is_renderer_initiated = false; // Whether a navigation in a new window has the opener suppressed. False if // the navigation is not in a new window. Can only be true when
diff --git a/content/public/browser/origin_trials_controller_delegate.h b/content/public/browser/origin_trials_controller_delegate.h index 8f7d350..fb52577 100644 --- a/content/public/browser/origin_trials_controller_delegate.h +++ b/content/public/browser/origin_trials_controller_delegate.h
@@ -22,29 +22,50 @@ // for the current profile. // // See |components/origin_trials/README.md| for more information. +// TODO(https://crbug.com/1410180): Switch |partition_origin| to use Cookie +// partitioning. This interface uses the last committed origin from the +// outermost frame or document as partitioning as an interim measure to get a +// stable partitioning key until cookie partitioning is fully rolled out. class CONTENT_EXPORT OriginTrialsControllerDelegate { public: virtual ~OriginTrialsControllerDelegate() = default; // Persist all enabled and persistable tokens in the |header_tokens|. - // Subsequent calls to this method will overwrite the list of persisted trials - // for the |origin|. + // + // Token persistence is partitioned based on |partition_origin|, meaning that + // the storage keeps track of which |partition_origin|s have been seen when + // persisting tokens for a given trial and origin. + // + // Subsequent calls to this method will update the registration of a token + // for an origin. Passing an empty |header_tokens| will effectively clear the + // persistence of tokens for the |origin| and |partition_origin|. + // TODO(https://crbug.com/1410180): Switch |partition_origin| to use Cookie + // partitioning. virtual void PersistTrialsFromTokens( const url::Origin& origin, + const url::Origin& partition_origin, const base::span<const std::string> header_tokens, const base::Time current_time) = 0; - // Returns |true| if |trial_name| has been persisted for |origin| and is still - // valid. This method should be used by origin trial owners to check if the - // feature under trial should be enabled. + // Returns |true| if |trial_name| has been persisted for |origin|, + // partitioned by |partition_origin| and is still valid. This method should + // be used by origin trial owners to check if the feature under trial should + // be enabled. + // TODO(https://crbug.com/1410180): Switch |partition_origin| to use Cookie + // partitioning. virtual bool IsTrialPersistedForOrigin(const url::Origin& origin, + const url::Origin& partition_origin, const base::StringPiece trial_name, const base::Time current_time) = 0; // Return the list of persistent origin trials that have been saved for - // |origin| and haven't expired given the |current_time| parameter. + // |origin|, partitioned by |partition_origin|, and haven't expired given the + // |current_time| parameter. + // TODO(https://crbug.com/1410180): Switch |partition_origin| to use Cookie + // partitioning. virtual base::flat_set<std::string> GetPersistedTrialsForOrigin( const url::Origin& origin, + const url::Origin& partition_origin, base::Time current_time) = 0; // Remove all persisted tokens. Used to clear browsing data.
diff --git a/content/public/browser/prefetch_service_delegate.h b/content/public/browser/prefetch_service_delegate.h index 6254553..760bf38 100644 --- a/content/public/browser/prefetch_service_delegate.h +++ b/content/public/browser/prefetch_service_delegate.h
@@ -9,6 +9,7 @@ #include "base/time/time.h" #include "content/common/content_export.h" +#include "content/public/browser/preloading.h" #include "url/gurl.h" namespace content { @@ -60,7 +61,7 @@ virtual bool DisableDecoysBasedOnUserSettings() = 0; // Get the state of the user's preloading settings. - virtual bool IsSomePreloadingEnabled() = 0; + virtual PreloadingEligibility IsSomePreloadingEnabled() = 0; virtual bool IsExtendedPreloadingEnabled() = 0; // Checks if the referring page is in the allow list to make prefetches.
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 54c0a5f2..7778d03 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -257,6 +257,13 @@ // invariant violations to a particular flavor of WebContents). base::Location creator_location; +#if BUILDFLAG(IS_ANDROID) + // Same as `creator_location`, for WebContents created via Java. This + // java.lang.Throwable contains the entire + // WebContentsCreator.createWebContents() stack trace. + base::android::ScopedJavaGlobalRef<jthrowable> java_creator_location; +#endif // BUILDFLAG(IS_ANDROID) + // Enables contents to hold wake locks, for example, to keep the screen on // while playing video. bool enable_wake_locks = true; @@ -1274,6 +1281,10 @@ const base::android::JavaRef<jobject>& jweb_contents_android); virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() = 0; + // Returns the value from CreateParams::java_creator_location. + virtual base::android::ScopedJavaLocalRef<jthrowable> + GetJavaCreatorLocation() = 0; + // Selects and zooms to the find result nearest to the point (x,y) defined in // find-in-page coordinates. virtual void ActivateNearestFindResult(float x, float y) = 0;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 288b2fb..2305a219 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -114,6 +114,13 @@ "BackForwardCacheEntryTimeout", base::FEATURE_ENABLED_BY_DEFAULT); +// Enables controlling the time to live for pages in the BackForwardCache. +// The time to live is defined by the param 'time_to_live_seconds'; if this +// param is not specified then this feature is ignored and the default is used. +BASE_FEATURE(kBackForwardCacheTimeToLiveControl, + "BackForwardCacheTimeToLiveControl", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enable back/forward cache for screen reader users. This flag should be // removed once the https://crbug.com/1271450 is resolved. BASE_FEATURE(kEnableBackForwardCacheForScreenReader,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 21a67f6..e93b19cc 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -32,6 +32,7 @@ kResourceTimingForCancelledNavigationInFrame); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheEntryTimeout); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheMemoryControls); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheTimeToLiveControl); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBackForwardCacheMediaSessionService); CONTENT_EXPORT BASE_DECLARE_FEATURE(kBlockInsecurePrivateNetworkRequests); CONTENT_EXPORT BASE_DECLARE_FEATURE(
diff --git a/content/public/test/back_forward_cache_util.cc b/content/public/test/back_forward_cache_util.cc index 2d5ff91d..fbee8a2 100644 --- a/content/public/test/back_forward_cache_util.cc +++ b/content/public/test/back_forward_cache_util.cc
@@ -69,7 +69,7 @@ std::vector<base::test::FeatureRefAndParams> default_features_and_params = { {features::kBackForwardCache, {{"ignore_outstanding_network_request_for_testing", "true"}}}, - {kBackForwardCacheTimeToLiveControl, + {features::kBackForwardCacheTimeToLiveControl, {{"time_to_live_in_seconds", "3600"}}}}; std::vector<base::test::FeatureRefAndParams> final_params; // Go over the additional features/params - if they match a default feature,
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc index a914184..f8191976 100644 --- a/content/public/test/fake_local_frame.cc +++ b/content/public/test/fake_local_frame.cc
@@ -71,10 +71,6 @@ void FakeLocalFrame::ClearFocusedElement() {} -void FakeLocalFrame::GetResourceSnapshotForWebBundle( - mojo::PendingReceiver<data_decoder::mojom::ResourceSnapshotForWebBundle> - receiver) {} - void FakeLocalFrame::CopyImageAt(const gfx::Point& window_point) {} void FakeLocalFrame::SaveImageAt(const gfx::Point& window_point) {}
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h index 39da064..e732e63 100644 --- a/content/public/test/fake_local_frame.h +++ b/content/public/test/fake_local_frame.h
@@ -60,9 +60,6 @@ void EnableViewSourceMode() override; void Focus() override; void ClearFocusedElement() override; - void GetResourceSnapshotForWebBundle( - mojo::PendingReceiver<data_decoder::mojom::ResourceSnapshotForWebBundle> - receiver) override; void CopyImageAt(const gfx::Point& window_point) override; void SaveImageAt(const gfx::Point& window_point) override; void ReportBlinkFeatureUsage(
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index 5989d7b2..4a25b1e2 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -338,6 +338,10 @@ // request. Instead, the mojo reply should be used directly. if (event_to_fire != ax::mojom::Event::kNone) { const std::vector<ui::AXEventIntent> intents; + if (serialize_post_lifecycle_) { + // Marking dirty ensures that a lifecycle update will be scheduled. + MarkWebAXObjectDirty(ax_object, /*subtree*/ false); + } HandleAXEvent(ui::AXEvent( ax_object.AxID(), event_to_fire, ax::mojom::EventFrom::kAction, ax::mojom::Action::kHitTest, intents, request_id)); @@ -570,13 +574,11 @@ DCHECK(!obj.IsDetached() || !serialize_post_lifecycle_); - if (IsImmediateProcessingRequiredForEvent(event)) { - if (serialize_post_lifecycle_) { - ScheduleImmediateAXUpdate(); - } else { - legacy_event_schedule_mode_ = - LegacyEventScheduleMode::kProcessEventsImmediately; - } + if (serialize_post_lifecycle_) { + ScheduleImmediateAXUpdate(); + } else { + legacy_event_schedule_mode_ = + LegacyEventScheduleMode::kProcessEventsImmediately; } if (!serialize_post_lifecycle_ || !obj.IsDetached()) {
diff --git a/content/renderer/document_state.h b/content/renderer/document_state.h index 54202cc..6fb08b3 100644 --- a/content/renderer/document_state.h +++ b/content/renderer/document_state.h
@@ -7,7 +7,6 @@ #include <memory> -#include "base/supports_user_data.h" #include "content/common/content_export.h" #include "net/http/http_response_info.h" #include "third_party/blink/public/web/web_document_loader.h"
diff --git a/content/renderer/pepper/resource_creation_impl.cc b/content/renderer/pepper/resource_creation_impl.cc index 79a7202..a4a00ac 100644 --- a/content/renderer/pepper/resource_creation_impl.cc +++ b/content/renderer/pepper/resource_creation_impl.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/feature_list.h" +#include "base/metrics/histogram_functions.h" #include "build/build_config.h" #include "content/common/content_switches_internal.h" #include "content/public/common/content_features.h" @@ -310,6 +311,9 @@ PP_Instance instance, PP_Resource graphics3d_id, PP_VideoDecoder_Profile profile) { + base::UmaHistogramBoolean( + "NaCl.ResourceCreationImpl.CreateVideoDecoderDev_Invoked", true); + if (IsVideoDecoderDevAPIEnabled()) { return create_video_decoder_dev_impl_callback_.Run(instance, graphics3d_id, profile);
diff --git a/content/services/auction_worklet/bidder_worklet.cc b/content/services/auction_worklet/bidder_worklet.cc index 57374f2..a851d556 100644 --- a/content/services/auction_worklet/bidder_worklet.cc +++ b/content/services/auction_worklet/bidder_worklet.cc
@@ -1050,7 +1050,7 @@ /*set_priority=*/absl::nullopt, /*update_priority_signals_overrides=*/ base::flat_map<std::string, mojom::PrioritySignalsDoublePtr>(), - /*update_priority_signals_overrides=*/ + /*pa_requests=*/ PrivateAggregationRequests(), std::move(error_msgs))); }
diff --git a/content/services/auction_worklet/bidder_worklet_unittest.cc b/content/services/auction_worklet/bidder_worklet_unittest.cc index 5a7e02a9..ddb02e1e 100644 --- a/content/services/auction_worklet/bidder_worklet_unittest.cc +++ b/content/services/auction_worklet/bidder_worklet_unittest.cc
@@ -5396,7 +5396,9 @@ class BidderWorkletPrivateAggregationEnabledTest : public BidderWorkletTest { public: BidderWorkletPrivateAggregationEnabledTest() { - scoped_feature_list_.InitAndEnableFeature(content::kPrivateAggregationApi); + scoped_feature_list_.InitAndEnableFeatureWithParameters( + content::kPrivateAggregationApi, + {{"fledge_extensions_enabled", "true"}}); } private: @@ -5404,21 +5406,42 @@ }; TEST_F(BidderWorkletPrivateAggregationEnabledTest, GenerateBid) { - auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedRequest1 = - auction_worklet::mojom::PrivateAggregationRequest::New( + mojom::PrivateAggregationRequest kExpectedRequest1( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/123, - /*value=*/45), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedRequest2 = - auction_worklet::mojom::PrivateAggregationRequest::New( + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedRequest2( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( - /*bucket=*/absl::MakeInt128(/*high=*/1, /*low=*/0), - /*value=*/1), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); + /*bucket=*/absl::MakeInt128(/*high=*/1, + /*low=*/0), + /*value=*/1)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest1( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket(234), + /*value=*/mojom::ForEventSignalValue::NewIntValue(56), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest2( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket( + absl::MakeInt128(/*high=*/1, + /*low=*/0)), + /*value=*/mojom::ForEventSignalValue::NewIntValue(2), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + + // Only sendHistogramReport() is called. { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); @@ -5442,6 +5465,58 @@ std::move(expected_pa_requests)); } + // Only reportContributionForEvent() is called. + { + PrivateAggregationRequests expected_pa_requests; + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + + RunGenerateBidWithJavascriptExpectingResult( + CreateGenerateBidScript( + R"({ad: "ad", bid:1, render:"https://response.test/" })", + /*extra_code=*/R"( + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )"), + /*expected_bid=*/ + mojom::BidderWorkletBid::New( + "\"ad\"", 1, GURL("https://response.test/"), + /*ad_components=*/absl::nullopt, base::TimeDelta()), + /*expected_data_version=*/absl::nullopt, + /*expected_errors=*/{}, + /*expected_debug_loss_report_url=*/absl::nullopt, + /*expected_debug_win_report_url=*/absl::nullopt, + /*expected_set_priority=*/absl::nullopt, + /*expected_update_priority_signals_overrides=*/{}, + std::move(expected_pa_requests)); + } + + // Both sendHistogramReport() and reportContributionForEvent() are called. + { + PrivateAggregationRequests expected_pa_requests; + expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + + RunGenerateBidWithJavascriptExpectingResult( + CreateGenerateBidScript( + R"({ad: "ad", bid:1, render:"https://response.test/" })", + /*extra_code=*/R"( + privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )"), + /*expected_bid=*/ + mojom::BidderWorkletBid::New( + "\"ad\"", 1, GURL("https://response.test/"), + /*ad_components=*/absl::nullopt, base::TimeDelta()), + /*expected_data_version=*/absl::nullopt, + /*expected_errors=*/{}, + /*expected_debug_loss_report_url=*/absl::nullopt, + /*expected_debug_win_report_url=*/absl::nullopt, + /*expected_set_priority=*/absl::nullopt, + /*expected_update_priority_signals_overrides=*/{}, + std::move(expected_pa_requests)); + } + // Set the private-aggregation permissions policy to disallowed. { permissions_policy_state_ = @@ -5474,6 +5549,7 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest2.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest2.Clone()); RunGenerateBidWithJavascriptExpectingResult( CreateGenerateBidScript( @@ -5481,6 +5557,8 @@ /*extra_code=*/R"( privateAggregation.sendHistogramReport( {bucket: 18446744073709551616n, value: 1}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 18446744073709551616n, value: 2}); )"), /*expected_bid=*/ mojom::BidderWorkletBid::New( @@ -5500,6 +5578,8 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); expected_pa_requests.push_back(kExpectedRequest2.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest2.Clone()); RunGenerateBidWithJavascriptExpectingResult( CreateGenerateBidScript( @@ -5508,6 +5588,10 @@ privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); privateAggregation.sendHistogramReport( {bucket: 18446744073709551616n, value: 1}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 18446744073709551616n, value: 2}); )"), /*expected_bid=*/ mojom::BidderWorkletBid::New( @@ -5522,22 +5606,26 @@ std::move(expected_pa_requests)); } - // An unrelated exception after sendHistogramReport shouldn't block the report + // An unrelated exception after sendHistogramReport and + // reportContributionForEvent shouldn't block the reports. { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); RunGenerateBidWithJavascriptExpectingResult( CreateGenerateBidScript( R"({ad: "ad", bid:1, render:"https://response.test/" })", /*extra_code=*/R"( privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); error; )"), /*expected_bid=*/mojom::BidderWorkletBidPtr(), /*expected_data_version=*/absl::nullopt, /*expected_errors=*/ - {"https://url.test/:7 Uncaught ReferenceError: error is not defined."}, + {"https://url.test/:9 Uncaught ReferenceError: error is not defined."}, /*expected_debug_loss_report_url=*/absl::nullopt, /*expected_debug_win_report_url=*/absl::nullopt, /*expected_set_priority=*/absl::nullopt, @@ -5550,7 +5638,13 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New( + /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); + expected_pa_requests.push_back( + auction_worklet::mojom::PrivateAggregationRequest::New( + kExpectedForEventRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); @@ -5561,6 +5655,8 @@ /*extra_code=*/R"( privateAggregation.enableDebugMode({debug_key: 1234n}); privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); )"), /*expected_bid=*/ mojom::BidderWorkletBid::New( @@ -5580,13 +5676,13 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest2->contribution->Clone(), + kExpectedRequest2.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); @@ -5636,20 +5732,38 @@ } TEST_F(BidderWorkletPrivateAggregationEnabledTest, ReportWin) { - auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedRequest1 = - auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::PrivateAggregationRequest kExpectedRequest1( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/123, - /*value=*/45), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - auction_worklet::mojom::PrivateAggregationRequestPtr kExpectedRequest2 = - auction_worklet::mojom::PrivateAggregationRequest::New( + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + auction_worklet::mojom::PrivateAggregationRequest kExpectedRequest2( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/absl::MakeInt128(/*high=*/1, /*low=*/0), - /*value=*/1), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); + /*value=*/1)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest1( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket(234), + /*value=*/mojom::ForEventSignalValue::NewIntValue(56), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest2( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket( + absl::MakeInt128(/*high=*/1, + /*low=*/0)), + /*value=*/mojom::ForEventSignalValue::NewIntValue(2), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); { PrivateAggregationRequests expected_pa_requests; @@ -5705,12 +5819,18 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); expected_pa_requests.push_back(kExpectedRequest2.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest2.Clone()); RunReportWinWithFunctionBodyExpectingResult( R"( privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); privateAggregation.sendHistogramReport({bucket: 18446744073709551616n, value: 1}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 18446744073709551616n, value: 2}); )", /*expected_report_url =*/absl::nullopt, /*expected_ad_beacon_map=*/{}, std::move(expected_pa_requests), @@ -5739,7 +5859,13 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New( + /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); + expected_pa_requests.push_back( + auction_worklet::mojom::PrivateAggregationRequest::New( + kExpectedForEventRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); @@ -5748,6 +5874,8 @@ R"( privateAggregation.enableDebugMode({debug_key: 1234n}); privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); )", /*expected_report_url=*/absl::nullopt, /*expected_ad_beacon_map=*/{}, std::move(expected_pa_requests), @@ -5759,13 +5887,13 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); expected_pa_requests.push_back( auction_worklet::mojom::PrivateAggregationRequest::New( - kExpectedRequest2->contribution->Clone(), + kExpectedRequest2.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); @@ -5781,6 +5909,23 @@ /*expected_ad_beacon_map=*/{}, std::move(expected_pa_requests), /*expected_errors=*/{}); } + + // For-event report and histogram report are reported. + { + PrivateAggregationRequests expected_pa_requests; + expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + + RunReportWinWithFunctionBodyExpectingResult( + R"( + privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )", + /*expected_report_url =*/absl::nullopt, + /*expected_ad_beacon_map=*/{}, std::move(expected_pa_requests), + /*expected_errors=*/{}); + } } class BidderWorkletPrivateAggregationDisabledTest : public BidderWorkletTest {
diff --git a/content/services/auction_worklet/context_recycler_unittest.cc b/content/services/auction_worklet/context_recycler_unittest.cc index 07002ba..48f69d42 100644 --- a/content/services/auction_worklet/context_recycler_unittest.cc +++ b/content/services/auction_worklet/context_recycler_unittest.cc
@@ -797,10 +797,10 @@ return gin::ConvertToV8(helper_->isolate(), dict); } - // Checks given `pa_requests` has one item, which equals to the request - // created from given `bucket` and `value`. DebugMode is enabled if - // `debug_key` is not nullopt. - void ExpectPrivateAggregationRequestsEqual( + // Expects that pa_requests has one request, and the request has the given + // bucket, value and debug_key (or none, if absl::nullopt). Also expects that + // debug mode is enabled if debug_key is not absl::nullopt. + void ExpectOneHistogramRequestEqualTo( std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr> pa_requests, absl::uint128 bucket, @@ -808,6 +808,7 @@ absl::optional<content::mojom::DebugKeyPtr> debug_key = absl::nullopt) { content::mojom::AggregatableReportHistogramContribution expected_contribution(bucket, value); + content::mojom::DebugModeDetailsPtr debug_mode_details; if (debug_key.has_value()) { debug_mode_details = content::mojom::DebugModeDetails::New( @@ -816,8 +817,10 @@ } else { debug_mode_details = content::mojom::DebugModeDetails::New(); } + auction_worklet::mojom::PrivateAggregationRequest expected_request( - expected_contribution.Clone(), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(expected_contribution.Clone()), content::mojom::AggregationServiceMode::kDefault, std::move(debug_mode_details)); @@ -868,7 +871,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45); @@ -887,7 +890,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/absl::MakeUint128(/*high=*/1, /*low=*/0), /*value=*/45); @@ -906,7 +909,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/absl::Uint128Max(), /*value=*/45); @@ -925,7 +928,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/0, /*value=*/45); @@ -944,7 +947,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/0); @@ -977,14 +980,16 @@ content::mojom::AggregatableReportHistogramContribution expected_contribution_1(/*bucket=*/123, /*value=*/45); auction_worklet::mojom::PrivateAggregationRequest expected_request_1( - expected_contribution_1.Clone(), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(expected_contribution_1.Clone()), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); content::mojom::AggregatableReportHistogramContribution expected_contribution_2(/*bucket=*/678, /*value=*/90); auction_worklet::mojom::PrivateAggregationRequest expected_request_2( - expected_contribution_2.Clone(), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(expected_contribution_2.Clone()), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); @@ -1214,7 +1219,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45, /*debug_key=*/nullptr); @@ -1237,7 +1242,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45, @@ -1261,7 +1266,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45, /*debug_key=*/ @@ -1359,7 +1364,7 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45, @@ -1384,7 +1389,7 @@ WrapDebugKey(std::string("1234"))); EXPECT_THAT(error_msgs, ElementsAre()); - ExpectPrivateAggregationRequestsEqual( + ExpectOneHistogramRequestEqualTo( context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests(), /*bucket=*/123, /*value=*/45, @@ -1422,7 +1427,8 @@ content::mojom::AggregatableReportHistogramContribution expected_contribution_1(/*bucket=*/123, /*value=*/45); auction_worklet::mojom::PrivateAggregationRequest expected_request_1( - expected_contribution_1.Clone(), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(expected_contribution_1.Clone()), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, @@ -1431,7 +1437,8 @@ content::mojom::AggregatableReportHistogramContribution expected_contribution_2(/*bucket=*/678, /*value=*/90); auction_worklet::mojom::PrivateAggregationRequest expected_request_2( - expected_contribution_2.Clone(), + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(expected_contribution_2.Clone()), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, @@ -1455,15 +1462,34 @@ {{"fledge_extensions_enabled", "true"}}); } - // Checks given `pa_requests` has one item, which equals to the request - // created from given `expected_contribution`. - void ExpectPrivateAggregationForEventRequestsEqual( - std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> + // Creates a PrivateAggregationRequest with ForEvent contribution. + auction_worklet::mojom::PrivateAggregationRequestPtr CreateForEventRequest( + absl::uint128 bucket, + int value, + const std::string& event_type) { + auction_worklet::mojom::AggregatableReportForEventContribution contribution( + auction_worklet::mojom::ForEventSignalBucket::NewIdBucket(bucket), + auction_worklet::mojom::ForEventSignalValue::NewIntValue(value), + std::move(event_type)); + + return auction_worklet::mojom::PrivateAggregationRequest::New( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(contribution.Clone()), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + } + + // Expects given `pa_requests` to have one item, which equals to the + // PrivateAggregationRequests created from given ForEvent contribution + // `expected_contribution`. + void ExpectOneForEventRequestEqualTo( + std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr> pa_requests, auction_worklet::mojom::AggregatableReportForEventContributionPtr expected_contribution) { - auction_worklet::mojom::PrivateAggregationForEventRequest expected_request( - expected_contribution.Clone(), + auction_worklet::mojom::PrivateAggregationRequest expected_request( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(expected_contribution.Clone()), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New()); @@ -1479,8 +1505,8 @@ // make sure they reset properly. TEST_F(ContextRecyclerPrivateAggregationExtensionsEnabledTest, PrivateAggregationForEventBindings) { - using PrivateAggregationForEventRequests = - std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr>; + using PrivateAggregationRequests = + std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>; const char kScript[] = R"( function test(args) { @@ -1494,21 +1520,24 @@ args.bucket.offset = BigInt(args.bucket.offset); } privateAggregation.reportContributionForEvent('reserved.win', args); - privateAggregation.reportContributionForEvent('reserved.loss', args); } - function testWinAndLoss(args) { + function testDifferentEventTypes(args) { // Passing BigInts in directly is complicated so we construct them from // strings. if (typeof args.bucket === "string") { args.bucket = BigInt(args.bucket); } privateAggregation.reportContributionForEvent('reserved.win', args); - // Add 1 to both bucket and value, to let reserved.loss request gets - // different contribution from reserved.win request. - args.bucket += BigInt(1); + // Add 1 to value, to let reserved.loss request gets different + // contribution from reserved.win request. args.value += 1; privateAggregation.reportContributionForEvent('reserved.loss', args); + args.value += 1; + privateAggregation.reportContributionForEvent('reserved.always', args); + args.value += 1; + // Arbitrary unreserved event type. + privateAggregation.reportContributionForEvent('click', args); } function testMissingEventType(args) { @@ -1528,14 +1557,14 @@ } privateAggregation.reportContributionForEvent(args, 'reserved.win'); } - function testNotReservedEventType(args) { - // Passing BigInts in directly is complicated so we construct them from - // strings. + + function testInvalidReservedEventType(args) { if (typeof args.bucket === "string") { args.bucket = BigInt(args.bucket); } - privateAggregation.reportContributionForEvent('not.reserved', args); + privateAggregation.reportContributionForEvent("reserved.something", args); } + function doNothing() {} )"; @@ -1555,32 +1584,26 @@ dict.Set("bucket", std::string("123")); dict.Set("value", 45); - Run(scope, script, "testWinAndLoss", error_msgs, + Run(scope, script, "testDifferentEventTypes", error_msgs, gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_win_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( - /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: - NewIdBucket(123), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 45)); - auto expected_loss_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( - /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: - NewIdBucket(124), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 46)); + auto pa_requests = context_recycler.private_aggregation_bindings() + ->TakePrivateAggregationRequests(); - ExpectPrivateAggregationForEventRequestsEqual( - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), - expected_win_contribution.Clone()); - - ExpectPrivateAggregationForEventRequestsEqual( - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss"), - std::move(expected_loss_contribution)); + ASSERT_EQ(pa_requests.size(), 4u); + EXPECT_EQ(pa_requests[0], + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedWin)); + EXPECT_EQ(pa_requests[1], + CreateForEventRequest(/*bucket=*/123, /*value=*/46, + /*event_type=*/kReservedLoss)); + EXPECT_EQ(pa_requests[2], + CreateForEventRequest(/*bucket=*/123, /*value=*/47, + /*event_type=*/kReservedAlways)); + EXPECT_EQ(pa_requests[3], + CreateForEventRequest(/*bucket=*/123, /*value=*/48, + /*event_type=*/"click")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests() @@ -1602,12 +1625,12 @@ EXPECT_THAT( error_msgs, ElementsAre( - "https://example.org/script.js:34 Uncaught TypeError: " + "https://example.org/script.js:37 Uncaught TypeError: " "reportContributionForEvent requires 2 parameters, with first " "parameter being a string and second parameter being an object.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -1624,12 +1647,12 @@ EXPECT_THAT( error_msgs, ElementsAre( - "https://example.org/script.js:38 Uncaught TypeError: " + "https://example.org/script.js:41 Uncaught TypeError: " "reportContributionForEvent requires 2 parameters, with first " "parameter being a string and second parameter being an object.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -1647,17 +1670,16 @@ EXPECT_THAT( error_msgs, ElementsAre( - "https://example.org/script.js:45 Uncaught TypeError: " + "https://example.org/script.js:48 Uncaught TypeError: " "reportContributionForEvent requires 2 parameters, with first " "parameter being a string and second parameter being an object.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } - // Not reserved event type, which is just being ignored currently, but will - // be supported in the future. + // Invalid reserved event type. { ContextRecyclerScope scope(context_recycler); std::vector<std::string> error_msgs; @@ -1666,11 +1688,14 @@ dict.Set("bucket", std::string("123")); dict.Set("value", 45); - Run(scope, script, "testNotReservedEventType", error_msgs, + Run(scope, script, "testInvalidReservedEventType", error_msgs, gin::ConvertToV8(helper_->isolate(), dict)); + // Don't throw an error if an invalid reserved event type is provided, to + // provide forward compatibility with new reserved event types added later. EXPECT_THAT(error_msgs, ElementsAre()); + EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -1687,17 +1712,18 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewIdBucket(absl::MakeUint128(/*high=*/1, /*low=*/0)), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 45)); + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(45), + /*event_type=*/kReservedWin); - ExpectPrivateAggregationForEventRequestsEqual( + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), - std::move(expected_contribution)); + ->TakePrivateAggregationRequests(), + expected_contribution.Clone()); } // Maximum bucket @@ -1713,17 +1739,18 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewIdBucket(absl::Uint128Max()), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 45)); + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(45), + /*event_type=*/kReservedWin); - ExpectPrivateAggregationForEventRequestsEqual( + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), - std::move(expected_contribution)); + ->TakePrivateAggregationRequests(), + expected_contribution.Clone()); } // Zero bucket @@ -1739,16 +1766,18 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewIdBucket(0), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 45)); - ExpectPrivateAggregationForEventRequestsEqual( + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(45), + /*event_type=*/kReservedWin); + + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), - std::move(expected_contribution)); + ->TakePrivateAggregationRequests(), + expected_contribution.Clone()); } // Zero value @@ -1764,16 +1793,18 @@ gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewIdBucket(123), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 0)); - ExpectPrivateAggregationForEventRequestsEqual( + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(0), + /*event_type=*/kReservedWin); + + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), - std::move(expected_contribution)); + ->TakePrivateAggregationRequests(), + expected_contribution.Clone()); } // Multiple requests @@ -1800,34 +1831,16 @@ EXPECT_THAT(error_msgs, ElementsAre()); } - auto expected_contribution_1 = - auction_worklet::mojom::AggregatableReportForEventContribution::New( - /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: - NewIdBucket(123), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 45)); - auction_worklet::mojom::PrivateAggregationForEventRequest - expected_request_1(expected_contribution_1.Clone(), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - - auto expected_contribution_2 = - auction_worklet::mojom::AggregatableReportForEventContribution::New( - /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: - NewIdBucket(678), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 90)); - auction_worklet::mojom::PrivateAggregationForEventRequest - expected_request_2(expected_contribution_2.Clone(), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - - PrivateAggregationForEventRequests pa_requests = + PrivateAggregationRequests pa_requests = context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"); + ->TakePrivateAggregationRequests(); ASSERT_EQ(pa_requests.size(), 2u); - EXPECT_EQ(pa_requests[0], expected_request_1.Clone()); - EXPECT_EQ(pa_requests[1], expected_request_2.Clone()); + EXPECT_EQ(pa_requests[0], + CreateForEventRequest(/*bucket=*/123, /*value=*/45, + /*event_type=*/kReservedWin)); + EXPECT_EQ(pa_requests[1], + CreateForEventRequest(/*bucket=*/678, /*value=*/90, + /*event_type=*/kReservedWin)); } // Too large bucket @@ -1847,10 +1860,7 @@ "BigInt is too large.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } @@ -1861,43 +1871,76 @@ gin::Dictionary bucket_dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - bucket_dict.Set("base_value", std::string("bidRejectReason")); + bucket_dict.Set("baseValue", std::string("bidRejectReason")); + bucket_dict.Set("scale", 2); bucket_dict.Set("offset", std::string("-255")); gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); dict.Set("bucket", bucket_dict); dict.Set("value", 1); - auto signal_bucket = auction_worklet::mojom::SignalBucketOrValue::New( + auto signal_bucket = auction_worklet::mojom::SignalBucket::New( /*base_value=*/auction_worklet::mojom::BaseValue::kBidRejectReason, - /*scale=*/0, /*has_scale*/ false, + /*scale=*/2, /*offset=*/ - auction_worklet::mojom::Offset::New(/*value=*/255, - /*is_negative=*/true)); + auction_worklet::mojom::BucketOffset::New(/*value=*/255, + /*is_negative=*/true)); Run(scope, script, "test", error_msgs, gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewSignalBucket(std::move(signal_bucket)), - /*value=*/auction_worklet::mojom::ForEventSignalValue::NewIntValue( - 1)); + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(1), + /*event_type=*/kReservedWin); - ExpectPrivateAggregationForEventRequestsEqual( + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), + ->TakePrivateAggregationRequests(), expected_contribution.Clone()); - - ExpectPrivateAggregationForEventRequestsEqual( - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss"), - std::move(expected_contribution)); } - // Invalid bucket dictionary, which has no base_value key + // Dictionary bucket. Scale and offset are optional. + { + ContextRecyclerScope scope(context_recycler); + std::vector<std::string> error_msgs; + + gin::Dictionary bucket_dict = + gin::Dictionary::CreateEmpty(helper_->isolate()); + bucket_dict.Set("baseValue", std::string("bidRejectReason")); + + gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); + dict.Set("bucket", bucket_dict); + dict.Set("value", 1); + + auction_worklet::mojom::SignalBucket signal_bucket; + signal_bucket.base_value = + auction_worklet::mojom::BaseValue::kBidRejectReason; + signal_bucket.offset = nullptr; + + Run(scope, script, "test", error_msgs, + gin::ConvertToV8(helper_->isolate(), dict)); + EXPECT_THAT(error_msgs, ElementsAre()); + + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( + /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: + NewSignalBucket(signal_bucket.Clone()), + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewIntValue(1), + /*event_type=*/kReservedWin); + + ExpectOneForEventRequestEqualTo( + context_recycler.private_aggregation_bindings() + ->TakePrivateAggregationRequests(), + expected_contribution.Clone()); + } + + // Invalid bucket dictionary, which has no "baseValue" key. { ContextRecyclerScope scope(context_recycler); std::vector<std::string> error_msgs; @@ -1917,18 +1960,18 @@ "TypeError: Invalid bucket dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } - // Invalid bucket dictionary, whose base_value is invalid. + // Invalid bucket dictionary, whose baseValue is invalid. { ContextRecyclerScope scope(context_recycler); std::vector<std::string> error_msgs; gin::Dictionary bucket_dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - bucket_dict.Set("base_value", std::string("notValidBaseValue")); + bucket_dict.Set("baseValue", std::string("notValidBaseValue")); gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); dict.Set("bucket", bucket_dict); @@ -1941,18 +1984,18 @@ "TypeError: Invalid bucket dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } - // Invalid bucket dictionary, whose scale is not Number. + // Invalid bucket dictionary, whose scale is not a Number. { ContextRecyclerScope scope(context_recycler); std::vector<std::string> error_msgs; gin::Dictionary bucket_dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - bucket_dict.Set("base_value", std::string("winningBid")); + bucket_dict.Set("baseValue", std::string("winningBid")); bucket_dict.Set("scale", std::string("255")); gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); @@ -1966,18 +2009,18 @@ "TypeError: Invalid bucket dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } - // Invalid bucket dictionary, whose offset is not BigInt. + // Invalid bucket dictionary, whose offset is not a BigInt. { ContextRecyclerScope scope(context_recycler); std::vector<std::string> error_msgs; gin::Dictionary bucket_dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - bucket_dict.Set("base_value", std::string("winningBid")); + bucket_dict.Set("baseValue", std::string("winningBid")); bucket_dict.Set("offset", 255); gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); @@ -1991,7 +2034,7 @@ "TypeError: Invalid bucket dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -2002,7 +2045,7 @@ gin::Dictionary value_dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - value_dict.Set("base_value", std::string("winningBid")); + value_dict.Set("baseValue", std::string("winningBid")); value_dict.Set("scale", 2); value_dict.Set("offset", -5); @@ -2010,33 +2053,28 @@ dict.Set("bucket", std::string("1596")); dict.Set("value", value_dict); - auto signal_value = auction_worklet::mojom::SignalBucketOrValue::New( + auto signal_value = auction_worklet::mojom::SignalValue::New( /*base_value=*/auction_worklet::mojom::BaseValue::kWinningBid, - /*scale=*/2, /*has_scale*/ true, - /*offset=*/ - auction_worklet::mojom::Offset::New(/*value=*/5, - /*is_negative=*/true)); + /*scale=*/2, + /*offset=*/-5); Run(scope, script, "test", error_msgs, gin::ConvertToV8(helper_->isolate(), dict)); EXPECT_THAT(error_msgs, ElementsAre()); - auto expected_contribution = - auction_worklet::mojom::AggregatableReportForEventContribution::New( + auction_worklet::mojom::AggregatableReportForEventContribution + expected_contribution( /*bucket=*/auction_worklet::mojom::ForEventSignalBucket:: NewIdBucket(1596), - /*value=*/auction_worklet::mojom::ForEventSignalValue:: - NewSignalValue(std::move(signal_value))); + /*value=*/ + auction_worklet::mojom::ForEventSignalValue::NewSignalValue( + std::move(signal_value)), + /*event_type=*/kReservedWin); - ExpectPrivateAggregationForEventRequestsEqual( + ExpectOneForEventRequestEqualTo( context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win"), + ->TakePrivateAggregationRequests(), expected_contribution.Clone()); - - ExpectPrivateAggregationForEventRequestsEqual( - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss"), - std::move(expected_contribution)); } // Invalid value dictionary, which has no base_value key @@ -2059,7 +2097,7 @@ "TypeError: Invalid value dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -2080,7 +2118,7 @@ "Bucket must be a BigInt or a dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -2101,7 +2139,7 @@ "Value must be an integer or a dictionary.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") + ->TakePrivateAggregationRequests() .empty()); } @@ -2122,10 +2160,7 @@ "BigInt must be non-negative.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } @@ -2146,10 +2181,7 @@ "Value must be non-negative.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } @@ -2170,10 +2202,7 @@ "argument.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } @@ -2194,10 +2223,7 @@ "argument.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } @@ -2213,10 +2239,7 @@ EXPECT_THAT(error_msgs, ElementsAre()); EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.win") - .empty()); - EXPECT_TRUE(context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationForEventRequests("reserved.loss") + ->TakePrivateAggregationRequests() .empty()); } } @@ -2235,9 +2258,6 @@ // Exercise PrivateAggregationBindings, and make sure they reset properly. TEST_F(ContextRecyclerPrivateAggregationDisabledTest, PrivateAggregationBindings) { - using PrivateAggregationRequests = - std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>; - const char kScript[] = R"( function test(args) { // Passing BigInts in directly is complicated so we construct them from @@ -2271,10 +2291,9 @@ ElementsAre("https://example.org/script.js:8 Uncaught ReferenceError: " "privateAggregation is not defined.")); - PrivateAggregationRequests pa_requests = - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationRequests(); - ASSERT_TRUE(pa_requests.empty()); + ASSERT_TRUE(context_recycler.private_aggregation_bindings() + ->TakePrivateAggregationRequests() + .empty()); } } @@ -2293,9 +2312,6 @@ // Exercise PrivateAggregationBindings, and make sure they reset properly. TEST_F(ContextRecyclerPrivateAggregationDisabledForFledgeOnlyTest, PrivateAggregationBindings) { - using PrivateAggregationRequests = - std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>; - const char kScript[] = R"( function test(args) { // Passing BigInts in directly is complicated so we construct them from @@ -2329,10 +2345,9 @@ ElementsAre("https://example.org/script.js:8 Uncaught ReferenceError: " "privateAggregation is not defined.")); - PrivateAggregationRequests pa_requests = - context_recycler.private_aggregation_bindings() - ->TakePrivateAggregationRequests(); - ASSERT_TRUE(pa_requests.empty()); + ASSERT_TRUE(context_recycler.private_aggregation_bindings() + ->TakePrivateAggregationRequests() + .empty()); } }
diff --git a/content/services/auction_worklet/private_aggregation_bindings.cc b/content/services/auction_worklet/private_aggregation_bindings.cc index 82f7eb5..7e7d9ce 100644 --- a/content/services/auction_worklet/private_aggregation_bindings.cc +++ b/content/services/auction_worklet/private_aggregation_bindings.cc
@@ -13,8 +13,8 @@ #include "base/check.h" #include "base/feature_list.h" -#include "base/notreached.h" #include "base/ranges/algorithm.h" +#include "base/strings/string_util.h" #include "content/common/aggregatable_report.mojom.h" #include "content/common/private_aggregation_features.h" #include "content/services/auction_worklet/auction_v8_helper.h" @@ -54,10 +54,10 @@ } // If returns `absl::nullopt`, will output an error to `error_out`. -// Modified from worklet_utils::ConvertBigIntToUint128(). -absl::optional<auction_worklet::mojom::OffsetPtr> ConvertBigIntToOffset( - v8::Local<v8::BigInt> bigint, - std::string* error_out) { +// Modified from `worklet_utils::ConvertBigIntToUint128()`. +absl::optional<auction_worklet::mojom::BucketOffsetPtr> +ConvertBigIntToBucketOffset(v8::Local<v8::BigInt> bigint, + std::string* error_out) { if (bigint.IsEmpty()) { *error_out = "Failed to interpret as BigInt"; return absl::nullopt; @@ -74,79 +74,120 @@ uint64_t words[2] = {0, 0}; // Least significant to most significant. bigint->ToWordsArray(&sign_bit, &word_count, words); - return auction_worklet::mojom::Offset::New( + return auction_worklet::mojom::BucketOffset::New( absl::MakeUint128(words[1], words[0]), /*is_negative=*/sign_bit); } -absl::optional<auction_worklet::mojom::SignalBucketOrValuePtr> -GetSignalBucketOrValue(v8::Isolate* isolate, - v8::Local<v8::Value> input, - bool is_bucket) { +// TODO(qingxinwu): Factor out common code shared between this function and +// GetSignalValue to reduce duplicate code. +absl::optional<auction_worklet::mojom::SignalBucketPtr> GetSignalBucket( + v8::Isolate* isolate, + v8::Local<v8::Value> input) { DCHECK(input->IsObject()); gin::Dictionary result_dict(isolate, input.As<v8::Object>()); std::string base_value_string; - if (!result_dict.Get("base_value", &base_value_string)) + if (!result_dict.Get("baseValue", &base_value_string)) { return absl::nullopt; + } absl::optional<auction_worklet::mojom::BaseValue> base_value_opt = BaseValueStringToEnum(base_value_string); - if (!base_value_opt.has_value()) + if (!base_value_opt.has_value()) { return absl::nullopt; + } - double scale = 0.0; + double scale = 1.0; v8::Local<v8::Value> js_scale; - bool has_scale = false; if (result_dict.Get("scale", &js_scale) && !js_scale.IsEmpty() && !js_scale->IsNullOrUndefined()) { - if (!js_scale->IsNumber()) + if (!js_scale->IsNumber()) { return absl::nullopt; - + } + // TODO(qingxinwu): Return empty if scale is NaN or infinite. scale = js_scale.As<v8::Number>()->Value(); - has_scale = true; } v8::Local<v8::Value> js_offset; - if (!result_dict.Get("offset", &js_offset)) { - return auction_worklet::mojom::SignalBucketOrValue::New( - base_value_opt.value(), scale, has_scale, - /*offset=*/nullptr); + if (!result_dict.Get("offset", &js_offset) || js_offset.IsEmpty() || + js_offset->IsNullOrUndefined()) { + return auction_worklet::mojom::SignalBucket::New(base_value_opt.value(), + scale, + /*offset=*/nullptr); } - auction_worklet::mojom::OffsetPtr offset; - // Offset has to be BigInt for bucket, and int for value. - if (is_bucket && js_offset->IsBigInt()) { - std::string error; - - absl::optional<auction_worklet::mojom::OffsetPtr> maybe_offset = - ConvertBigIntToOffset(js_offset.As<v8::BigInt>(), &error); - if (!maybe_offset.has_value()) - return nullptr; - - offset = std::move(maybe_offset.value()); - } else if (!is_bucket && js_offset->IsInt32()) { - // Convert it to int128 as well to allow value dictionary share the same - // mojo type with bucket for simplicity. It will be parsed back to int - // when used. - int value_offset = js_offset.As<v8::Int32>()->Value(); - offset = - auction_worklet::mojom::Offset::New(std::abs(value_offset), - /*is_negative=*/value_offset < 0); - } else { + auction_worklet::mojom::BucketOffsetPtr offset; + // Offset must be BigInt for bucket. + if (!js_offset->IsBigInt()) { return absl::nullopt; } - return auction_worklet::mojom::SignalBucketOrValue::New( - base_value_opt.value(), scale, has_scale, std::move(offset)); + // TODO(qingxinwu): `error` is ignored currently. Report it and consider + // surfacing more informative errors like "offset must be BigInt for bucket". + std::string error; + absl::optional<auction_worklet::mojom::BucketOffsetPtr> maybe_offset = + ConvertBigIntToBucketOffset(js_offset.As<v8::BigInt>(), &error); + if (!maybe_offset.has_value()) { + return nullptr; + } + offset = std::move(maybe_offset.value()); + return auction_worklet::mojom::SignalBucket::New(base_value_opt.value(), + scale, std::move(offset)); +} + +absl::optional<auction_worklet::mojom::SignalValuePtr> GetSignalValue( + v8::Isolate* isolate, + v8::Local<v8::Value> input) { + DCHECK(input->IsObject()); + gin::Dictionary result_dict(isolate, input.As<v8::Object>()); + + std::string base_value_string; + if (!result_dict.Get("baseValue", &base_value_string)) { + return absl::nullopt; + } + + absl::optional<auction_worklet::mojom::BaseValue> base_value_opt = + BaseValueStringToEnum(base_value_string); + if (!base_value_opt.has_value()) { + return absl::nullopt; + } + + double scale = 1.0; + v8::Local<v8::Value> js_scale; + if (result_dict.Get("scale", &js_scale) && !js_scale.IsEmpty() && + !js_scale->IsNullOrUndefined()) { + if (!js_scale->IsNumber()) { + return absl::nullopt; + } + // TODO(b/266615909): Disallow scale being NaN or infinite. + scale = js_scale.As<v8::Number>()->Value(); + } + + v8::Local<v8::Value> js_offset; + if (!result_dict.Get("offset", &js_offset) || js_offset.IsEmpty() || + js_offset->IsNullOrUndefined()) { + return auction_worklet::mojom::SignalValue::New(base_value_opt.value(), + scale, + /*offset=*/0); + } + + // Offset must be int32 for value. + if (!js_offset->IsInt32()) { + return absl::nullopt; + } + int32_t offset = js_offset.As<v8::Int32>()->Value(); + return auction_worklet::mojom::SignalValue::New(base_value_opt.value(), scale, + offset); } auction_worklet::mojom::AggregatableReportForEventContributionPtr ParseForEventContribution(v8::Isolate* isolate, - v8::Local<v8::Value> arg, + const std::string& event_type, + v8::Local<v8::Value> arg_contribution, std::string* error) { gin::Dictionary dict(isolate); - bool success = gin::ConvertFromV8(isolate, arg, &dict); + bool success = gin::ConvertFromV8(isolate, arg_contribution, &dict); DCHECK(success); v8::Local<v8::Value> js_bucket; @@ -182,9 +223,8 @@ bucket = auction_worklet::mojom::ForEventSignalBucket::NewIdBucket( maybe_bucket.value()); } else if (js_bucket->IsObject()) { - absl::optional<auction_worklet::mojom::SignalBucketOrValuePtr> - maybe_signal_bucket_ptr = - GetSignalBucketOrValue(isolate, js_bucket, /*is_bucket=*/true); + absl::optional<auction_worklet::mojom::SignalBucketPtr> + maybe_signal_bucket_ptr = GetSignalBucket(isolate, js_bucket); if (!maybe_signal_bucket_ptr.has_value()) { *error = "Invalid bucket dictionary"; return nullptr; @@ -204,9 +244,8 @@ return nullptr; } } else if (js_value->IsObject()) { - absl::optional<auction_worklet::mojom::SignalBucketOrValuePtr> - maybe_signal_value_ptr = - GetSignalBucketOrValue(isolate, js_value, /*is_bucket=*/false); + absl::optional<auction_worklet::mojom::SignalValuePtr> + maybe_signal_value_ptr = GetSignalValue(isolate, js_value); if (!maybe_signal_value_ptr.has_value()) { *error = "Invalid value dictionary"; return nullptr; @@ -222,11 +261,15 @@ } return auction_worklet::mojom::AggregatableReportForEventContribution::New( - std::move(bucket), std::move(value)); + std::move(bucket), std::move(value), std::move(event_type)); } } // namespace +const char kReservedAlways[] = "reserved.always"; +const char kReservedWin[] = "reserved.win"; +const char kReservedLoss[] = "reserved.loss"; + PrivateAggregationBindings::PrivateAggregationBindings( AuctionV8Helper* v8_helper, bool private_aggregation_permissions_policy_allowed) @@ -285,8 +328,6 @@ void PrivateAggregationBindings::Reset() { private_aggregation_contributions_.clear(); - private_aggregation_for_event_win_contributions_.clear(); - private_aggregation_for_event_loss_contributions_.clear(); debug_mode_details_.is_enabled = false; debug_mode_details_.debug_key = nullptr; } @@ -298,7 +339,7 @@ requests.reserve(private_aggregation_contributions_.size()); base::ranges::transform( private_aggregation_contributions_, std::back_inserter(requests), - [this](content::mojom::AggregatableReportHistogramContributionPtr& + [this](auction_worklet::mojom::AggregatableReportContributionPtr& contribution) { return auction_worklet::mojom::PrivateAggregationRequest::New( std::move(contribution), @@ -311,23 +352,6 @@ return requests; } -std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> -PrivateAggregationBindings::TakePrivateAggregationForEventRequests( - const std::string& event_type) { - if (event_type == "reserved.win") { - return PrivateAggregationRequestsFromContribution( - std::move(private_aggregation_for_event_win_contributions_)); - } else if (event_type == "reserved.loss") { - return PrivateAggregationRequestsFromContribution( - std::move(private_aggregation_for_event_loss_contributions_)); - } else { - // Todo(qingxinwu): Support other event types (maybe arbitrary), such as - // "click". - NOTREACHED(); - return {}; - } -} - void PrivateAggregationBindings::SendHistogramReport( const v8::FunctionCallbackInfo<v8::Value>& args) { PrivateAggregationBindings* bindings = @@ -344,7 +368,8 @@ } bindings->private_aggregation_contributions_.push_back( - std::move(contribution)); + auction_worklet::mojom::AggregatableReportContribution:: + NewHistogramContribution(std::move(contribution))); } void PrivateAggregationBindings::ReportContributionForEvent( @@ -367,9 +392,17 @@ return; } + if (base::StartsWith(event_type, "reserved.") && event_type != kReservedWin && + event_type != kReservedLoss && event_type != kReservedAlways) { + // Don't throw an error if an invalid reserved event type is provided, to + // provide forward compatibility with new reserved event types added later. + return; + } + std::string error; auction_worklet::mojom::AggregatableReportForEventContributionPtr - contribution = ParseForEventContribution(isolate, args[1], &error); + contribution = + ParseForEventContribution(isolate, event_type, args[1], &error); if (contribution.is_null()) { DCHECK(base::IsStringUTF8(error)); @@ -378,15 +411,9 @@ return; } - // TODO(qingxinwu): Consider throwing an error if `event_type` has "reserved." - // prefix, but is not recognized as one of the reserved event types. - if (event_type == "reserved.win") { - bindings->private_aggregation_for_event_win_contributions_.push_back( - std::move(contribution)); - } else if (event_type == "reserved.loss") { - bindings->private_aggregation_for_event_loss_contributions_.push_back( - std::move(contribution)); - } + bindings->private_aggregation_contributions_.push_back( + auction_worklet::mojom::AggregatableReportContribution:: + NewForEventContribution(std::move(contribution))); } void PrivateAggregationBindings::EnableDebugMode( @@ -401,27 +428,4 @@ bindings->debug_mode_details_); } -std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> -PrivateAggregationBindings::PrivateAggregationRequestsFromContribution( - std::vector< - auction_worklet::mojom::AggregatableReportForEventContributionPtr> - contributions) { - std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> - requests; - requests.reserve(contributions.size()); - base::ranges::transform( - contributions, std::back_inserter(requests), - [this](auction_worklet::mojom::AggregatableReportForEventContributionPtr& - contribution) { - return auction_worklet::mojom::PrivateAggregationForEventRequest::New( - std::move(contribution), - // TODO(alexmt): consider allowing this to be set - content::mojom::AggregationServiceMode::kDefault, - debug_mode_details_.Clone()); - }); - contributions.clear(); - - return requests; -} - } // namespace auction_worklet
diff --git a/content/services/auction_worklet/private_aggregation_bindings.h b/content/services/auction_worklet/private_aggregation_bindings.h index 9a865fa..4cf813b0 100644 --- a/content/services/auction_worklet/private_aggregation_bindings.h +++ b/content/services/auction_worklet/private_aggregation_bindings.h
@@ -18,6 +18,11 @@ class AuctionV8Helper; +// Reserved event types for aggregatable report's for-event contribution. +CONTENT_EXPORT extern const char kReservedAlways[]; +CONTENT_EXPORT extern const char kReservedWin[]; +CONTENT_EXPORT extern const char kReservedLoss[]; + // Class to manage bindings for the Private Aggregation API. Expected to be used // for a context managed by `ContextRecycler`. Throws exceptions when invalid // arguments are detected. @@ -40,9 +45,6 @@ std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr> TakePrivateAggregationRequests(); - std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> - TakePrivateAggregationForEventRequests(const std::string& event_type); - private: static void SendHistogramReport( const v8::FunctionCallbackInfo<v8::Value>& args); @@ -50,14 +52,6 @@ const v8::FunctionCallbackInfo<v8::Value>& args); static void EnableDebugMode(const v8::FunctionCallbackInfo<v8::Value>& args); - // Creates private aggregation for event requests from given `contributions`, - // and returns the requests. - std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr> - PrivateAggregationRequestsFromContribution( - std::vector< - auction_worklet::mojom::AggregatableReportForEventContributionPtr> - contributions); - const raw_ptr<AuctionV8Helper> v8_helper_; bool private_aggregation_permissions_policy_allowed_; @@ -65,19 +59,9 @@ // Defaults to debug mode being disabled. content::mojom::DebugModeDetails debug_mode_details_; - // Contributions from `sendHistogramReport()`. - std::vector<content::mojom::AggregatableReportHistogramContributionPtr> + // Contributions from calling Private Aggregation APIs. + std::vector<auction_worklet::mojom::AggregatableReportContributionPtr> private_aggregation_contributions_; - - // Contributions of event type "reserved.win" from - // `reportContributionsForEvent()`. - std::vector<auction_worklet::mojom::AggregatableReportForEventContributionPtr> - private_aggregation_for_event_win_contributions_; - - // Contributions of event type "reserved.loss" from - // `reportContributionsForEvent()`. - std::vector<auction_worklet::mojom::AggregatableReportForEventContributionPtr> - private_aggregation_for_event_loss_contributions_; }; } // namespace auction_worklet
diff --git a/content/services/auction_worklet/public/mojom/private_aggregation_request.mojom b/content/services/auction_worklet/public/mojom/private_aggregation_request.mojom index 5a175ab..5d74dbd1 100644 --- a/content/services/auction_worklet/public/mojom/private_aggregation_request.mojom +++ b/content/services/auction_worklet/public/mojom/private_aggregation_request.mojom
@@ -8,14 +8,6 @@ import "content/common/private_aggregation_host.mojom"; import "mojo/public/mojom/base/int128.mojom"; -// Represents a request made to the Private Aggregation API (e.g. via -// `privateAggregation.sendHistogramReport()`). -struct PrivateAggregationRequest { - content.mojom.AggregatableReportHistogramContribution contribution; - content.mojom.AggregationServiceMode aggregation_mode; - content.mojom.DebugModeDetails debug_mode_details; -}; - // Indicates which value the browser should use to calculate the resulting // bucket or value. enum BaseValue { @@ -26,57 +18,77 @@ kBidRejectReason = 4, }; -// Offset to add/subtract to the auction result value. -// Offset's `value` should be Uint128 for contribution's bucket, and int for its -// value. To make things simpler, using Uint128 for both, and will parse it to -// int in code for contribution's value offset. -// We need to support negative offset value, so adding a is_negative bool to -// indicate whether offset is negative. -struct Offset { +// Bucket's offset to add/subtract to the auction result value. Offset's `value` +// should be Uint128. We need to support negative offset value, so adding a +// is_negative bool to indicate whether offset is negative. +struct BucketOffset { mojo_base.mojom.Uint128 value; bool is_negative; }; -// Both the bucket and value can be a SignalBucketOrValue. -// TODO(b/262009451): Find a way that supports calculating a Uint128 bucket from -// double base value (e.g., winning bid) using scale and offset. -struct SignalBucketOrValue { +// Bucket object of a contribution. +struct SignalBucket { // The name of the auction result value we want to report. BaseValue base_value; - // Optional scale factor by which we want to multiply the output. - // TODO(https://crbug.com/657632): Update when optional doubles are supported. - double scale; - bool has_scale; + // Scale factor by which we want to multiply the output. Default to 1.0. + double scale = 1.0; // Optional offset to add/subtract to the auction result value. - Offset? offset; + // TODO(qingxinwu): Inline BucketOffset's fields here with default values, and + // get rid of BucketOffset struct. + BucketOffset? offset; +}; + +// Value object of a contribution. +struct SignalValue { + // The name of the auction result value we want to report. + BaseValue base_value; + + // Scale factor by which we want to multiply the output. Default to 1.0. + double scale = 1.0; + + // Offset to add/subtract to the auction result value. Default to 0. + int32 offset = 0; }; // A bucket which is a 128bit ID or a SignalBucketOrValue which tells the // browser how to calculate the bucket. union ForEventSignalBucket { + // TODO(qingxinwu): Consider changing it to a more clear name. mojo_base.mojom.Uint128 id_bucket; - SignalBucketOrValue signal_bucket; + SignalBucket signal_bucket; }; // A value is an integer, or a SignalBucketOrValue which tells the browser how // to calculate the value. union ForEventSignalValue { int32 int_value; - SignalBucketOrValue signal_value; + SignalValue signal_value; }; -// A contribution contains a bucket and a value. +// A for-event contribution contains a bucket, a value, and an event_type. +// See https://github.com/WICG/turtledove/blob/main/FLEDGE_extended_PA_reporting.md#reporting-api-informal-specification struct AggregatableReportForEventContribution { ForEventSignalBucket bucket; ForEventSignalValue value; + + // Identifies the event type that triggers sending this report. + string event_type; }; -// Represents a request made to the extended Private Aggregation API (e.g. via -// `privateAggregation.reportContributionForEvent()`). -struct PrivateAggregationForEventRequest { - AggregatableReportForEventContribution contribution; +// `histogram_contribution` for sendHistogramReport(), and +// `for_event_contribution` for reportPrivateAggregationEvent(). +union AggregatableReportContribution { + content.mojom.AggregatableReportHistogramContribution histogram_contribution; + AggregatableReportForEventContribution for_event_contribution; +}; + +// Represents a request made to Private Aggregation API. It can be either +// sendHistogramReport() or reportPrivateAggregationEvent(), depending on the +// type of contribution. +struct PrivateAggregationRequest { + AggregatableReportContribution contribution; content.mojom.AggregationServiceMode aggregation_mode; content.mojom.DebugModeDetails debug_mode_details; };
diff --git a/content/services/auction_worklet/seller_worklet_unittest.cc b/content/services/auction_worklet/seller_worklet_unittest.cc index 188801d..dd669d5 100644 --- a/content/services/auction_worklet/seller_worklet_unittest.cc +++ b/content/services/auction_worklet/seller_worklet_unittest.cc
@@ -24,6 +24,7 @@ #include "content/common/private_aggregation_features.h" #include "content/services/auction_worklet/auction_v8_helper.h" #include "content/services/auction_worklet/public/mojom/auction_worklet_service.mojom.h" +#include "content/services/auction_worklet/public/mojom/seller_worklet.mojom.h" #include "content/services/auction_worklet/worklet_devtools_debug_test_util.h" #include "content/services/auction_worklet/worklet_test_util.h" #include "content/services/auction_worklet/worklet_v8_debug_test_util.h" @@ -3829,7 +3830,9 @@ class SellerWorkletPrivateAggregationEnabledTest : public SellerWorkletTest { public: SellerWorkletPrivateAggregationEnabledTest() { - scoped_feature_list_.InitAndEnableFeature(content::kPrivateAggregationApi); + scoped_feature_list_.InitAndEnableFeatureWithParameters( + content::kPrivateAggregationApi, + {{"fledge_extensions_enabled", "true"}}); } private: @@ -3837,31 +3840,53 @@ }; TEST_F(SellerWorkletPrivateAggregationEnabledTest, ScoreAd) { - mojom::PrivateAggregationRequestPtr kExpectedRequest1 = - mojom::PrivateAggregationRequest::New( + mojom::PrivateAggregationRequest kExpectedRequest1( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/123, - /*value=*/45), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - mojom::PrivateAggregationRequestPtr kExpectedRequest2 = - mojom::PrivateAggregationRequest::New( + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedRequest2( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/absl::MakeInt128(/*high=*/1, /*low=*/0), - /*value=*/1), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); + /*value=*/1)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + + mojom::PrivateAggregationRequest kExpectedForEventRequest1( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket(234), + /*value=*/mojom::ForEventSignalValue::NewIntValue(56), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest2( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket( + absl::MakeInt128(/*high=*/1, + /*low=*/0)), + /*value=*/mojom::ForEventSignalValue::NewIntValue(2), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); RunScoreAdWithJavascriptExpectingResult( - CreateScoreAdScript("5", - "privateAggregation.sendHistogramReport({bucket: " - "123n, value: 45})"), - 5, /*expected_errors=*/ - {}, mojom::ComponentAuctionModifiedBidParamsPtr(), + CreateScoreAdScript("5", R"( + privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )"), + 5, /*expected_errors=*/{}, + mojom::ComponentAuctionModifiedBidParamsPtr(), /*expected_data_version=*/absl::nullopt, /*expected_debug_loss_report_url=*/absl::nullopt, /*expected_debug_win_report_url=*/absl::nullopt, @@ -3898,11 +3923,15 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest2.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest2.Clone()); RunScoreAdWithJavascriptExpectingResult( - CreateScoreAdScript("5", - "privateAggregation.sendHistogramReport(" - "{bucket: 18446744073709551616n, value: 1})"), + CreateScoreAdScript("5", R"( + privateAggregation.sendHistogramReport({bucket: 18446744073709551616n, + value: 1}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 18446744073709551616n, value: 2}); + )"), 5, /*expected_errors=*/{}, mojom::ComponentAuctionModifiedBidParamsPtr(), /*expected_data_version=*/absl::nullopt, @@ -3917,12 +3946,18 @@ PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); expected_pa_requests.push_back(kExpectedRequest2.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest2.Clone()); RunScoreAdWithJavascriptExpectingResult( CreateScoreAdScript("5", R"( privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); privateAggregation.sendHistogramReport({bucket: 18446744073709551616n, value: 1}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 18446744073709551616n, value: 2}); )"), 5, /*expected_errors=*/{}, mojom::ComponentAuctionModifiedBidParamsPtr(), @@ -3933,18 +3968,22 @@ std::move(expected_pa_requests)); } - // An unrelated exception after sendHistogramReport shouldn't block the report + // An unrelated exception after sendHistogramReport and + // reportContributionForEvent shouldn't block the reports. { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest1.Clone()); RunScoreAdWithJavascriptExpectingResult( CreateScoreAdScript("5", R"( privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); error; )"), 0, /*expected_errors=*/ - {"https://url.test/:6 Uncaught ReferenceError: error is not defined."}, + {"https://url.test/:8 Uncaught ReferenceError: error is not defined."}, mojom::ComponentAuctionModifiedBidParamsPtr(), /*expected_data_version=*/absl::nullopt, /*expected_debug_loss_report_url=*/absl::nullopt, @@ -3957,7 +3996,12 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New( + /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); + expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( + kExpectedForEventRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); @@ -3967,6 +4011,8 @@ R"( privateAggregation.enableDebugMode({debug_key: 1234n}); privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); )"), 5, /*expected_errors=*/{}, mojom::ComponentAuctionModifiedBidParamsPtr(), @@ -3981,12 +4027,12 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest2->contribution->Clone(), + kExpectedRequest2.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); @@ -4010,21 +4056,30 @@ } TEST_F(SellerWorkletPrivateAggregationEnabledTest, ReportResult) { - mojom::PrivateAggregationRequestPtr kExpectedRequest1 = - mojom::PrivateAggregationRequest::New( + mojom::PrivateAggregationRequest kExpectedRequest1( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/123, - /*value=*/45), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); - mojom::PrivateAggregationRequestPtr kExpectedRequest2 = - mojom::PrivateAggregationRequest::New( + /*value=*/45)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedRequest2( + mojom::AggregatableReportContribution::NewHistogramContribution( content::mojom::AggregatableReportHistogramContribution::New( /*bucket=*/absl::MakeInt128(/*high=*/1, /*low=*/0), - /*value=*/1), - content::mojom::AggregationServiceMode::kDefault, - content::mojom::DebugModeDetails::New()); + /*value=*/1)), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + mojom::PrivateAggregationRequest kExpectedForEventRequest( + mojom::AggregatableReportContribution::NewForEventContribution( + mojom::AggregatableReportForEventContribution::New( + /*bucket=*/mojom::ForEventSignalBucket::NewIdBucket(234), + /*value=*/mojom::ForEventSignalValue::NewIntValue(56), + /*event_type=*/"reserved.win")), + content::mojom::AggregationServiceMode::kDefault, + content::mojom::DebugModeDetails::New()); + // Only sendHistogramReport() is called. { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(kExpectedRequest1.Clone()); @@ -4038,6 +4093,42 @@ /*expected_errors=*/{}); } + // Only reportContributionForEvent() is called. + { + PrivateAggregationRequests expected_pa_requests; + expected_pa_requests.push_back(kExpectedForEventRequest.Clone()); + + RunReportResultCreatedScriptExpectingResult( + "5", + R"( + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )", + /*expected_signals_for_winner=*/"5", + /*expected_report_url=*/absl::nullopt, /*expected_ad_beacon_map=*/{}, + std::move(expected_pa_requests), + /*expected_errors=*/{}); + } + + // Both sendHistogramReport() and reportContributionForEvent() are called. + { + PrivateAggregationRequests expected_pa_requests; + expected_pa_requests.push_back(kExpectedRequest1.Clone()); + expected_pa_requests.push_back(kExpectedForEventRequest.Clone()); + + RunReportResultCreatedScriptExpectingResult( + "5", + R"( + privateAggregation.sendHistogramReport({bucket: 123n, value: 45}); + privateAggregation.reportContributionForEvent( + "reserved.win", {bucket: 234n, value: 56}); + )", + /*expected_signals_for_winner=*/"5", + /*expected_report_url=*/absl::nullopt, /*expected_ad_beacon_map=*/{}, + std::move(expected_pa_requests), + /*expected_errors=*/{}); + } + // Set the private-aggregation permissions policy to disallowed. { permissions_policy_state_ = @@ -4130,7 +4221,7 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, content::mojom::DebugKey::New(1234u)))); @@ -4151,12 +4242,12 @@ { PrivateAggregationRequests expected_pa_requests; expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest1->contribution->Clone(), + kExpectedRequest1.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr))); expected_pa_requests.push_back(mojom::PrivateAggregationRequest::New( - kExpectedRequest2->contribution->Clone(), + kExpectedRequest2.contribution->Clone(), content::mojom::AggregationServiceMode::kDefault, content::mojom::DebugModeDetails::New( /*is_enabled=*/true, /*debug_key=*/nullptr)));
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index f2da991..9f48acb9 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -450,11 +450,6 @@ override_web_preferences_callback_.Run(prefs); } -base::FilePath ShellContentBrowserClient::GetFontLookupTableCacheDir() { - return browser_context()->GetPath().Append( - FILE_PATH_LITERAL("FontLookupTableCache")); -} - std::unique_ptr<content::DevToolsManagerDelegate> ShellContentBrowserClient::CreateDevToolsManagerDelegate() { return std::make_unique<ShellDevToolsManagerDelegate>(browser_context());
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 176a7fe1..f070810b 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -77,7 +77,6 @@ override; void OverrideWebkitPrefs(WebContents* web_contents, blink::web_pref::WebPreferences* prefs) override; - base::FilePath GetFontLookupTableCacheDir() override; std::unique_ptr<content::DevToolsManagerDelegate> CreateDevToolsManagerDelegate() override; void ExposeInterfacesToRenderer(
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 3d3a84f..a6da6a3 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2279,6 +2279,7 @@ "../browser/interest_group/auction_url_loader_factory_proxy_unittest.cc", "../browser/interest_group/auction_worklet_manager_unittest.cc", "../browser/interest_group/interest_group_k_anonymity_manager_unittest.cc", + "../browser/interest_group/interest_group_pa_report_util_unittest.cc", "../browser/interest_group/interest_group_permissions_cache_unittest.cc", "../browser/interest_group/interest_group_permissions_checker_unittest.cc", "../browser/interest_group/interest_group_priority_util_unittest.cc",
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac-before-11.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac-before-11.txt new file mode 100644 index 0000000..558243b --- /dev/null +++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac-before-11.txt
@@ -0,0 +1 @@ +AXTextField AXHelp='My name is Garaventa the weird. (QED) Where are my marbles?'
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt index 558243b..0a71ab99 100644 --- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt +++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-mac.txt
@@ -1 +1 @@ -AXTextField AXHelp='My name is Garaventa the weird. (QED) Where are my marbles?' +AXTextField accessibilityCustomContent=[{label: 'description', value: 'My name is Garaventa the weird. (QED) Where are my marbles?'}]
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element.html b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element.html index 3663ab3..e9bc534 100644 --- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element.html +++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element.html
@@ -4,6 +4,7 @@ @AURALINUX-DENY:name* @MAC-DENY:AXDescription* @MAC-DENY:AXValue* +@MAC-ALLOW:accessibilityCustomContent @MAC-ALLOW:AXHelp* @WIN-DENY:name* -->
diff --git a/content/test/data/accessibility/aria/aria-describedby-expected-mac-before-11.txt b/content/test/data/accessibility/aria/aria-describedby-expected-mac-before-11.txt new file mode 100644 index 0000000..74a7926 --- /dev/null +++ b/content/test/data/accessibility/aria/aria-describedby-expected-mac-before-11.txt
@@ -0,0 +1,5 @@ +AXWebArea AXRoleDescription='HTML content' +++AXTextField AXHelp='Your username should be your email id' AXRoleDescription='text field' +++AXGroup AXSubrole=AXUserInterfaceTooltip AXRoleDescription='tooltip' AXTitle='Your username should be your email id' +++++AXStaticText AXRoleDescription='text' AXValue='Your username should be your email id' +++AXTextField AXHelp='mmddyy' AXRoleDescription='text field'
diff --git a/content/test/data/accessibility/aria/aria-describedby-expected-mac.txt b/content/test/data/accessibility/aria/aria-describedby-expected-mac.txt index 74a7926..248cf77 100644 --- a/content/test/data/accessibility/aria/aria-describedby-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-describedby-expected-mac.txt
@@ -1,5 +1,5 @@ AXWebArea AXRoleDescription='HTML content' -++AXTextField AXHelp='Your username should be your email id' AXRoleDescription='text field' +++AXTextField AXRoleDescription='text field' accessibilityCustomContent=[{label: 'description', value: 'Your username should be your email id'}] ++AXGroup AXSubrole=AXUserInterfaceTooltip AXRoleDescription='tooltip' AXTitle='Your username should be your email id' ++++AXStaticText AXRoleDescription='text' AXValue='Your username should be your email id' -++AXTextField AXHelp='mmddyy' AXRoleDescription='text field' +++AXTextField AXRoleDescription='text field' accessibilityCustomContent=[{label: 'description', value: 'mmddyy'}]
diff --git a/content/test/data/accessibility/aria/aria-describedby-updates.html b/content/test/data/accessibility/aria/aria-describedby-updates.html index 5e8b6bb..f4259b2 100644 --- a/content/test/data/accessibility/aria/aria-describedby-updates.html +++ b/content/test/data/accessibility/aria/aria-describedby-updates.html
@@ -3,7 +3,8 @@ @BLINK-ALLOW:description=* @WIN-ALLOW:description=* @MAC-ALLOW:AXDescription -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @BLINK-DENY:descriptionFrom* --> <!DOCTYPE html>
diff --git a/content/test/data/accessibility/aria/aria-describedby.html b/content/test/data/accessibility/aria/aria-describedby.html index d7f8089..122f331 100644 --- a/content/test/data/accessibility/aria/aria-describedby.html +++ b/content/test/data/accessibility/aria/aria-describedby.html
@@ -1,7 +1,8 @@ <!-- @MAC-ALLOW:AXRoleDescription @MAC-ALLOW:AXDescription -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @WIN-ALLOW:xml-roles:* @WIN-ALLOW:description* @WIN-DENY:name*
diff --git a/content/test/data/accessibility/aria/aria-tooltip-expected-mac-before-11.txt b/content/test/data/accessibility/aria/aria-tooltip-expected-mac-before-11.txt new file mode 100644 index 0000000..8765222b --- /dev/null +++ b/content/test/data/accessibility/aria/aria-tooltip-expected-mac-before-11.txt
@@ -0,0 +1,4 @@ +AXWebArea AXRoleDescription='HTML content' +++AXTextField AXHelp='Your username should be your email id' AXRoleDescription='text field' +++AXGroup AXSubrole=AXUserInterfaceTooltip AXRoleDescription='tooltip' AXTitle='Your username should be your email id' +++++AXStaticText AXRoleDescription='text' AXValue='Your username should be your email id'
diff --git a/content/test/data/accessibility/aria/aria-tooltip-expected-mac.txt b/content/test/data/accessibility/aria/aria-tooltip-expected-mac.txt index 8765222b..92f6bb6c 100644 --- a/content/test/data/accessibility/aria/aria-tooltip-expected-mac.txt +++ b/content/test/data/accessibility/aria/aria-tooltip-expected-mac.txt
@@ -1,4 +1,4 @@ AXWebArea AXRoleDescription='HTML content' -++AXTextField AXHelp='Your username should be your email id' AXRoleDescription='text field' +++AXTextField AXRoleDescription='text field' accessibilityCustomContent=[{label: 'description', value: 'Your username should be your email id'}] ++AXGroup AXSubrole=AXUserInterfaceTooltip AXRoleDescription='tooltip' AXTitle='Your username should be your email id' ++++AXStaticText AXRoleDescription='text' AXValue='Your username should be your email id'
diff --git a/content/test/data/accessibility/aria/aria-tooltip.html b/content/test/data/accessibility/aria/aria-tooltip.html index 5caf4667..7cba85f 100644 --- a/content/test/data/accessibility/aria/aria-tooltip.html +++ b/content/test/data/accessibility/aria/aria-tooltip.html
@@ -1,6 +1,7 @@ <!-- @MAC-ALLOW:AXRoleDescription -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @WIN-ALLOW:xml-roles:* @WIN-DENY:name* -->
diff --git a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac-before-11.txt b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac-before-11.txt new file mode 100644 index 0000000..b4862c8 --- /dev/null +++ b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac-before-11.txt
@@ -0,0 +1,9 @@ +AXWebArea AXRoleDescription='HTML content' +++AXTextField AXPlaceholderValue='aria-placeholder1' AXRoleDescription='text field' +++AXTextField AXPlaceholderValue='placeholder2' AXRoleDescription='text field' +++AXTextField AXDescription='aria-label3' AXPlaceholderValue='placeholder3' AXRoleDescription='text field' +++AXTextField AXDescription='aria-label4' AXPlaceholderValue='aria-placeholder4' AXRoleDescription='text field' +++AXTextField AXDescription='aria-label5' AXHelp='aria-description5' AXPlaceholderValue='placeholder5' AXRoleDescription='text field' +++AXGroup AXRoleDescription='group' +++++AXStaticText AXRoleDescription='text' AXValue='aria-description5' +++AXTextField AXDescription='title6' AXPlaceholderValue='aria-placeholder6' AXRoleDescription='text field' \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac.txt b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac.txt index b4862c8..d6fc51e 100644 --- a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac.txt +++ b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-mac.txt
@@ -3,7 +3,7 @@ ++AXTextField AXPlaceholderValue='placeholder2' AXRoleDescription='text field' ++AXTextField AXDescription='aria-label3' AXPlaceholderValue='placeholder3' AXRoleDescription='text field' ++AXTextField AXDescription='aria-label4' AXPlaceholderValue='aria-placeholder4' AXRoleDescription='text field' -++AXTextField AXDescription='aria-label5' AXHelp='aria-description5' AXPlaceholderValue='placeholder5' AXRoleDescription='text field' +++AXTextField AXDescription='aria-label5' AXPlaceholderValue='placeholder5' AXRoleDescription='text field' accessibilityCustomContent=[{label: 'description', value: 'aria-description5'}] ++AXGroup AXRoleDescription='group' ++++AXStaticText AXRoleDescription='text' AXValue='aria-description5' -++AXTextField AXDescription='title6' AXPlaceholderValue='aria-placeholder6' AXRoleDescription='text field' \ No newline at end of file +++AXTextField AXDescription='title6' AXPlaceholderValue='aria-placeholder6' AXRoleDescription='text field'
diff --git a/content/test/data/accessibility/aria/input-text-aria-placeholder.html b/content/test/data/accessibility/aria/input-text-aria-placeholder.html index da2df1a..4c00694 100644 --- a/content/test/data/accessibility/aria/input-text-aria-placeholder.html +++ b/content/test/data/accessibility/aria/input-text-aria-placeholder.html
@@ -2,7 +2,8 @@ @MAC-ALLOW:AXRoleDescription @MAC-ALLOW:AXDescription @MAC-ALLOW:AXPlaceholderValue -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @WIN-ALLOW:placeholder* @WIN-ALLOW:description* @BLINK-ALLOW:placeholder=*
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-mac-before-11.txt b/content/test/data/accessibility/html/button-name-calc-expected-mac-before-11.txt new file mode 100644 index 0000000..50726a6 --- /dev/null +++ b/content/test/data/accessibility/html/button-name-calc-expected-mac-before-11.txt
@@ -0,0 +1,20 @@ +AXWebArea +++AXButton AXTitle='InnerText0' +++AXButton AXHelp='Title1' AXTitle='InnerText1' +++AXButton AXDescription='AriaLabel2' AXHelp='Title2' +++AXButton AXHelp='Title3' AXTitle='LabelledBy3' +++AXButton AXHelp='DescribedBy4' AXTitle='LabelledBy4' +++AXButton AXHelp='DescribedBy5' AXTitle='InnerText5' +++AXButton AXTitle='Outer inner' +++++AXStaticText +++++AXGroup +++++++AXStaticText +++AXButton AXTitle='Outer inner1' +++++AXStaticText +++++AXGroup AXDescription='inner1' +++++++AXStaticText +++AXButton AXTitle='Outer grandchild' +++++AXStaticText +++++AXGroup +++++++AXGroup +++++++++AXStaticText
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-mac.txt b/content/test/data/accessibility/html/button-name-calc-expected-mac.txt index 50726a6..f7eeb8f 100644 --- a/content/test/data/accessibility/html/button-name-calc-expected-mac.txt +++ b/content/test/data/accessibility/html/button-name-calc-expected-mac.txt
@@ -3,8 +3,8 @@ ++AXButton AXHelp='Title1' AXTitle='InnerText1' ++AXButton AXDescription='AriaLabel2' AXHelp='Title2' ++AXButton AXHelp='Title3' AXTitle='LabelledBy3' -++AXButton AXHelp='DescribedBy4' AXTitle='LabelledBy4' -++AXButton AXHelp='DescribedBy5' AXTitle='InnerText5' +++AXButton AXTitle='LabelledBy4' accessibilityCustomContent=[{label: 'description', value: 'DescribedBy4'}] +++AXButton AXTitle='InnerText5' accessibilityCustomContent=[{label: 'description', value: 'DescribedBy5'}] ++AXButton AXTitle='Outer inner' ++++AXStaticText ++++AXGroup
diff --git a/content/test/data/accessibility/html/button-name-calc.html b/content/test/data/accessibility/html/button-name-calc.html index 6dc8b71..20801c6 100644 --- a/content/test/data/accessibility/html/button-name-calc.html +++ b/content/test/data/accessibility/html/button-name-calc.html
@@ -8,6 +8,7 @@ @AURALINUX-ALLOW:explicit-name* @MAC-ALLOW:AXDescription @MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent @MAC-DENY:AXValue --> <html>
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-mac-before-11.txt b/content/test/data/accessibility/html/canvas-fallback-expected-mac-before-11.txt new file mode 100644 index 0000000..8d0c0be --- /dev/null +++ b/content/test/data/accessibility/html/canvas-fallback-expected-mac-before-11.txt
@@ -0,0 +1,15 @@ +AXWebArea +++AXGroup +++++AXGroup +++++++AXStaticText AXValue='Static fallback' +++++AXGroup +++++++AXStaticText AXValue='<newline> ' +++++++AXGroup AXHelp='Aria hidden paragraph in fallback content' +++++++++AXStaticText AXValue='Line breaking content in a fallback' +++++++AXStaticText AXValue='<newline> ' +++++++AXGroup AXHelp='Visibility hidden paragraph in fallback content' +++++++++AXStaticText AXValue='This is another paragraph in fallback' +++++++AXStaticText AXValue='<newline> ' +++++++AXStaticText AXValue='<newline> ' +++++++AXStaticText AXValue='<newline> ' +++++++AXStaticText AXValue='<newline> '
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-mac.txt b/content/test/data/accessibility/html/canvas-fallback-expected-mac.txt index 8d0c0be..9d603ed7 100644 --- a/content/test/data/accessibility/html/canvas-fallback-expected-mac.txt +++ b/content/test/data/accessibility/html/canvas-fallback-expected-mac.txt
@@ -4,10 +4,10 @@ ++++++AXStaticText AXValue='Static fallback' ++++AXGroup ++++++AXStaticText AXValue='<newline> ' -++++++AXGroup AXHelp='Aria hidden paragraph in fallback content' +++++++AXGroup accessibilityCustomContent=[{label: 'description', value: 'Aria hidden paragraph in fallback content'}] ++++++++AXStaticText AXValue='Line breaking content in a fallback' ++++++AXStaticText AXValue='<newline> ' -++++++AXGroup AXHelp='Visibility hidden paragraph in fallback content' +++++++AXGroup accessibilityCustomContent=[{label: 'description', value: 'Visibility hidden paragraph in fallback content'}] ++++++++AXStaticText AXValue='This is another paragraph in fallback' ++++++AXStaticText AXValue='<newline> ' ++++++AXStaticText AXValue='<newline> '
diff --git a/content/test/data/accessibility/html/canvas-fallback.html b/content/test/data/accessibility/html/canvas-fallback.html index ca91f144..7921666 100644 --- a/content/test/data/accessibility/html/canvas-fallback.html +++ b/content/test/data/accessibility/html/canvas-fallback.html
@@ -3,7 +3,8 @@ @BLINK-DENY:descriptionFrom* @BLINK-ALLOW:hierarchicalLevel* @MAC-DENY:AXDescription='To get missing image descriptions, open the context menu.' -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @WIN-DENY:description* @WIN-ALLOW:description=* @WIN-DENY:name*
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-mac-before-11.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-mac-before-11.txt new file mode 100644 index 0000000..1d197b2a --- /dev/null +++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-mac-before-11.txt
@@ -0,0 +1,7 @@ +AXWebArea +++AXCheckBox AXDescription='Title0' +++AXCheckBox AXHelp='Title1' AXTitle='Label1' +++AXCheckBox AXDescription='AriaLabel2' AXHelp='Title2' +++AXCheckBox AXHelp='Title3' AXTitle='LabelledBy3' +++AXCheckBox AXHelp='DescribedBy4' AXTitle='LabelledBy4' +++AXCheckBox AXHelp='DescribedBy5'
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-mac.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-mac.txt index 1d197b2a..8ee860a 100644 --- a/content/test/data/accessibility/html/checkbox-name-calc-expected-mac.txt +++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-mac.txt
@@ -3,5 +3,5 @@ ++AXCheckBox AXHelp='Title1' AXTitle='Label1' ++AXCheckBox AXDescription='AriaLabel2' AXHelp='Title2' ++AXCheckBox AXHelp='Title3' AXTitle='LabelledBy3' -++AXCheckBox AXHelp='DescribedBy4' AXTitle='LabelledBy4' -++AXCheckBox AXHelp='DescribedBy5' +++AXCheckBox AXTitle='LabelledBy4' accessibilityCustomContent=[{label: 'description', value: 'DescribedBy4'}] +++AXCheckBox accessibilityCustomContent=[{label: 'description', value: 'DescribedBy5'}]
diff --git a/content/test/data/accessibility/html/checkbox-name-calc.html b/content/test/data/accessibility/html/checkbox-name-calc.html index f4caf57..5f2e46b 100644 --- a/content/test/data/accessibility/html/checkbox-name-calc.html +++ b/content/test/data/accessibility/html/checkbox-name-calc.html
@@ -7,6 +7,7 @@ @AURALINUX-DENY:checkable @MAC-ALLOW:AXDescription @MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent @MAC-DENY:AXValue --> <html>
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac-before-11.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac-before-11.txt new file mode 100644 index 0000000..dbf4004 --- /dev/null +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac-before-11.txt
@@ -0,0 +1,6 @@ +AXWebArea +++AXTextArea AXDescription='label' +++AXTextArea AXHelp='description' +++AXTextArea AXDescription='title' +++AXGroup +++++AXStaticText AXValue='description'
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac.txt index dbf4004..f0f3db66 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac.txt +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-mac.txt
@@ -1,6 +1,6 @@ AXWebArea ++AXTextArea AXDescription='label' -++AXTextArea AXHelp='description' +++AXTextArea accessibilityCustomContent=[{label: 'description', value: 'description'}] ++AXTextArea AXDescription='title' ++AXGroup ++++AXStaticText AXValue='description'
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants.html b/content/test/data/accessibility/html/contenteditable-with-no-descendants.html index 9a2af794..2ea28f39 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants.html +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants.html
@@ -1,5 +1,6 @@ <!-- -@MAC-ALLOW:AXHelp +@MAC-ALLOW:accessibilityCustomContent +@MAC-ALLOW:AXHelp* @WIN-ALLOW:description* @WIN-ALLOW:IA2_STATE_EDITABLE @WIN-ALLOW:ia2_hypertext=*
diff --git a/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent-expected.txt b/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent-expected.txt index c4776dd..861bd660 100644 --- a/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent-expected.txt +++ b/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent-expected.txt
@@ -1,4 +1,6 @@ div.accessibilityCustomContent[0].label='description' div.accessibilityCustomContent[0].value='Text-description' div.accessibilityAttributeValue(AXHelp)=NULL -div_with_tooltip.accessibilityAttributeValue(AXHelp)='Description from describedby' +div_with_tooltip.accessibilityCustomContent[0].label='description' +div_with_tooltip.accessibilityCustomContent[0].value='Description from describedby' +div_with_tooltip.accessibilityAttributeValue(AXHelp)=NULL
diff --git a/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent.html b/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent.html index 39b8b0e..50be66b 100644 --- a/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent.html +++ b/content/test/data/accessibility/mac/description/aria-description-in-axcustomcontent.html
@@ -3,10 +3,12 @@ div.accessibilityCustomContent[0].label div.accessibilityCustomContent[0].value div.accessibilityAttributeValue(AXHelp) + div_with_tooltip.accessibilityCustomContent[0].label + div_with_tooltip.accessibilityCustomContent[0].value div_with_tooltip.accessibilityAttributeValue(AXHelp) --> <!-- -Note, this test will only run when macOS is greater or equal to 11. The purpose of the test is to show that AXHelp DOES NOT surface the aria-description string beginning with macOS 11 (instead, it can be found in AXCustomContent). +Note, this test will only run when macOS is greater or equal to 11. The purpose of the test is to show that, beginning with macOS 11, AXHelp DOES NOT surface the aria-description string or the content of aria-describedby (instead, it can be found in AXCustomContent). --> <!DOCTYPE html> <html>
diff --git a/content/test/data/attribution_reporting/interop/README.md b/content/test/data/attribution_reporting/interop/README.md index a5db5a9..d1c0941 100644 --- a/content/test/data/attribution_reporting/interop/README.md +++ b/content/test/data/attribution_reporting/interop/README.md
@@ -372,6 +372,20 @@ "trigger_debug_key": "789" } } + ], + + "verbose_debug_reports": [ + { + // Upper bound time at which the report would have been sent in + // milliseconds since the UNIX epoch. + "report_time": "123", + + // URL to which the report would have been sent. + "report_url": "https://reporting.example/.well-known/attribution-reporting/debug/verbose" + + // The body of the report. + "payload": [...] + } ] } }
diff --git a/content/test/data/attribution_reporting/interop/destination_limit.json b/content/test/data/attribution_reporting/interop/destination_limit.json index e8f49e6..75bd45a 100644 --- a/content/test/data/attribution_reporting/interop/destination_limit.json +++ b/content/test/data/attribution_reporting/interop/destination_limit.json
@@ -16,6 +16,7 @@ "url": "https://reporter1.test/register-source", "response": { "Attribution-Reporting-Register-Source": { + "debug_reporting": true, "destination": "https://destination1.test", "source_event_id": "111", "expiry": "86400" @@ -35,6 +36,7 @@ "url": "https://reporter1.test/register-source", "response": { "Attribution-Reporting-Register-Source": { + "debug_reporting": true, "destination": "https://destination2.test", "source_event_id": "222" } @@ -53,6 +55,7 @@ "url": "https://reporter2.test/register-source", "response": { "Attribution-Reporting-Register-Source": { + "debug_reporting": true, "destination": "https://destination2.test", "source_event_id": "333" } @@ -71,6 +74,7 @@ "url": "https://reporter1.test/register-source", "response": { "Attribution-Reporting-Register-Source": { + "debug_reporting": true, "destination": "https://destination2.test", "source_event_id": "444" } @@ -89,6 +93,7 @@ "url": "https://reporter1.test/register-source", "response": { "Attribution-Reporting-Register-Source": { + "debug_reporting": true, "destination": "https://destination3.test", "source_event_id": "555" } @@ -249,6 +254,21 @@ "report_time": "1643498373000", "report_url": "https://reporter1.test/.well-known/attribution-reporting/report-event-attribution" } + ], + "verbose_debug_reports": [ + { + "payload": [{ + "body": { + "attribution_destination": "https://destination2.test", + "limit": "1", + "source_event_id": "222", + "source_site": "https://source1.test" + }, + "type": "source-destination-limit" + }], + "report_time": "1643235575000", + "report_url": "https://reporter1.test/.well-known/attribution-reporting/debug/verbose" + } ] } }
diff --git a/content/test/data/attribution_reporting/register_trigger_headers_debug_reporting.html.mock-http-headers b/content/test/data/attribution_reporting/register_trigger_headers_debug_reporting.html.mock-http-headers index e791911..d901c1ba 100644 --- a/content/test/data/attribution_reporting/register_trigger_headers_debug_reporting.html.mock-http-headers +++ b/content/test/data/attribution_reporting/register_trigger_headers_debug_reporting.html.mock-http-headers
@@ -1,2 +1,2 @@ HTTP/1.1 200 OK -Attribution-Reporting-Register-Trigger:{"debug_reporting": true} +Attribution-Reporting-Register-Trigger:{"event_trigger_data":[{"trigger_data":"7"}], "debug_reporting":true}
diff --git a/content/test/data/attribution_reporting/simulator/clear_data.input.json b/content/test/data/attribution_reporting/simulator/clear_data.input.json index 3ac46fa9..fcdd9ac 100644 --- a/content/test/data/attribution_reporting/simulator/clear_data.input.json +++ b/content/test/data/attribution_reporting/simulator/clear_data.input.json
@@ -13,7 +13,7 @@ { "timestamp": "1643235573000", "source_origin": "https://s.test", - "reporting_origin": "https://r.test", + "reporting_origin": "https://r2.test", "source_type": "navigation", "Attribution-Reporting-Register-Source": { "destination": "https://d2.test", @@ -36,7 +36,7 @@ }, { "timestamp": "1643235575000", - "reporting_origin": "https://r.test", + "reporting_origin": "https://r2.test", "destination_origin": "https://d2.test", "Attribution-Reporting-Register-Trigger": { "event_trigger_data": [ @@ -52,7 +52,7 @@ "timestamp": "1643235574000", "delete_begin": "1643235573000", "delete_end": "1643235573000", - "origins": ["https://d1.test"] + "origins": ["https://r.test"] } ] }
diff --git a/content/test/data/attribution_reporting/simulator/clear_data.output.json b/content/test/data/attribution_reporting/simulator/clear_data.output.json index ec5e92d..eedcfde 100644 --- a/content/test/data/attribution_reporting/simulator/clear_data.output.json +++ b/content/test/data/attribution_reporting/simulator/clear_data.output.json
@@ -10,7 +10,7 @@ "trigger_data": "7" }, "intended_report_time": "1643411973000", - "report_url": "https://r.test/.well-known/attribution-reporting/report-event-attribution" + "report_url": "https://r2.test/.well-known/attribution-reporting/report-event-attribution" } ] }
diff --git a/content/test/data/autofill/autofill_form_devtools_issues_test.html b/content/test/data/autofill/autofill_form_devtools_issues_test.html index c6753fdc..1405109 100644 --- a/content/test/data/autofill/autofill_form_devtools_issues_test.html +++ b/content/test/data/autofill/autofill_form_devtools_issues_test.html
@@ -15,6 +15,8 @@ <input type="text" id="input_4"> <!-- Inputs with an empty autocomplete attribute. --> <input aria-label="I have a label" type="text" id="input_5" autocomplete /> + <!-- Inputs without id neither name. --> + <input aria-label="I have a label" type="text"> </form> </body> </html>
diff --git a/content/test/data/media/canplaytype_test.js b/content/test/data/media/canplaytype_test.js index dfc99d9..aeaebf5 100644 --- a/content/test/data/media/canplaytype_test.js +++ b/content/test/data/media/canplaytype_test.js
@@ -256,9 +256,9 @@ // Codecs are case sensitive. 'Theora', - 'Opus', + 'OpuS', 'Vorbis', - 'Theora, Opus', + 'Theora, OpuS', 'Theora, Vorbis', // Unknown codecs. @@ -313,9 +313,9 @@ // Codecs are case sensitive. 'VP8, Vorbis', - 'VP8.0, Opus', + 'VP8.0, OpuS', 'VP9, Vorbis', - 'VP9.0, Opus', + 'VP9.0, OpuS', // Unknown codec. 'unknown', @@ -663,10 +663,13 @@ 'probably': [ 'audio/flac', 'audio/ogg; codecs="flac"', + 'audio/ogg; codecs="fLaC"', // See CodecSupportTest_mp4 for more flac Variants. 'audio/mp4; codecs="flac"', 'video/mp4; codecs="flac"', + 'audio/mp4; codecs="fLaC"', + 'video/mp4; codecs="fLaC"', ], 'not': [ 'video/flac', @@ -744,10 +747,13 @@ const MP4_CODEC_MAP = { 'probably': [ 'audio/mp4; codecs="flac"', + 'audio/mp4; codecs="fLaC"', 'audio/mp4; codecs="mp4a.69"', 'audio/mp4; codecs="mp4a.6B"', 'audio/mp4; codecs="opus"', + 'audio/mp4; codecs="Opus"', 'video/mp4; codecs="flac"', + 'video/mp4; codecs="fLaC"', 'video/mp4; codecs="mp4a.69"', 'video/mp4; codecs="mp4a.6B"', 'video/mp4; codecs="opus"',
diff --git a/content/test/gpu/PRESUBMIT.py b/content/test/gpu/PRESUBMIT.py index d52077d..527807f 100644 --- a/content/test/gpu/PRESUBMIT.py +++ b/content/test/gpu/PRESUBMIT.py
@@ -10,6 +10,8 @@ USE_PYTHON3 = True +PRESUBMIT_VERSION = '2.0.0' + EXTRA_PATHS_COMPONENTS = [ ('build', ), ('build', 'fuchsia'), @@ -23,13 +25,17 @@ ] -def CommonChecks(input_api, output_api): - results = [] +def _GetChromiumSrcPath(input_api): + """Returns the path to the Chromium src directory.""" + return input_api.os_path.realpath( + input_api.os_path.join(input_api.PresubmitLocalPath(), '..', '..', '..')) + +def _GetGpuEnv(input_api): + """Gets the common environment for running GPU tests.""" gpu_env = dict(input_api.environ) current_path = input_api.PresubmitLocalPath() - chromium_src_path = input_api.os_path.realpath( - input_api.os_path.join(current_path, '..', '..', '..')) + chromium_src_path = _GetChromiumSrcPath(input_api) testing_path = input_api.os_path.join(chromium_src_path, 'testing') gpu_env.update({ 'PYTHONPATH': @@ -37,63 +43,58 @@ 'PYTHONDONTWRITEBYTECODE': '1', }) + return gpu_env - gpu_tests = [ - input_api.Command( - name='run_content_test_gpu_unittests', - cmd=[input_api.python3_executable, 'run_unittests.py', 'gpu_tests'], - kwargs={'env': gpu_env}, - message=output_api.PresubmitError, - python3=True), - input_api.Command(name='validate_tag_consistency', - cmd=[ - input_api.python3_executable, - 'validate_tag_consistency.py', 'validate' - ], - kwargs={}, - message=output_api.PresubmitError, - python3=True), - ] - results.extend(input_api.RunTests(gpu_tests)) - results.extend( - input_api.canned_checks.RunUnitTestsInDirectory( - input_api, - output_api, - input_api.os_path.join(input_api.PresubmitLocalPath(), - 'unexpected_passes'), [r'^.+_unittest\.py$'], - env=gpu_env, - run_on_python2=False, - run_on_python3=True, - skip_shebang_check=True)) +def CheckGpuTestsUnittests(input_api, output_api): + """Runs the unittests for the gpu_tests directory.""" + gpu_env = _GetGpuEnv(input_api) + command = input_api.Command( + name='run_content_test_gpu_unittests', + cmd=[input_api.python3_executable, 'run_unittests.py', 'gpu_tests'], + kwargs={'env': gpu_env}, + message=output_api.PresubmitError, + python3=True) + return input_api.RunTests([command]) - results.extend( - input_api.canned_checks.RunUnitTestsInDirectory( - input_api, - output_api, - input_api.os_path.join(input_api.PresubmitLocalPath(), - 'flake_suppressor'), [r'^.+_unittest\.py$'], - env=gpu_env, - run_on_python2=False, - run_on_python3=True, - skip_shebang_check=True)) - pylint_extra_paths = [ - input_api.os_path.join(chromium_src_path, *component) - for component in EXTRA_PATHS_COMPONENTS - ] - pylint_checks = input_api.canned_checks.GetPylint( +def CheckUnexpectedPassesUnittests(input_api, output_api): + """Runs the unittests for the unexpected_passes directory.""" + return input_api.canned_checks.RunUnitTestsInDirectory( input_api, output_api, - extra_paths_list=pylint_extra_paths, - pylintrc='pylintrc', - version='2.7') - results.extend(input_api.RunTests(pylint_checks)) + input_api.os_path.join(input_api.PresubmitLocalPath(), + 'unexpected_passes'), [r'^.+_unittest\.py$'], + env=_GetGpuEnv(input_api), + run_on_python2=False, + run_on_python3=True, + skip_shebang_check=True) - results.extend(CheckForNewSkipExpectations(input_api, output_api)) - results.extend(CheckPytypePathsInSync(input_api, output_api)) - return results +def CheckFlakeSuppressorUnittests(input_api, output_api): + """Runs the unittests for the flake_suppressor directory.""" + return input_api.canned_checks.RunUnitTestsInDirectory( + input_api, + output_api, + input_api.os_path.join(input_api.PresubmitLocalPath(), + 'flake_suppressor'), [r'^.+_unittest\.py$'], + env=_GetGpuEnv(input_api), + run_on_python2=False, + run_on_python3=True, + skip_shebang_check=True) + + +def CheckValidateTagConsistency(input_api, output_api): + """Checks that GPU expectation tags are consistent across all files.""" + command = input_api.Command(name='validate_tag_consistency', + cmd=[ + input_api.python3_executable, + 'validate_tag_consistency.py', 'validate' + ], + kwargs={}, + message=output_api.PresubmitError, + python3=True) + return input_api.RunTests([command]) def CheckForNewSkipExpectations(input_api, output_api): @@ -122,6 +123,22 @@ return result +def CheckPylint(input_api, output_api): + """Runs pylint on all directory content and subdirectories.""" + chromium_src_path = _GetChromiumSrcPath(input_api) + pylint_extra_paths = [ + input_api.os_path.join(chromium_src_path, *component) + for component in EXTRA_PATHS_COMPONENTS + ] + pylint_checks = input_api.canned_checks.GetPylint( + input_api, + output_api, + extra_paths_list=pylint_extra_paths, + pylintrc='pylintrc', + version='2.7') + return input_api.RunTests(pylint_checks) + + def CheckPytypePathsInSync(input_api, output_api): """Checks that run_pytype.py's paths are in sync with PRESUBMIT.py's""" filepath = input_api.os_path.join(input_api.PresubmitLocalPath(), @@ -148,11 +165,3 @@ 'run_pytype.py, please ensure they are identical.') ] return [] - - -def CheckChangeOnUpload(input_api, output_api): - return CommonChecks(input_api, output_api) - - -def CheckChangeOnCommit(input_api, output_api): - return CommonChecks(input_api, output_api)
diff --git a/content/test/gpu/gpu_tests/common_browser_args.py b/content/test/gpu/gpu_tests/common_browser_args.py index 913aae33..e2895104 100644 --- a/content/test/gpu/gpu_tests/common_browser_args.py +++ b/content/test/gpu/gpu_tests/common_browser_args.py
@@ -13,7 +13,7 @@ '--disable-direct-composition-video-overlays' DISABLE_DIRECT_COMPOSITION_VP_SCALING = '--disable_vp_scaling=1' DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS = '--disable-domain-blocking-for-3d-apis' -DISABLE_FEATURES_D3D11_VIDEO_DECODER = '--disable-features=D3D11VideoDecoder' +DISABLE_FEATURES_D3D11_VIDEO_DECODER = '--disable_d3d11_video_decoder=1' DISABLE_GPU = '--disable-gpu' DISABLE_GPU_COMPOSITING = '--disable-gpu-compositing' DISABLE_GPU_PROCESS_CRASH_LIMIT = '--disable-gpu-process-crash-limit'
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index aa5d3bf..5057239 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -347,7 +347,9 @@ crbug.com/1395227 [ mac-x86_64 mojave no-asan nvidia-0xfe9 release ] Pixel_WebGPUImportVideoFrameUnaccelerated [ Failure ] crbug.com/1395227 [ amd-0x679e mac-x86_64 monterey no-asan release ] Pixel_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ] crbug.com/1395227 [ asan intel mac-x86_64 monterey release ] Pixel_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ] -crbug.com/1395227 [ mac ] Pixel_WebGPUImportVideoFrame [ Failure ] +crbug.com/1395227 [ amd-0x679e mac-x86_64 monterey no-asan release ] Pixel_WebGPUImportVideoFrame [ Failure ] +crbug.com/1395227 [ asan intel mac-x86_64 monterey release ] Pixel_WebGPUImportVideoFrame [ Failure ] +crbug.com/1395227 [ mac-x86_64 mojave no-asan nvidia-0xfe9 release ] Pixel_WebGPUImportVideoFrame [ Failure ] crbug.com/1395227 [ amd-0x679e mac-x86_64 monterey no-asan release ] Pixel_WebGPUImportVideoFrameOffscreenCanvas [ Failure ] crbug.com/1395227 [ asan intel mac-x86_64 monterey release ] Pixel_WebGPUImportVideoFrameOffscreenCanvas [ Failure ] crbug.com/1395227 [ mac-x86_64 mojave no-asan nvidia-0xfe9 release ] Pixel_WebGPUImportVideoFrameOffscreenCanvas [ Failure ] @@ -386,8 +388,9 @@ crbug.com/1382332 [ fuchsia ] Pixel_MediaRecorderFromVideoElementWithOoprCanvasDisabled [ Failure ] crbug.com/1382332 [ linux nvidia-0x2184 passthrough debug angle-vulkan ] Pixel_MediaRecorderFromVideoElementWithOoprCanvasDisabled [ Failure ] -# Pixel_MediaRecorderFromVideoElement flakes on Linux FYI Release (Intel UHD 630) +# Pixel_MediaRecorderFromVideoElement flakes on several Linux/Lacros FYI bots crbug.com/1382332 [ linux release renderer-skia-vulkan intel-0x9bc5 ] Pixel_MediaRecorderFromVideoElement [ RetryOnFailure ] +crbug.com/1382332 [ linux release renderer-skia-gl display-server-wayland intel-0x9bc5 ] Pixel_MediaRecorderFromVideoElement [ RetryOnFailure ] # WebGL tests are seeing occasional hangs on Linux FYI Release (AMD RX 5500 XT). crbug.com/1396451 [ linux desktop amd-0x7340 ] Pixel_WebGLSadCanvas [ RetryOnFailure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt index 8dbc9fc..5b48b33 100644 --- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -213,7 +213,7 @@ crbug.com/1409457 [ win amd ] OverlayModeTraceTest_DirectComposition_Video_VP9_YUY2 [ Failure ] crbug.com/1402261 [ win intel ] OverlayModeTraceTest_DirectComposition_Video_* [ RetryOnFailure ] -crbug.com/1402261 [ win amd ] OverlayModeTraceTest_DirectComposition_Video_* [ RetryOnFailure ] +crbug.com/1402261 [ win amd ] OverlayModeTraceTest_DirectComposition_Video_* [ Failure ] ####################################################################### # Automated Entries After This Point - Do Not Manually Add Below Here #
diff --git a/content/web_test/browser/web_test_origin_trial_throttle.cc b/content/web_test/browser/web_test_origin_trial_throttle.cc index 6900b27f..7c625cfb 100644 --- a/content/web_test/browser/web_test_origin_trial_throttle.cc +++ b/content/web_test/browser/web_test_origin_trial_throttle.cc
@@ -12,6 +12,7 @@ #include "base/time/time.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/origin_trials_controller_delegate.h" +#include "content/public/browser/render_frame_host.h" #include "url/gurl.h" #include "url/origin.h" @@ -49,8 +50,15 @@ base::flat_set<std::string> trials; if (!origin.opaque()) { + url::Origin partition_origin = origin; + if (navigation_handle()->GetParentFrameOrOuterDocument()) { + partition_origin = navigation_handle() + ->GetParentFrameOrOuterDocument() + ->GetOutermostMainFrame() + ->GetLastCommittedOrigin(); + } trials = origin_trials_controller_delegate_->GetPersistedTrialsForOrigin( - origin, base::Time::Now()); + origin, partition_origin, base::Time::Now()); } std::string header_value = base::JoinString( base::span<std::string>(trials.begin(), trials.end()), ", ");
diff --git a/device/bluetooth/public/mojom/BUILD.gn b/device/bluetooth/public/mojom/BUILD.gn index e9628529..687e1f5 100644 --- a/device/bluetooth/public/mojom/BUILD.gn +++ b/device/bluetooth/public/mojom/BUILD.gn
@@ -50,6 +50,7 @@ "device.mojom", ] webui_module_path = "/" + use_typescript_sources = true public_deps = [ ":mojom" ]
diff --git a/docs/dangling_ptr.md b/docs/dangling_ptr.md index db37f72..8379d4e 100644 --- a/docs/dangling_ptr.md +++ b/docs/dangling_ptr.md
@@ -1,12 +1,12 @@ -# Dangling pointer detector. +# Dangling Pointer Detector Dangling pointers are not a problem unless they are dereferenced and used. However, they are a source of UaF bugs and highly discouraged unless you are 100% confident that they are never dereferenced after the pointed-to objects are freed. -See also the guide: [how to fix dangling pointers. -[docs/dangling_ptr.md](./dangling_ptr_guide.md) +See also the [Dangling Pointers Guide](./dangling_ptr_guide.md) for how to fix +cases where dangling pointers occur. Behind build flags, Chrome implements a dangling pointer detector. It causes Chrome to crash, whenever a raw_ptr becomes dangling: @@ -23,7 +23,7 @@ raw_ptr<T, DisableDanglingPtrDetection> ptr_may_dangle; ``` -The `DanglingUntriaged` has been used to annotate pre-existing dangling +The `DanglingUntriaged` option has been used to annotate pre-existing dangling pointers in Chrome: ```cpp raw_ptr<T, DanglingUntriaged> ptr_dangling_mysteriously;
diff --git a/docs/dangling_ptr_guide.md b/docs/dangling_ptr_guide.md index a416868..665ab73 100644 --- a/docs/dangling_ptr_guide.md +++ b/docs/dangling_ptr_guide.md
@@ -1,4 +1,4 @@ -# Dangling pointer guide +# Dangling Pointer Guide A dangling pointer has been found in your patch? This doc will help you fix it. @@ -9,13 +9,13 @@ [docs/dangling_ptr.md](./dangling_ptr.md) **Table of content** -- [`Case 1` I don’t own the affected component](#-case-1--i-don-t-own-the-affected-component) -- [`Case 2` The dangling pointer does not own the deleted object.](#-case-2--the-dangling-pointer-does-not-own-the-deleted-object) +- [`Case 1` I don’t own the affected component](#i-don_t-own-the-affected-component) +- [`Case 2` The dangling pointer does not own the deleted object.](#the-dangling-pointer-does-not-own-the-deleted-object) - [Incorrect destruction order](#incorrect-destruction-order) - [Observer callback](#observer-callback) - [Challenging lifespan](#challenging-lifespan) - [Fallback solution](#fallback-solution) -- [`Case 3` The pointer manages ownership over the object](#-case-3--the-pointer-manages-ownership-over-the-object) +- [`Case 3` The pointer manages ownership over the object](#the-pointer-manages-ownership-over-the-object) - [Smart pointers](#smart-pointers) - [Object vended from C API](#object-vended-from-c-api) - [Object conditionally owned](#object-conditionally-owned) @@ -39,11 +39,11 @@ Engineers might uncover new dangling pointers, by testing new code paths. Knowing about dangling pointers is a purely positive increment. In some cases, the affected component belongs to a different team. We don’t want to disrupt -engineers achieving their primary goal, if they only “discovered” a dangling -pointer. Annotating the pointer makes the issue visible directly into the code, +engineers achieving their primary goal, if they only “discover” a dangling +pointer. Annotating the pointer makes the issue visible directly in the code, improving our knowledge of Chrome. -## `Case 2` The dangling pointer does not own the deleted object. +## `Case 2` The dangling pointer does not own the deleted object ### Incorrect destruction order @@ -84,7 +84,7 @@ ### Fallback solution As a last resort, when the situation is perfectly understood, and you believe it -is better to let the pointer to dangle, the raw_ptr can be annotated with +is better to let the pointer dangle, the raw_ptr can be annotated with `DisableDanglingPtrDetection`. A comment explaining why this is safe must be added.
diff --git a/docs/ios/unrealized_web_state.md b/docs/ios/unrealized_web_state.md index a3d627c4..6cbdbf1 100644 --- a/docs/ios/unrealized_web_state.md +++ b/docs/ios/unrealized_web_state.md
@@ -31,7 +31,6 @@ - registering and removing Observers - registering and removing WebStatePolicyDecider -- registering ScriptCommandCallback - `const` property getters (*) - retrieving saved state (**) - attaching tab helpers
diff --git a/docs/network_traffic_annotations.md b/docs/network_traffic_annotations.md index 413adc42..a804396 100644 --- a/docs/network_traffic_annotations.md +++ b/docs/network_traffic_annotations.md
@@ -159,10 +159,18 @@ Note that settings look different on different platforms, make sure your description works everywhere! * `chrome_policy`: Policy configuration that disables or limits this network - request. This would be a text serialized protobuf of any enterprise policy. - See policy list or + request. This would be a text serialized protobuf of any **non-device** + enterprise policy. See policy list or `out/Debug/gen/components/policy/proto/chrome_settings.proto` for the full list of policies. + * Note: Use `chrome_device_policy` instead for device policies. + * `chrome_device_policy`: Policy configuration that disables or limits this + network request. This would be a text serialized protobuf of any + **device** enterprise policy. See + `components/policy/proto/chrome_device_policy.proto` for the full list of + policies. + * Note: Use `chrome_policy` instead for non-device policies (e.g. user + policies). * `policy_exception_justification`: If there is no policy to disable or limit this request, a justification can be presented here. * `deprecated_policies`: Policy names disabling or limiting this network request
diff --git a/docs/webapps/README.md b/docs/webapps/README.md index 6557517..d4ce5748 100644 --- a/docs/webapps/README.md +++ b/docs/webapps/README.md
@@ -163,6 +163,7 @@ - [/docs/webapps/os_integration.md][50] - [/docs/webapps/manifest_update_process.md][51] - [/docs/webapps/isolated_web_apps.md][52] +- [/docs/webapps/webui_web_apps.md][54] ## How To Use @@ -259,6 +260,13 @@ 1. Create a new interface for this new external dependency, put it on the `WebAppProvider`, and create a fake for it so that you can test with it faked. 1. If all else fails, use a browser test. +### Common Testing Utilities + +* UrlLoadObserver - Waits for given url to load anywhere. +* AllBrowserTabAddedWaiter - Waits for a tab to be added anywhere (works for both app browser and regular browser). +* BrowserChangeObserver - Waits for a browser to add or remove. +* content::TestNavigationObserver - Waits for a navigation anywhere or in given WebContents. See StartWatchingNewWebContents to watch all web contents. + ## Relevant Classes #### [`WebAppProvider`][12] @@ -360,3 +368,4 @@ [51]: manifest_update_process.md [52]: isolated_web_apps.md [53]: /chrome/browser/web_applications/url_handler_prefs.h +[54]: webui_web_apps.md
diff --git a/docs/webapps/webui_web_app.md b/docs/webapps/webui_web_app.md new file mode 100644 index 0000000..af8a4ae4 --- /dev/null +++ b/docs/webapps/webui_web_app.md
@@ -0,0 +1,13 @@ +## WebUI Web Apps + +### Installable WebUIs + +Chrome WebUI can be installed as web apps if they are developed for that purpose (e.g. have valid manifests). Please consult with the Web Apps & Security teams if you consider making a WebUI installable. +So far the only such app is the PasswordManager WebUI available at `chrome://password-manager`. + +### Restrictions + +WebUI web apps should have a clear and limited purpose and scope, and do not access other Chrome resources. For example, a Password Manager app should not let the user access the browsing history inside the app. +To guarantee that, a navigation throttle exists that opens all navigations from WebUI web apps in a new browser tab, instead of opening an in-app CCT. + +*This does not apply for ChromeOS system web apps, which might have their own navigation rules.
diff --git a/docs/webui_in_chrome.md b/docs/webui_in_chrome.md index aca7138..bf8e2f5 100644 --- a/docs/webui_in_chrome.md +++ b/docs/webui_in_chrome.md
@@ -36,7 +36,7 @@ <meta charset="utf-8"> <link rel="stylesheet" href="hello_world.css"> <hello-world-app></hello-world-app> - <script type="module" src="hello_world.js"></script> + <script type="module" src="app.js"></script> </html> ```
diff --git a/extensions/browser/api/networking_private/networking_private_service_client.h b/extensions/browser/api/networking_private/networking_private_service_client.h index 39a4758..580512f 100644 --- a/extensions/browser/api/networking_private/networking_private_service_client.h +++ b/extensions/browser/api/networking_private/networking_private_service_client.h
@@ -14,7 +14,6 @@ #include "base/containers/id_map.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/supports_user_data.h" #include "base/values.h" #include "components/keyed_service/core/keyed_service.h" #include "components/wifi/wifi_service.h"
diff --git a/extensions/browser/extension_api_frame_id_map.cc b/extensions/browser/extension_api_frame_id_map.cc index 1a2969d..651fe36b 100644 --- a/extensions/browser/extension_api_frame_id_map.cc +++ b/extensions/browser/extension_api_frame_id_map.cc
@@ -164,7 +164,7 @@ } absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return DocumentId(); }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index cd73d0e..749360df 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1817,6 +1817,8 @@ SMARTCARDPROVIDERPRIVATE_REPORTGETSTATUSCHANGERESULT = 1754, FILEMANAGERPRIVATE_RESUMEIOTASK = 1755, PASSWORDSPRIVATE_GETCREDENTIALSWITHREUSEDPASSWORD = 1756, + OS_TELEMETRY_GETAUDIOINFO = 1757, + OS_TELEMETRY_GETMARKETINGINFO = 1758, // Last entry: Add new entries above, then run: // tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc index 577a582..58a1b57 100644 --- a/extensions/common/extension_features.cc +++ b/extensions/common/extension_features.cc
@@ -147,4 +147,11 @@ "MinimumMV3CSPWithInlineSpeculationRules", base::FEATURE_ENABLED_BY_DEFAULT); +// If enabled, APIs of the Telemetry Extension platform that have pending +// approval will be enabled. Read more about the platform here: +// https://chromium.googlesource.com/chromium/src/+/master/docs/telemetry_extension/README.md. +BASE_FEATURE(kTelemetryExtensionPendingApprovalApi, + "TelemetryExtensionPendingApprovalApi", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace extensions_features
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h index 708de9e7..b05d82a 100644 --- a/extensions/common/extension_features.h +++ b/extensions/common/extension_features.h
@@ -52,6 +52,8 @@ BASE_DECLARE_FEATURE(kMinimumMV3CSPWithInlineSpeculationRules); +BASE_DECLARE_FEATURE(kTelemetryExtensionPendingApprovalApi); + } // namespace extensions_features #endif // EXTENSIONS_COMMON_EXTENSION_FEATURES_H_
diff --git a/extensions/common/features/feature_flags.cc b/extensions/common/features/feature_flags.cc index 1d5408a9..f1eab55e 100644 --- a/extensions/common/features/feature_flags.cc +++ b/extensions/common/features/feature_flags.cc
@@ -22,6 +22,7 @@ const base::Feature* kFeatureFlags[] = { &extensions_features::kExtensionsOffscreenDocuments, &extensions_features::kNewWebstoreDomain, + &extensions_features::kTelemetryExtensionPendingApprovalApi, }; CONSTINIT base::span<const base::Feature*> g_feature_flags_test_override;
diff --git a/extensions/renderer/bindings/api_binding.h b/extensions/renderer/bindings/api_binding.h index 95bf7d9..e4e7aa7 100644 --- a/extensions/renderer/bindings/api_binding.h +++ b/extensions/renderer/bindings/api_binding.h
@@ -12,7 +12,6 @@ #include "base/containers/flat_set.h" #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" -#include "base/supports_user_data.h" #include "base/values.h" #include "extensions/renderer/bindings/argument_spec.h" #include "v8/include/v8.h"
diff --git a/fuchsia_web/runners/cast/test/cast_runner_launcher.cc b/fuchsia_web/runners/cast/test/cast_runner_launcher.cc index 6acc2e6..1ab70dd0 100644 --- a/fuchsia_web/runners/cast/test/cast_runner_launcher.cc +++ b/fuchsia_web/runners/cast/test/cast_runner_launcher.cc
@@ -140,7 +140,8 @@ .targets = {ParentRef()}}); realm_root_ = realm_builder.Build(); - return std::make_unique<sys::ServiceDirectory>(realm_root_->CloneRoot()); + return std::make_unique<sys::ServiceDirectory>( + realm_root_->component().CloneExposedDir()); } } // namespace test
diff --git a/fuchsia_web/shell/web_engine_shell.cc b/fuchsia_web/shell/web_engine_shell.cc index 5b78eb0..b94868c 100644 --- a/fuchsia_web/shell/web_engine_shell.cc +++ b/fuchsia_web/shell/web_engine_shell.cc
@@ -169,7 +169,7 @@ auto realm = realm_builder.Build(); fuchsia::component::BinderPtr binder_proxy = - realm.Connect<fuchsia::component::Binder>(); + realm.component().Connect<fuchsia::component::Binder>(); // Wait for binder_proxy to be closed. base::RunLoop run_loop;
diff --git a/fuchsia_web/webengine/browser/content_directory_loader_factory.cc b/fuchsia_web/webengine/browser/content_directory_loader_factory.cc index eb7b534..f8ba7572f 100644 --- a/fuchsia_web/webengine/browser/content_directory_loader_factory.cc +++ b/fuchsia_web/webengine/browser/content_directory_loader_factory.cc
@@ -5,7 +5,7 @@ #include "fuchsia_web/webengine/browser/content_directory_loader_factory.h" #include <lib/fdio/directory.h> -#include <lib/fdio/fdio.h> +#include <lib/fdio/fd.h> #include <algorithm> #include <memory> @@ -121,32 +121,22 @@ // Creates a read-only MemoryMappedFile view to |file|. bool MapFile(fidl::InterfaceHandle<fuchsia::io::Node> file, base::MemoryMappedFile* mmap) { - // Bind the file channel to a FDIO entry and then a file descriptor so that - // we can use it for reading. - fdio_t* fdio = nullptr; - zx_status_t status = fdio_create(file.TakeChannel().release(), &fdio); - if (status == ZX_ERR_PEER_CLOSED) { + // Bind the file channel to a file descriptor so that we can use it for + // reading. + base::ScopedFD fd; + if (zx_status_t status = fdio_fd_create(file.TakeChannel().release(), + base::ScopedFD::Receiver(fd).get()); + status != ZX_OK) { // File-not-found errors are expected in some cases, so handle this result // w/o logging error text. - return false; - } else if (status != ZX_OK) { - ZX_DLOG_IF(WARNING, status != ZX_OK, status) << "fdio_create"; - return false; - } - - base::ScopedFD fd(fdio_bind_to_fd(fdio, -1, 0)); - if (!fd.is_valid()) { - LOG(ERROR) << "fdio_bind_to_fd returned an invalid FD."; + ZX_DLOG_IF(WARNING, status != ZX_ERR_PEER_CLOSED, status) + << "fdio_fd_create"; return false; } // Map the file into memory. - if (!mmap->Initialize(base::File(std::move(fd)), - base::MemoryMappedFile::READ_ONLY)) { - return false; - } - - return true; + return mmap->Initialize(base::File(std::move(fd)), + base::MemoryMappedFile::READ_ONLY); } // Initiates data transfer from |file_channel| to |client_remote|.
diff --git a/fuchsia_web/webengine/test/context_provider_for_test_v2.cc b/fuchsia_web/webengine/test/context_provider_for_test_v2.cc index 93aa1fc9..feb83a8 100644 --- a/fuchsia_web/webengine/test/context_provider_for_test_v2.cc +++ b/fuchsia_web/webengine/test/context_provider_for_test_v2.cc
@@ -59,7 +59,8 @@ const base::CommandLine& command_line) { auto realm_root = BuildRealm(command_line); ::fuchsia::web::ContextProviderPtr context_provider; - zx_status_t status = realm_root.Connect(context_provider.NewRequest()); + zx_status_t status = + realm_root.component().Connect(context_provider.NewRequest()); ZX_CHECK(status == ZX_OK, status) << "Connect to ContextProvider"; return ContextProviderForTest(std::move(realm_root), std::move(context_provider)); @@ -92,8 +93,8 @@ void ContextProviderForDebugTest::ConnectToDebug( ::fidl::InterfaceRequest<::fuchsia::web::Debug> debug_request) { - zx_status_t status = - context_provider_.realm_root().Connect(std::move(debug_request)); + zx_status_t status = context_provider_.realm_root().component().Connect( + std::move(debug_request)); ZX_CHECK(status == ZX_OK, status) << "Connect to Debug"; }
diff --git a/gin/gin_features.cc b/gin/gin_features.cc index 98ad69d..1ef4db0 100644 --- a/gin/gin_features.cc +++ b/gin/gin_features.cc
@@ -113,17 +113,6 @@ "V8TurboFastApiCalls", base::FEATURE_ENABLED_BY_DEFAULT); -// Artificially delays script execution. -BASE_FEATURE(kV8ScriptAblation, - "V8ScriptAblation", - base::FEATURE_DISABLED_BY_DEFAULT); -const base::FeatureParam<int> kV8ScriptDelayOnceMs{&kV8ScriptAblation, - "V8ScriptDelayOnceMs", 0}; -const base::FeatureParam<int> kV8ScriptDelayMs{&kV8ScriptAblation, - "V8ScriptDelayMs", 0}; -const base::FeatureParam<double> kV8ScriptDelayFraction{ - &kV8ScriptAblation, "V8ScriptDelayFraction", 0.0}; - // Enables slow histograms that provide detailed information at increased // runtime overheads. BASE_FEATURE(kV8SlowHistograms, @@ -140,9 +129,6 @@ BASE_FEATURE(kV8SlowHistogramsSparkplugAndroid, "V8SlowHistogramsSparkplugAndroid", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kV8SlowHistogramsScriptAblation, - "V8SlowHistogramsScriptAblation", - base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kV8DelayMemoryReducer, "V8DelayMemoryReducer",
diff --git a/gin/gin_features.h b/gin/gin_features.h index 6ba6bb6..5b2d4498 100644 --- a/gin/gin_features.h +++ b/gin/gin_features.h
@@ -32,19 +32,15 @@ GIN_EXPORT BASE_DECLARE_FEATURE(kV8OptimizeJavascript); GIN_EXPORT BASE_DECLARE_FEATURE(kV8PerContextMarkingWorklist); GIN_EXPORT BASE_DECLARE_FEATURE(kV8ReduceConcurrentMarkingTasks); -GIN_EXPORT BASE_DECLARE_FEATURE(kV8ScriptAblation); -GIN_EXPORT extern const base::FeatureParam<double> kV8ScriptDelayFraction; -GIN_EXPORT extern const base::FeatureParam<int> kV8ScriptDelayMs; -GIN_EXPORT extern const base::FeatureParam<int> kV8ScriptDelayOnceMs; GIN_EXPORT BASE_DECLARE_FEATURE(kV8ShortBuiltinCalls); GIN_EXPORT BASE_DECLARE_FEATURE(kV8SlowHistograms); GIN_EXPORT BASE_DECLARE_FEATURE(kV8SlowHistogramsCodeMemoryWriteProtection); GIN_EXPORT BASE_DECLARE_FEATURE(kV8SlowHistogramsSparkplug); GIN_EXPORT BASE_DECLARE_FEATURE(kV8SlowHistogramsSparkplugAndroid); -GIN_EXPORT BASE_DECLARE_FEATURE(kV8SlowHistogramsScriptAblation); GIN_EXPORT BASE_DECLARE_FEATURE(kV8Sparkplug); GIN_EXPORT BASE_DECLARE_FEATURE(kV8SparkplugNeedsShortBuiltinCalls); GIN_EXPORT BASE_DECLARE_FEATURE(kV8TurboFastApiCalls); +GIN_EXPORT BASE_DECLARE_FEATURE(kV8MegaDomIC); GIN_EXPORT BASE_DECLARE_FEATURE(kV8DelayMemoryReducer); GIN_EXPORT BASE_DECLARE_FEATURE(kV8UseLibmTrigFunctions); GIN_EXPORT extern const base::FeatureParam<base::TimeDelta>
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index c10536b3..1b77e0d 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -313,27 +313,13 @@ } } - if (base::FeatureList::IsEnabled(features::kV8ScriptAblation)) { - if (int delay = features::kV8ScriptDelayMs.Get()) { - SetV8FlagsFormatted("--script-delay=%i", delay); - } - if (int delay = features::kV8ScriptDelayOnceMs.Get()) { - SetV8FlagsFormatted("--script-delay-once=%i", delay); - } - if (double fraction = features::kV8ScriptDelayFraction.Get()) { - SetV8FlagsFormatted("--script-delay-fraction=%f", fraction); - } - } - // Make sure aliases of kV8SlowHistograms only enable the feature to // avoid contradicting settings between multiple finch experiments. bool any_slow_histograms_alias = base::FeatureList::IsEnabled( features::kV8SlowHistogramsCodeMemoryWriteProtection) || base::FeatureList::IsEnabled(features::kV8SlowHistogramsSparkplug) || - base::FeatureList::IsEnabled( - features::kV8SlowHistogramsSparkplugAndroid) || - base::FeatureList::IsEnabled(features::kV8SlowHistogramsScriptAblation); + base::FeatureList::IsEnabled(features::kV8SlowHistogramsSparkplugAndroid); if (any_slow_histograms_alias) { SetV8Flags("--slow-histograms"); } else {
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 12bf1f9..dc56682 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -577,7 +577,6 @@ "ipc/common/gpu_memory_buffer_impl_test_template.h", "ipc/common/mojom_traits_unittest.cc", "ipc/host/gpu_disk_cache_unittest.cc", - "ipc/service/gpu_channel_manager_unittest.cc", "ipc/service/gpu_channel_test_common.cc", "ipc/service/gpu_channel_test_common.h", "ipc/service/gpu_watchdog_thread_unittest.cc", @@ -657,6 +656,7 @@ "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_drawing.cc", "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_framebuffers.cc", "command_buffer/service/gles2_cmd_decoder_passthrough_unittest_textures.cc", + "ipc/service/gpu_channel_manager_unittest.cc", "ipc/service/gpu_channel_unittest.cc", ] }
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index 5d8f4e2..48f8b8e 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h
@@ -164,6 +164,8 @@ bool supports_oop_raster = false; + bool supports_yuv_rgb_conversion = false; + bool chromium_gpu_fence = false; bool chromium_nonblocking_readback = false;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 77df479b..d0687082 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1262,16 +1262,6 @@ gl::GLImage* image) override; #endif - // Attaches |image| to the texture referred to by |client_texture_id|, marking - // the image as needing on-demand binding by the decoder if - // |can_bind_to_sampler| is false and as not needing on-demand binding by the - // decoder otherwise. |can_bind_to_sampler| is always false on Mac/Win and - // always true on all other platforms. - void BindImageInternal(uint32_t client_texture_id, - uint32_t texture_target, - gl::GLImage* image, - bool can_bind_to_sampler); - void DoTraceEndCHROMIUM(void); void DoDrawBuffersEXT(GLsizei count, const volatile GLenum* bufs); @@ -18536,29 +18526,6 @@ uint32_t client_texture_id, uint32_t texture_target, gl::GLImage* image) { - BindImageInternal(client_texture_id, texture_target, image, - /*can_bind_to_sampler=*/false); -} -#elif !BUILDFLAG(IS_ANDROID) -void GLES2DecoderImpl::AttachImageToTextureWithClientBinding( - uint32_t client_texture_id, - uint32_t texture_target, - gl::GLImage* image) { - BindImageInternal(client_texture_id, texture_target, image, - /*can_bind_to_sampler=*/true); -} -#endif - -void GLES2DecoderImpl::BindImageInternal(uint32_t client_texture_id, - uint32_t texture_target, - gl::GLImage* image, - bool can_bind_to_sampler) { -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) - CHECK(!can_bind_to_sampler); -#else - CHECK(can_bind_to_sampler); -#endif - TextureRef* ref = texture_manager()->GetTexture(client_texture_id); if (!ref) { return; @@ -18570,10 +18537,27 @@ } texture_manager()->SetLevelImage(ref, texture_target, 0, image, - can_bind_to_sampler - ? gpu::gles2::Texture::BOUND - : gpu::gles2::Texture::UNBOUND); + gpu::gles2::Texture::UNBOUND); } +#elif !BUILDFLAG(IS_ANDROID) +void GLES2DecoderImpl::AttachImageToTextureWithClientBinding( + uint32_t client_texture_id, + uint32_t texture_target, + gl::GLImage* image) { + TextureRef* ref = texture_manager()->GetTexture(client_texture_id); + if (!ref) { + return; + } + + GLenum bind_target = GLES2Util::GLFaceTargetToTextureTarget(texture_target); + if (ref->texture()->target() != bind_target) { + return; + } + + texture_manager()->SetLevelImage(ref, texture_target, 0, image, + gpu::gles2::Texture::BOUND); +} +#endif error::Error GLES2DecoderImpl::HandleTraceBeginCHROMIUM( uint32_t immediate_data_size,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 38832cd..5c85440 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1761,6 +1761,9 @@ caps.shared_image_swap_chain = caps.shared_image_d3d && D3DImageBackingFactory::IsSwapChainSupported(); #endif // BUILDFLAG(IS_WIN) + if (base::FeatureList::IsEnabled(features::kPassthroughYuvRgbConversion)) { + caps.supports_yuv_rgb_conversion = true; + } caps.texture_npot = feature_info_->feature_flags().npot_ok; caps.supports_scanout_shared_images = SharedImageManager::SupportsScanoutImages(); @@ -2466,19 +2469,52 @@ return error::kNoError; } +// static +std::unique_ptr<GLES2DecoderPassthroughImpl::LazySharedContextState> +GLES2DecoderPassthroughImpl::LazySharedContextState::Create( + GLES2DecoderPassthroughImpl* impl) { + auto context = + std::make_unique<GLES2DecoderPassthroughImpl::LazySharedContextState>( + impl); + if (!context->Initialize()) { + return nullptr; + } + return context; +} + GLES2DecoderPassthroughImpl::LazySharedContextState::LazySharedContextState( GLES2DecoderPassthroughImpl* impl) - : impl_(impl) { + : impl_(impl) {} + +GLES2DecoderPassthroughImpl::LazySharedContextState::~LazySharedContextState() { + ui::ScopedMakeCurrent smc(shared_context_state_->context(), + shared_context_state_->surface()); + shared_context_state_.reset(); +} + +bool GLES2DecoderPassthroughImpl::LazySharedContextState::Initialize() { auto gl_surface = gl::init::CreateOffscreenGLSurface( impl_->context_->GetGLDisplayEGL(), gfx::Size()); - DCHECK(gl_surface); + if (!gl_surface) { + impl_->InsertError( + GL_INVALID_OPERATION, + "ContextResult::kFatalFailure: Failed to create GL Surface " + "for SharedContextState"); + return false; + } gl::GLContextAttribs attribs; attribs.global_texture_share_group = true; attribs.global_semaphore_share_group = true; auto gl_context = gl::init::CreateGLContext(impl_->context_->share_group(), gl_surface.get(), attribs); - DCHECK(gl_context); + if (!gl_context) { + impl_->InsertError( + GL_INVALID_OPERATION, + "ContextResult::kFatalFailure: Failed to create GL Context " + "for SharedContextState"); + return false; + } // Make current context using `gl_context` and `gl_surface` ui::ScopedMakeCurrent smc(gl_context.get(), gl_surface.get()); @@ -2498,21 +2534,16 @@ impl_->InsertError(GL_INVALID_OPERATION, "ContextResult::kFatalFailure: Failed to Initialize GL " "for SharedContextState"); - return; + return false; } if (!shared_context_state_->InitializeGrContext(gpu_preferences, workarounds, /*cache=*/nullptr)) { impl_->InsertError(GL_INVALID_OPERATION, "ContextResult::kFatalFailure: Failed to Initialize " "GrContext for SharedContextState"); - return; + return false; } -} - -GLES2DecoderPassthroughImpl::LazySharedContextState::~LazySharedContextState() { - ui::ScopedMakeCurrent smc(shared_context_state_->context(), - shared_context_state_->surface()); - shared_context_state_.reset(); + return true; } void GLES2DecoderPassthroughImpl::InsertError(GLenum error,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 45a1832..a34f8bd 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -611,6 +611,9 @@ // about state tracking. class LazySharedContextState { public: + static std::unique_ptr<LazySharedContextState> Create( + GLES2DecoderPassthroughImpl* impl); + explicit LazySharedContextState(GLES2DecoderPassthroughImpl* impl); ~LazySharedContextState(); @@ -619,6 +622,8 @@ } private: + bool Initialize(); + raw_ptr<GLES2DecoderPassthroughImpl> impl_ = nullptr; scoped_refptr<SharedContextState> shared_context_state_; };
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index dcd0102..c22363f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -4958,7 +4958,10 @@ GLenum subsampling, const volatile GLbyte* mailboxes_in) { if (!lazy_context_) { - lazy_context_ = std::make_unique<LazySharedContextState>(this); + lazy_context_ = LazySharedContextState::Create(this); + if (!lazy_context_) { + return error::kNoError; + } } ui::ScopedMakeCurrent smc(lazy_context_->shared_context_state()->context(), lazy_context_->shared_context_state()->surface()); @@ -4978,7 +4981,10 @@ GLenum subsampling, const volatile GLbyte* mailboxes_in) { if (!lazy_context_) { - lazy_context_ = std::make_unique<LazySharedContextState>(this); + lazy_context_ = LazySharedContextState::Create(this); + if (!lazy_context_) { + return error::kNoError; + } } ui::ScopedMakeCurrent smc(lazy_context_->shared_context_state()->context(), lazy_context_->shared_context_state()->surface());
diff --git a/gpu/command_buffer/service/gles2_external_framebuffer.cc b/gpu/command_buffer/service/gles2_external_framebuffer.cc index 888426be..7b8f340 100644 --- a/gpu/command_buffer/service/gles2_external_framebuffer.cc +++ b/gpu/command_buffer/service/gles2_external_framebuffer.cc
@@ -357,10 +357,10 @@ } if (!shared_image_representation_->format().is_single_plane() || - (shared_image_representation_->format().resource_format() != - viz::ResourceFormat::RGBA_8888 && - shared_image_representation_->format().resource_format() != - viz::ResourceFormat::RGBX_8888)) { + (shared_image_representation_->format() != + viz::SinglePlaneFormat::kRGBA_8888 && + shared_image_representation_->format() != + viz::SinglePlaneFormat::kRGBX_8888)) { LOG(ERROR) << "Unsupported format"; return false; }
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index 4c94d04..cdc9ccf 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -1236,6 +1236,7 @@ caps.shared_image_swap_chain = D3DImageBackingFactory::IsSwapChainSupported(); #endif // BUILDFLAG(IS_WIN) caps.disable_legacy_mailbox = disable_legacy_mailbox_; + caps.supports_yuv_rgb_conversion = true; return caps; }
diff --git a/gpu/command_buffer/service/service_font_manager.cc b/gpu/command_buffer/service/service_font_manager.cc index dc64f4a4..7df5cad 100644 --- a/gpu/command_buffer/service/service_font_manager.cc +++ b/gpu/command_buffer/service/service_font_manager.cc
@@ -110,17 +110,21 @@ // In general, Skia analysis of glyphs should find all cases. // If this is not happening, please file a bug with a repro so // it can be fixed. + static crash_reporter::CrashKeyString<64> crash_key("oop_cache_miss"); + const char* kFormatString = "type: %" PRIu32 ", fontSize: %d"; +#if DCHECK_IS_ON() + crash_reporter::ScopedCrashKeyString auto_clear( + &crash_key, base::StringPrintf(kFormatString, type, fontSize)); NOTREACHED(); - +#else if (dump_count_ < kMaxDumps && base::RandInt(1, 100) == 1 && !font_manager_->disable_oopr_debug_crash_dump()) { - static crash_reporter::CrashKeyString<64> crash_key("oop_cache_miss"); crash_reporter::ScopedCrashKeyString auto_clear( - &crash_key, base::StringPrintf("type: %" PRIu32 ", fontSize: %d", - type, fontSize)); + &crash_key, base::StringPrintf(kFormatString, type, fontSize)); base::debug::DumpWithoutCrashing(); ++dump_count_; } +#endif } void notifyReadFailure(
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc index f787e74..6ea5f89 100644 --- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
@@ -56,6 +56,10 @@ // Only RGBA formats supported by CreateSharedImage. absl::optional<DXGI_FORMAT> GetSupportedRGBAFormat( viz::SharedImageFormat format) { + if (!format.is_single_plane()) { + return {}; + } + switch (format.resource_format()) { case viz::ResourceFormat::RGBA_F16: return DXGI_FORMAT_R16G16B16A16_FLOAT;
diff --git a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc index 61e24450..3cfc4f8 100644 --- a/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc +++ b/gpu/command_buffer/service/shared_image/gl_ozone_image_representation.cc
@@ -29,6 +29,36 @@ namespace { +// Converts a value that is aligned with glTexImage{2|3}D's |internalformat| +// parameter to the value that is correspondingly aligned with +// glTexImage{2|3}D's |format| parameter. |internalformat| is mostly an unsized +// format that can be used both as internal format and data format. However, +// GL_EXT_texture_norm16 follows ES3 semantics and only exposes a sized +// internalformat. +unsigned GetDataFormatFromInternalFormat(unsigned internalformat) { + switch (internalformat) { + case GL_R16_EXT: + return GL_RED_EXT; + case GL_RG16_EXT: + return GL_RG_EXT; + case GL_RGB10_A2_EXT: + return GL_RGBA; + case GL_RGB_YCRCB_420_CHROMIUM: + case GL_RGB_YCBCR_420V_CHROMIUM: + case GL_RGB_YCBCR_P010_CHROMIUM: + return GL_RGB; + case GL_RED: + case GL_RG: + case GL_RGB: + case GL_RGBA: + case GL_BGRA_EXT: + return internalformat; + default: + NOTREACHED(); + return GL_NONE; + } +} + // Returns BufferFormat for given `format` and `plane_index`. gfx::BufferFormat GetBufferFormatForPlane(viz::SharedImageFormat format, int plane_index) { @@ -222,7 +252,7 @@ gles2::CreateGLES2TextureWithLightRef(gl_texture_service_id, target); GLuint internal_format = np_gl_binding->GetInternalFormat(); - GLenum gl_format = np_gl_binding->GetDataFormat(); + GLenum gl_format = GetDataFormatFromInternalFormat(internal_format); GLenum gl_type = np_gl_binding->GetDataType(); texture->SetLevelInfo(target, 0, internal_format, backing->size().width(), backing->size().height(), 1, 0, gl_format, gl_type, @@ -251,7 +281,7 @@ } GLuint internal_format = np_gl_binding->GetInternalFormat(); - GLenum gl_format = np_gl_binding->GetDataFormat(); + GLenum gl_format = GetDataFormatFromInternalFormat(internal_format); GLenum gl_type = np_gl_binding->GetDataType(); scoped_refptr<gles2::TexturePassthrough> texture_passthrough = base::MakeRefCounted<gpu::gles2::TexturePassthrough>(
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_holder.cc b/gpu/command_buffer/service/shared_image/gl_texture_holder.cc index 184cfea..7dd96fe 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_holder.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_holder.cc
@@ -40,9 +40,15 @@ GLTextureHolder::GLTextureHolder(viz::ResourceFormat format, const gfx::Size& size, - bool is_passthrough) - : format_(format), size_(size), is_passthrough_(is_passthrough) {} + bool is_passthrough, + gl::ProgressReporter* progress_reporter) + : format_(format), + size_(size), + is_passthrough_(is_passthrough), + progress_reporter_(progress_reporter) {} +// TODO(kylechar): When `texture_` is removed with validating command decoder +// move constructor/assignment can be defaulted. GLTextureHolder::GLTextureHolder(GLTextureHolder&& other) { operator=(std::move(other)); } @@ -56,6 +62,7 @@ other.texture_ = nullptr; passthrough_texture_ = std::move(other.passthrough_texture_); format_desc_ = other.format_desc_; + progress_reporter_ = other.progress_reporter_; return *this; } @@ -84,7 +91,6 @@ const GLCommonImageBackingFactory::FormatInfo& format_info, bool framebuffer_attachment_angle, base::span<const uint8_t> pixel_data, - gl::ProgressReporter* progress_reporter, const std::string& debug_label) { format_desc_.target = GL_TEXTURE_2D; format_desc_.data_format = format_info.gl_format; @@ -120,7 +126,7 @@ // if available. if (format_info.supports_storage) { { - gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexStorage2DEXTFn(format_desc_.target, /*levels=*/1, format_info.adjusted_storage_internal_format, size_.width(), size_.height()); @@ -129,7 +135,7 @@ if (!pixel_data.empty()) { ScopedUnpackState scoped_unpack_state( /*uploading_data=*/true); - gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexSubImage2DFn(format_desc_.target, /*level=*/0, /*xoffset=*/0, /*yoffset=*/0, size_.width(), size_.height(), format_info.adjusted_format, @@ -137,14 +143,14 @@ } } else if (format_info.is_compressed) { ScopedUnpackState scoped_unpack_state(!pixel_data.empty()); - gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glCompressedTexImage2DFn(format_desc_.target, 0, format_desc_.image_internal_format, size_.width(), size_.height(), /*border=*/0, pixel_data.size(), pixel_data.data()); } else { ScopedUnpackState scoped_unpack_state(!pixel_data.empty()); - gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter); + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); api->glTexImage2DFn( format_desc_.target, /*level=*/0, format_desc_.image_internal_format, size_.width(), size_.height(), /*border=*/0, @@ -194,9 +200,6 @@ } } - // TODO(kylechar): Create ScopedProgressReporter for duration of - // glTexSubImage2D. - gl::ScopedTextureBinder scoped_texture_binder(gl_target, texture_id); ScopedUnpackState scoped_unpack_state( /*uploading_data=*/true, gl_unpack_row_length, gl_unpack_alignment); @@ -204,8 +207,11 @@ const void* pixels = !repacked_data.empty() ? repacked_data.data() : pixmap.addr(); gl::GLApi* api = gl::g_current_gl_context; - api->glTexSubImage2DFn(gl_target, /*level=*/0, 0, 0, size_.width(), - size_.height(), gl_format, gl_type, pixels); + { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); + api->glTexSubImage2DFn(gl_target, /*level=*/0, 0, 0, size_.width(), + size_.height(), gl_format, gl_type, pixels); + } DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR)); return true; @@ -284,15 +290,15 @@ } } - // TODO(kylechar): Create ScopedProgressReporter for duration of - // glReadPixels. - ScopedPackState scoped_pack_state(gl_pack_row_length, gl_pack_alignment); void* pixels = !unpack_buffer.empty() ? unpack_buffer.data() : pixmap.writable_addr(); - api->glReadPixelsFn(0, 0, size_.width(), size_.height(), gl_format, gl_type, - pixels); + { + gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); + api->glReadPixelsFn(0, 0, size_.width(), size_.height(), gl_format, gl_type, + pixels); + } DCHECK_EQ(api->glGetErrorFn(), static_cast<GLenum>(GL_NO_ERROR)); api->glDeleteFramebuffersEXTFn(1, &framebuffer);
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_holder.h b/gpu/command_buffer/service/shared_image/gl_texture_holder.h index e34ef03..3e360b8 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_holder.h +++ b/gpu/command_buffer/service/shared_image/gl_texture_holder.h
@@ -7,6 +7,7 @@ #include "gpu/command_buffer/service/shared_image/gl_common_image_backing_factory.h" #include "gpu/command_buffer/service/shared_image/shared_image_format_utils.h" +#include "ui/gl/progress_reporter.h" namespace gpu { @@ -18,7 +19,8 @@ public: GLTextureHolder(viz::ResourceFormat format, const gfx::Size& size, - bool is_passthrough); + bool is_passthrough, + gl::ProgressReporter* progress_reporter); GLTextureHolder(GLTextureHolder&& other); GLTextureHolder& operator=(GLTextureHolder&& other); ~GLTextureHolder(); @@ -34,7 +36,6 @@ void Initialize(const GLCommonImageBackingFactory::FormatInfo& format_info, bool framebuffer_attachment_angle, base::span<const uint8_t> pixel_data, - gl::ProgressReporter* progress_reporter, const std::string& debug_label); // Uploads pixels from `pixmap` to GL texture. @@ -67,6 +68,7 @@ gles2::Texture* texture_ = nullptr; scoped_refptr<gles2::TexturePassthrough> passthrough_texture_; GLFormatDesc format_desc_; + raw_ptr<gl::ProgressReporter> progress_reporter_ = nullptr; }; } // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc index 43c5325..ab958dd 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing.cc
@@ -269,10 +269,10 @@ for (int plane = 0; plane < num_planes; ++plane) { textures_.emplace_back(GetPlaneFormat(format(), plane), format().GetPlaneSize(plane, size()), - is_passthrough_); + is_passthrough_, progress_reporter); textures_[plane].Initialize(format_info[plane], framebuffer_attachment_angle, pixel_data, - progress_reporter, debug_label); + debug_label); } if (!pixel_data.empty()) {
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc index a925d6a2..8096185d0 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory_unittest.cc
@@ -329,6 +329,11 @@ GTEST_SKIP(); } + // https://crbug.com/1410447 + if (format == viz::SinglePlaneFormat::kBGRA_8888) { + GTEST_SKIP(); + } + EXPECT_CALL(progress_reporter_, ReportProgress).Times(AtLeast(1)); auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256);
diff --git a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm index efb7898..45fc4bb 100644 --- a/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm +++ b/gpu/command_buffer/service/shared_image/iosurface_image_backing_factory.mm
@@ -277,8 +277,7 @@ gfx::ScopedIOSurface io_surface; const uint32_t io_surface_plane = 0; const gfx::GenericSharedMemoryId io_surface_id; - const gfx::BufferFormat buffer_format = - viz::BufferFormat(format.resource_format()); + const gfx::BufferFormat buffer_format = ToBufferFormat(format); { gl::ScopedProgressReporter scoped_progress_reporter(progress_reporter_); const bool should_clear = false;
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc index 75065458..063c1a42 100644 --- a/gpu/command_buffer/service/shared_image/ozone_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/ozone_image_backing.cc
@@ -320,18 +320,15 @@ } bool OzoneImageBacking::UploadFromMemory(const std::vector<SkPixmap>& pixmaps) { - DCHECK_EQ(pixmaps.size(), 1u); - auto& pixmap = pixmaps[0]; - - DCHECK(!pixmap.info().isEmpty()); - - if (context_state_->context_lost()) + if (context_state_->context_lost()) { return false; + } DCHECK(context_state_->IsCurrent(nullptr)); auto representation = ProduceSkia( nullptr, context_state_->memory_type_tracker(), context_state_); + DCHECK_EQ(pixmaps.size(), representation->NumPlanesExpected()); std::vector<GrBackendSemaphore> begin_semaphores; std::vector<GrBackendSemaphore> end_semaphores; @@ -350,15 +347,20 @@ DCHECK(result); } - DCHECK_EQ(size(), representation->size()); - bool written = context_state_->gr_context()->updateBackendTexture( - dest_scoped_access->promise_image_texture()->backendTexture(), &pixmap, - /*numLevels=*/1, representation->surface_origin(), nullptr, nullptr); + bool written = true; + for (int plane = 0; plane < format().NumberOfPlanes(); ++plane) { + GrBackendTexture backend_texture = + dest_scoped_access->promise_image_texture(plane)->backendTexture(); + if (!context_state_->gr_context()->updateBackendTexture( + backend_texture, &pixmaps[plane], + /*numLevels=*/1, surface_origin(), nullptr, nullptr)) { + written = false; + } + } FlushAndSubmitIfNecessary(std::move(end_semaphores), context_state_.get()); - if (written && !representation->IsCleared()) { - representation->SetClearedRect( - gfx::Rect(pixmap.info().width(), pixmap.info().height())); + if (written && !IsCleared()) { + SetCleared(); } return written; }
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc index 3a80dea..a85bc62 100644 --- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
@@ -221,7 +221,7 @@ gfx::GpuMemoryBufferType gmb_type, GrContextType gr_context_type, base::span<const uint8_t> pixel_data) { - if (format.is_multi_plane() && gmb_type != gfx::NATIVE_PIXMAP) { + if (format.is_multi_plane() && !pixel_data.empty()) { return false; }
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index bee03a8..34699e4 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -2595,14 +2595,6 @@ ref->texture()->SetLevelImage(target, level, image, state); } -void TextureManager::SetLevelImageState(TextureRef* ref, - GLenum target, - GLint level, - Texture::ImageState state) { - DCHECK(ref); - ref->texture()->SetLevelImageState(target, level, state); -} - size_t TextureManager::GetSignatureSize() const { return sizeof(TextureTag) + sizeof(TextureSignature); }
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index a0a0ba3a..aea3cef 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h
@@ -1108,11 +1108,6 @@ gl::GLImage* image, Texture::ImageState state); - void SetLevelImageState(TextureRef* ref, - GLenum target, - GLint level, - Texture::ImageState state); - size_t GetSignatureSize() const; void AddToSignature(
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index 9edecc41..eb26e2af 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -2071,7 +2071,7 @@ uint64_t high = uint64_t(c.high_high) << 32 | uint64_t(c.high_low); uint64_t low = uint64_t(c.low_high) << 32 | uint64_t(c.low_low); absl::optional<base::UnguessableToken> unguessable_token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!unguessable_token.has_value()) { return error::kInvalidArguments; }
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index 76223ee5..3a5527bf 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -363,6 +363,12 @@ "UseGpuSchedulerDfs", base::FEATURE_DISABLED_BY_DEFAULT); +// Enable YUV<->RGB conversion for video clients through passthrough command +// decoder. +BASE_FEATURE(kPassthroughYuvRgbConversion, + "PassthroughYuvRgbConversion", + base::FEATURE_DISABLED_BY_DEFAULT); + bool UseGles2ForOopR() { #if BUILDFLAG(IS_ANDROID) // GLS3 + passthrough decoder break many tests on Android.
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h index 12ac3f7..611dd39 100644 --- a/gpu/config/gpu_finch_features.h +++ b/gpu/config/gpu_finch_features.h
@@ -88,6 +88,8 @@ GPU_EXPORT BASE_DECLARE_FEATURE(kIncreasedCmdBufferParseSlice); +GPU_EXPORT BASE_DECLARE_FEATURE(kPassthroughYuvRgbConversion); + GPU_EXPORT bool UseGles2ForOopR(); GPU_EXPORT bool IsUsingVulkan(); GPU_EXPORT bool IsDrDcEnabled();
diff --git a/headless/lib/browser/headless_browser_impl_mac.mm b/headless/lib/browser/headless_browser_impl_mac.mm index e2cb88f..1df47b0 100644 --- a/headless/lib/browser/headless_browser_impl_mac.mm +++ b/headless/lib/browser/headless_browser_impl_mac.mm
@@ -5,7 +5,10 @@ #include "headless/lib/browser/headless_browser_impl.h" #import "base/mac/scoped_objc_class_swizzler.h" +#include "base/memory/weak_ptr.h" #include "base/no_destructor.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "headless/lib/browser/headless_web_contents_impl.h" @@ -88,15 +91,28 @@ void HeadlessBrowserImpl::PlatformSetWebContentsBounds( HeadlessWebContentsImpl* web_contents, const gfx::Rect& bounds) { - NSView* web_view = - web_contents->web_contents()->GetNativeView().GetNativeNSView(); + content::WebContents* content_web_contents = web_contents->web_contents(); + + NSView* web_view = content_web_contents->GetNativeView().GetNativeNSView(); NSRect frame = gfx::ScreenRectToNSRect(bounds); [web_view setFrame:frame]; - content::RenderWidgetHostView* host_view = - web_contents->web_contents()->GetRenderWidgetHostView(); - if (host_view) - host_view->SetWindowFrameInScreen(bounds); + // Render widget host view is not ready at this point, so post a task to set + // bounds at later time. + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<content::WebContents> content_web_contents, + const gfx::Rect& bounds) { + if (content_web_contents) { + content::RenderWidgetHostView* host_view = + content_web_contents->GetRenderWidgetHostView(); + if (host_view) { + host_view->SetWindowFrameInScreen(bounds); + } + } + }, + content_web_contents->GetWeakPtr(), bounds)); } ui::Compositor* HeadlessBrowserImpl::PlatformGetCompositor(
diff --git a/headless/test/data/protocol/sanity/window-size-on-start-expected.txt b/headless/test/data/protocol/sanity/window-size-on-start-expected.txt new file mode 100644 index 0000000..e96a4ec --- /dev/null +++ b/headless/test/data/protocol/sanity/window-size-on-start-expected.txt
@@ -0,0 +1,2 @@ +Tests window size upon start. +Window size: 800x600 \ No newline at end of file
diff --git a/headless/test/data/protocol/sanity/window-size-on-start.js b/headless/test/data/protocol/sanity/window-size-on-start.js new file mode 100644 index 0000000..0d2eeb4f --- /dev/null +++ b/headless/test/data/protocol/sanity/window-size-on-start.js
@@ -0,0 +1,20 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function(testRunner) { + const html = `<!doctype html> + <html><body>Hello, world!</body></html> + `; + + const {page, dp} = + await testRunner.startHTML(html, 'Tests window size upon start.'); + + const {result: {result: {value}}} = await dp.Runtime.evaluate({ + expression: `'Window size: ' + window.outerWidth + 'x' + window.outerHeight` + }); + + testRunner.log(value); + + testRunner.completeTest(); +})
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc index 1290475b..2654723 100644 --- a/headless/test/headless_protocol_browsertest.cc +++ b/headless/test/headless_protocol_browsertest.cc
@@ -333,6 +333,8 @@ HEADLESS_PROTOCOL_TEST(ShowFilePickerInterception, "sanity/show-file-picker-interception.js") +HEADLESS_PROTOCOL_TEST(WindowSizeOnStart, "sanity/window-size-on-start.js") + class HeadlessProtocolBrowserTestWithProxy : public HeadlessProtocolBrowserTest { public:
diff --git a/infra/config/generated/builders/ci/mac11-wpt-content-shell-fyi-rel/properties.json b/infra/config/generated/builders/ci/mac11-wpt-content-shell-fyi-rel/properties.json index c3d903b3..d7b0f4b 100644 --- a/infra/config/generated/builders/ci/mac11-wpt-content-shell-fyi-rel/properties.json +++ b/infra/config/generated/builders/ci/mac11-wpt-content-shell-fyi-rel/properties.json
@@ -34,6 +34,12 @@ "builder": "mac11-wpt-content-shell-fyi-rel", "project": "chromium" } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "mac11-wpt-content-shell-fyi-rel", + "group": "tryserver.chromium.mac" + } ] } },
diff --git a/infra/config/generated/builders/ci/mac12-arm64-wpt-content-shell-fyi-rel/properties.json b/infra/config/generated/builders/ci/mac12-arm64-wpt-content-shell-fyi-rel/properties.json index f9f9c7e3..5e28779 100644 --- a/infra/config/generated/builders/ci/mac12-arm64-wpt-content-shell-fyi-rel/properties.json +++ b/infra/config/generated/builders/ci/mac12-arm64-wpt-content-shell-fyi-rel/properties.json
@@ -35,6 +35,12 @@ "builder": "mac12-arm64-wpt-content-shell-fyi-rel", "project": "chromium" } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "mac12-arm64-wpt-content-shell-fyi-rel", + "group": "tryserver.chromium.mac" + } ] } },
diff --git a/infra/config/generated/builders/try/ios-simulator-full-configs/properties.json b/infra/config/generated/builders/try/ios-simulator-full-configs/properties.json index 0f5e8737..7bdaf0c 100644 --- a/infra/config/generated/builders/try/ios-simulator-full-configs/properties.json +++ b/infra/config/generated/builders/try/ios-simulator-full-configs/properties.json
@@ -53,6 +53,10 @@ "$build/flakiness": { "check_for_flakiness": true }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org" + }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics"
diff --git a/infra/config/generated/builders/try/mac-arm64-on-arm64-rel/properties.json b/infra/config/generated/builders/try/mac-arm64-on-arm64-rel/properties.json index 498bf23..7af887c 100644 --- a/infra/config/generated/builders/try/mac-arm64-on-arm64-rel/properties.json +++ b/infra/config/generated/builders/try/mac-arm64-on-arm64-rel/properties.json
@@ -37,12 +37,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac-builder-next-rel/properties.json b/infra/config/generated/builders/try/mac-builder-next-rel/properties.json index 8941d03..dc0d327e 100644 --- a/infra/config/generated/builders/try/mac-builder-next-rel/properties.json +++ b/infra/config/generated/builders/try/mac-builder-next-rel/properties.json
@@ -38,12 +38,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 300, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac-official/properties.json b/infra/config/generated/builders/try/mac-official/properties.json index f961280..e2b3a3d 100644 --- a/infra/config/generated/builders/try/mac-official/properties.json +++ b/infra/config/generated/builders/try/mac-official/properties.json
@@ -38,9 +38,10 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" + "$build/reclient": { + "instance": "rbe-chromium-untrusted", + "jobs": 300, + "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/try/mac-osxbeta-rel/properties.json b/infra/config/generated/builders/try/mac-osxbeta-rel/properties.json index 20c6efe..eda7837 100644 --- a/infra/config/generated/builders/try/mac-osxbeta-rel/properties.json +++ b/infra/config/generated/builders/try/mac-osxbeta-rel/properties.json
@@ -75,12 +75,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac-rel-compilator/properties.json b/infra/config/generated/builders/try/mac-rel-compilator/properties.json index f740cb95..237ed229 100644 --- a/infra/config/generated/builders/try/mac-rel-compilator/properties.json +++ b/infra/config/generated/builders/try/mac-rel-compilator/properties.json
@@ -159,6 +159,11 @@ "$build/flakiness": { "check_for_flakiness": true }, + "$build/goma": { + "jobs": 150, + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org" + }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 300,
diff --git a/infra/config/generated/builders/try/mac-updater-try-builder-dbg/properties.json b/infra/config/generated/builders/try/mac-updater-try-builder-dbg/properties.json index d273a6c..9eddfddc 100644 --- a/infra/config/generated/builders/try/mac-updater-try-builder-dbg/properties.json +++ b/infra/config/generated/builders/try/mac-updater-try-builder-dbg/properties.json
@@ -72,9 +72,10 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" + "$build/reclient": { + "instance": "rbe-chromium-untrusted", + "jobs": 150, + "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/try/mac-updater-try-builder-rel/properties.json b/infra/config/generated/builders/try/mac-updater-try-builder-rel/properties.json index ef33d02c..62fcde3 100644 --- a/infra/config/generated/builders/try/mac-updater-try-builder-rel/properties.json +++ b/infra/config/generated/builders/try/mac-updater-try-builder-rel/properties.json
@@ -72,9 +72,10 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" + "$build/reclient": { + "instance": "rbe-chromium-untrusted", + "jobs": 150, + "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [],
diff --git a/infra/config/generated/builders/try/mac10.13-blink-rel/properties.json b/infra/config/generated/builders/try/mac10.13-blink-rel/properties.json index 2b48a62..116201c9 100644 --- a/infra/config/generated/builders/try/mac10.13-blink-rel/properties.json +++ b/infra/config/generated/builders/try/mac10.13-blink-rel/properties.json
@@ -37,10 +37,6 @@ "retry_failed_shards": true } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 150,
diff --git a/infra/config/generated/builders/try/mac10.14-blink-rel/properties.json b/infra/config/generated/builders/try/mac10.14-blink-rel/properties.json index 828d66b..c4fec30 100644 --- a/infra/config/generated/builders/try/mac10.14-blink-rel/properties.json +++ b/infra/config/generated/builders/try/mac10.14-blink-rel/properties.json
@@ -37,10 +37,6 @@ "retry_failed_shards": true } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 150,
diff --git a/infra/config/generated/builders/try/mac11-wpt-content-shell-fyi-rel/properties.json b/infra/config/generated/builders/try/mac11-wpt-content-shell-fyi-rel/properties.json new file mode 100644 index 0000000..3ff50b9e --- /dev/null +++ b/infra/config/generated/builders/try/mac11-wpt-content-shell-fyi-rel/properties.json
@@ -0,0 +1,57 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "mac11-wpt-content-shell-fyi-rel", + "project": "chromium" + }, + "builder_spec": { + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_bits": 64, + "target_platform": "mac" + }, + "legacy_gclient_config": { + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "mac11-wpt-content-shell-fyi-rel", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org" + }, + "$build/reclient": { + "instance": "rbe-chromium-untrusted", + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "tryserver.chromium.mac", + "recipe": "chromium_trybot" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json b/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json index efdd0157..735a38d0 100644 --- a/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json +++ b/infra/config/generated/builders/try/mac11.0-blink-rel/properties.json
@@ -37,10 +37,6 @@ "retry_failed_shards": true } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 150,
diff --git a/infra/config/generated/builders/try/mac12-arm64-wpt-content-shell-fyi-rel/properties.json b/infra/config/generated/builders/try/mac12-arm64-wpt-content-shell-fyi-rel/properties.json new file mode 100644 index 0000000..8ccca1d5 --- /dev/null +++ b/infra/config/generated/builders/try/mac12-arm64-wpt-content-shell-fyi-rel/properties.json
@@ -0,0 +1,58 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "mac12-arm64-wpt-content-shell-fyi-rel", + "project": "chromium" + }, + "builder_spec": { + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_arch": "arm", + "target_bits": 64, + "target_platform": "mac" + }, + "legacy_gclient_config": { + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "mac12-arm64-wpt-content-shell-fyi-rel", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org" + }, + "$build/reclient": { + "instance": "rbe-chromium-untrusted", + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "tryserver.chromium.mac", + "recipe": "chromium_trybot" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac12.0.arm64-blink-rel/properties.json b/infra/config/generated/builders/try/mac12.0.arm64-blink-rel/properties.json index db936b35..6ef31d5b 100644 --- a/infra/config/generated/builders/try/mac12.0.arm64-blink-rel/properties.json +++ b/infra/config/generated/builders/try/mac12.0.arm64-blink-rel/properties.json
@@ -37,10 +37,6 @@ "retry_failed_shards": true } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "jobs": 150,
diff --git a/infra/config/generated/builders/try/mac_chromium_10.13_rel_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_10.13_rel_ng/properties.json index dd74b78..98246237 100644 --- a/infra/config/generated/builders/try/mac_chromium_10.13_rel_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_10.13_rel_ng/properties.json
@@ -88,6 +88,7 @@ }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac_chromium_10.14_rel_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_10.14_rel_ng/properties.json index 1b9663e..69bbc45 100644 --- a/infra/config/generated/builders/try/mac_chromium_10.14_rel_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_10.14_rel_ng/properties.json
@@ -79,12 +79,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac_chromium_10.15_rel_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_10.15_rel_ng/properties.json index 1fa6779..7986aa6 100644 --- a/infra/config/generated/builders/try/mac_chromium_10.15_rel_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_10.15_rel_ng/properties.json
@@ -79,12 +79,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac_chromium_archive_rel_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_archive_rel_ng/properties.json index d0a516b..1dd403c 100644 --- a/infra/config/generated/builders/try/mac_chromium_archive_rel_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_archive_rel_ng/properties.json
@@ -38,12 +38,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac_chromium_compile_dbg_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_compile_dbg_ng/properties.json index fc8992c..03b0dcb1 100644 --- a/infra/config/generated/builders/try/mac_chromium_compile_dbg_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_compile_dbg_ng/properties.json
@@ -110,6 +110,10 @@ "is_compile_only": true } }, + "$build/goma": { + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org" + }, "$build/reclient": { "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics"
diff --git a/infra/config/generated/builders/try/mac_chromium_compile_rel_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_compile_rel_ng/properties.json index c8115c7..06cce01 100644 --- a/infra/config/generated/builders/try/mac_chromium_compile_rel_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_compile_rel_ng/properties.json
@@ -221,12 +221,9 @@ "is_compile_only": true } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/mac_chromium_dbg_ng/properties.json b/infra/config/generated/builders/try/mac_chromium_dbg_ng/properties.json index 8dd9581..899b9f36 100644 --- a/infra/config/generated/builders/try/mac_chromium_dbg_ng/properties.json +++ b/infra/config/generated/builders/try/mac_chromium_dbg_ng/properties.json
@@ -74,12 +74,9 @@ ] } }, - "$build/goma": { - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org" - }, "$build/reclient": { "instance": "rbe-chromium-untrusted", + "jobs": 150, "metrics_project": "chromium-reclient-metrics" }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 86231858..a33fc9e 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -3334,6 +3334,10 @@ includable_only: true } builders { + name: "chromium/try/mac11-wpt-content-shell-fyi-rel" + includable_only: true + } + builders { name: "chromium/try/mac11.0-blink-rel" includable_only: true } @@ -3367,6 +3371,10 @@ includable_only: true } builders { + name: "chromium/try/mac12-arm64-wpt-content-shell-fyi-rel" + includable_only: true + } + builders { name: "chromium/try/mac12-tests" includable_only: true }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index d71233d1..8efec653 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -85979,6 +85979,103 @@ } } builders { + name: "mac11-wpt-content-shell-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cpu:x86-64" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:1" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/mac11-wpt-content-shell-fyi-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.mac",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + experiments { + key: "luci.buildbucket.omit_python2" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "mac11.0-blink-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:mac11.0-blink-rel" @@ -86369,6 +86466,103 @@ description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/mac12-arm64-rel\">mac12-arm64-rel</a>." } builders { + name: "mac12-arm64-wpt-content-shell-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cpu:x86-64" + dimensions: "os:Mac" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:1" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/mac12-arm64-wpt-content-shell-fyi-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.mac",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + experiments { + key: "luci.buildbucket.omit_python2" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "mac12-tests" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index a3d584d51..2f08887d 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -17698,6 +17698,9 @@ name: "buildbucket/luci.chromium.try/mac11-arm64-rel" } builders { + name: "buildbucket/luci.chromium.try/mac11-wpt-content-shell-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac11.0-blink-rel" } builders { @@ -17710,6 +17713,9 @@ name: "buildbucket/luci.chromium.try/mac12-arm64-rel-compilator" } builders { + name: "buildbucket/luci.chromium.try/mac12-arm64-wpt-content-shell-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac12-tests" } builders { @@ -18850,12 +18856,18 @@ name: "buildbucket/luci.chromium.try/mac11-arm64-rel" } builders { + name: "buildbucket/luci.chromium.try/mac11-wpt-content-shell-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac12-arm64-rel" } builders { name: "buildbucket/luci.chromium.try/mac12-arm64-rel-compilator" } builders { + name: "buildbucket/luci.chromium.try/mac12-arm64-wpt-content-shell-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac12-tests" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index b101f6a..fc3e5bc 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4844,6 +4844,15 @@ } } job { + id: "linux-code-coverage" + realm: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "linux-code-coverage" + } +} +job { id: "linux-extended-tracing-rel" realm: "ci" buildbucket { @@ -6265,7 +6274,6 @@ triggers: "android-bfcache-rel" triggers: "android-binary-size-generator" triggers: "android-chrome-pie-x86-wpt-fyi-rel" - triggers: "android-code-coverage-native" triggers: "android-cronet-arm-dbg" triggers: "android-cronet-arm-rel" triggers: "android-cronet-arm64-dbg" @@ -6325,7 +6333,6 @@ triggers: "ios-fieldtrial-rel" triggers: "ios-m1-simulator-cronet" triggers: "ios-simulator" - triggers: "ios-simulator-code-coverage" triggers: "ios-simulator-cronet" triggers: "ios-simulator-full-configs" triggers: "ios-simulator-multi-window" @@ -6370,7 +6377,6 @@ triggers: "linux-lacros-builder-fyi-rel" triggers: "linux-lacros-builder-rel" triggers: "linux-lacros-builder-rel (reclient)" - triggers: "linux-lacros-code-coverage" triggers: "linux-lacros-dbg" triggers: "linux-lacros-dbg-fyi" triggers: "linux-lacros-version-skew-fyi" @@ -6402,7 +6408,6 @@ triggers: "mac-arm64-on-arm64-rel" triggers: "mac-arm64-rel" triggers: "mac-backuprefptr-x64-fyi-rel" - triggers: "mac-code-coverage" triggers: "mac-hermetic-upgrade-rel" triggers: "mac-official" triggers: "mac-rel-cft" @@ -6432,7 +6437,6 @@ triggers: "win-swangle-x86" triggers: "win-updater-builder-dbg" triggers: "win-updater-builder-rel" - triggers: "win10-code-coverage" triggers: "win10-rel-no-external-ip" triggers: "win32-archive-dbg" triggers: "win32-archive-rel" @@ -6532,6 +6536,25 @@ } } trigger { + id: "code-coverage-gitiles-trigger" + realm: "ci" + schedule: "with 12h interval" + triggers: "android-code-coverage" + triggers: "android-code-coverage-native" + triggers: "fuchsia-code-coverage" + triggers: "ios-simulator-code-coverage" + triggers: "linux-chromeos-code-coverage" + triggers: "linux-code-coverage" + triggers: "linux-js-code-coverage" + triggers: "linux-lacros-code-coverage" + triggers: "mac-code-coverage" + triggers: "win10-code-coverage" + gitiles { + repo: "https://chromium.googlesource.com/chromium/src" + refs: "regexp:refs/heads/main" + } +} +trigger { id: "webrtc-gitiles-trigger" realm: "webrtc" triggers: "WebRTC Chromium FYI Android Builder"
diff --git a/infra/config/generated/luci/project.cfg b/infra/config/generated/luci/project.cfg index 1abf2a4d..8a047f1 100644 --- a/infra/config/generated/luci/project.cfg +++ b/infra/config/generated/luci/project.cfg
@@ -7,7 +7,7 @@ name: "chromium" access: "group:all" lucicfg { - version: "1.35.3" + version: "1.37.0" package_dir: "../.." config_dir: "generated/luci" entry_point: "main.star"
diff --git a/infra/config/subprojects/chromium/ci/chromium.coverage.star b/infra/config/subprojects/chromium/ci/chromium.coverage.star index feedf14..c08f2cef 100644 --- a/infra/config/subprojects/chromium/ci/chromium.coverage.star +++ b/infra/config/subprojects/chromium/ci/chromium.coverage.star
@@ -7,6 +7,19 @@ load("//lib/builders.star", "os", "reclient", "xcode") load("//lib/ci.star", "ci") load("//lib/consoles.star", "consoles") +load("//project.star", "settings") + +# crbug/1408581 - The code coverage CI builders are expected to be triggered +# off the same ref every 12 hours. This poller is configured with a schedule +# to ensure this - setting schedules on the builder configuration does not +# guarantee that they are triggered off the same ref. +luci.gitiles_poller( + name = "code-coverage-gitiles-trigger", + bucket = "ci", + repo = "https://chromium.googlesource.com/chromium/src", + refs = [settings.ref], + schedule = "with 12h interval", +) ci.defaults.set( builder_group = "chromium.coverage", @@ -26,7 +39,13 @@ title = "Code Coverage CI Builders", ) -ci.builder( +def coverage_builder(**kwargs): + return ci.builder( + triggered_by = ["code-coverage-gitiles-trigger"], + **kwargs + ) + +coverage_builder( name = "android-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -58,14 +77,10 @@ generate_blame_list = True, reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, schedule = "triggered", - # TODO: This is currently triggered by an internal coordinating builder - # that runs every 12 hours. This should be cleaned up s.t. all coverage - # builders are triggered identically. - triggered_by = [], use_java_coverage = True, ) -ci.builder( +coverage_builder( name = "android-code-coverage-native", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -101,7 +116,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "fuchsia-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -135,14 +150,10 @@ ], coverage_test_types = ["overall", "unit"], schedule = "triggered", - # TODO: This is currently triggered by an internal coordinating builder - # that runs every 12 hours. This should be cleaned up s.t. all coverage - # builders are triggered identically. - triggered_by = [], use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "ios-simulator-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -176,7 +187,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "linux-chromeos-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -195,7 +206,6 @@ ), build_gs_bucket = "chromium-fyi-archive", ), - triggered_by = [], os = os.LINUX_DEFAULT, console_view_entry = [ consoles.console_view_entry( @@ -210,7 +220,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "linux-js-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -227,7 +237,6 @@ ), build_gs_bucket = "chromium-fyi-archive", ), - triggered_by = [], os = os.LINUX_DEFAULT, console_view_entry = [ consoles.console_view_entry( @@ -240,7 +249,7 @@ use_javascript_coverage = True, ) -ci.builder( +coverage_builder( name = "linux-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -255,7 +264,6 @@ ), build_gs_bucket = "chromium-fyi-archive", ), - triggered_by = [], os = os.LINUX_DEFAULT, console_view_entry = [ consoles.console_view_entry( @@ -268,7 +276,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "linux-lacros-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -298,7 +306,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "mac-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( @@ -328,7 +336,7 @@ use_clang_coverage = True, ) -ci.builder( +coverage_builder( name = "win10-code-coverage", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(
diff --git a/infra/config/subprojects/chromium/try/tryserver.blink.star b/infra/config/subprojects/chromium/try/tryserver.blink.star index d0f604b..95d35fd0 100644 --- a/infra/config/subprojects/chromium/try/tryserver.blink.star +++ b/infra/config/subprojects/chromium/try/tryserver.blink.star
@@ -29,7 +29,6 @@ kwargs.setdefault("branch_selector", branches.STANDARD_MILESTONE) kwargs.setdefault("builderless", True) kwargs.setdefault("cores", None) - kwargs.setdefault("goma_backend", goma.backend.RBE_PROD) kwargs.setdefault("os", os.MAC_ANY) kwargs.setdefault("ssd", True) return try_.builder( @@ -91,7 +90,6 @@ ), builderless = True, os = os.WINDOWS_ANY, - goma_backend = None, ) try_.builder( @@ -175,7 +173,6 @@ try_settings = builder_config.try_settings( retry_failed_shards = True, ), - goma_backend = None, ) blink_mac_builder( @@ -218,7 +215,6 @@ try_settings = builder_config.try_settings( retry_failed_shards = True, ), - goma_backend = None, ) blink_mac_builder( @@ -239,7 +235,6 @@ try_settings = builder_config.try_settings( retry_failed_shards = False, ), - goma_backend = None, ) blink_mac_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index 268e4e6..ab0abae 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -45,6 +45,8 @@ builderless = False, os = os.MAC_DEFAULT, cpu = cpu.ARM64, + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -55,6 +57,8 @@ ], builderless = False, os = os.MAC_13, + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) # This trybot mirrors the trybot mac-rel @@ -84,6 +88,8 @@ mirrors = ["ci/Mac Builder Next"], builderless = False, os = os.MAC_13, + goma_backend = None, + reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, ) try_.builder( @@ -150,7 +156,6 @@ os = os.MAC_DEFAULT, main_list_view = "try", check_for_flakiness = True, - goma_backend = None, ) try_.builder( @@ -171,6 +176,13 @@ goma_backend = None, ) +try_.builder( + name = "mac11-wpt-content-shell-fyi-rel", + mirrors = [ + "ci/mac11-wpt-content-shell-fyi-rel", + ], +) + try_.orchestrator_builder( name = "mac12-arm64-rel", compilator = "mac12-arm64-rel-compilator", @@ -195,6 +207,13 @@ ) try_.builder( + name = "mac12-arm64-wpt-content-shell-fyi-rel", + mirrors = [ + "ci/mac12-arm64-wpt-content-shell-fyi-rel", + ], +) + +try_.builder( name = "mac12-wpt-content-shell-fyi-rel", mirrors = [ "ci/mac12-wpt-content-shell-fyi-rel", @@ -210,6 +229,7 @@ "ci/Mac Builder", "ci/Mac10.13 Tests", ], + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -218,6 +238,8 @@ "ci/Mac Builder", "ci/Mac10.14 Tests", ], + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -226,6 +248,8 @@ "ci/Mac Builder", "ci/Mac10.15 Tests", ], + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -251,6 +275,8 @@ mirrors = [ "ci/mac-archive-rel", ], + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -275,7 +301,6 @@ ), os = os.MAC_DEFAULT, main_list_view = "try", - goma_backend = None, tryjob = try_.job(), ) @@ -288,6 +313,8 @@ include_all_triggered_testers = True, is_compile_only = True, ), + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -296,6 +323,8 @@ "ci/Mac Builder (dbg)", "ci/Mac12 Tests (dbg)", ], + goma_backend = None, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) try_.builder( @@ -437,7 +466,6 @@ ], ), use_clang_coverage = True, - goma_backend = None, ) ios_builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.star b/infra/config/subprojects/chromium/try/tryserver.chromium.star index a561234..e24332d 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.star
@@ -4,7 +4,7 @@ """Definitions of builders in the tryserver.chromium builder group.""" load("//lib/branches.star", "branches") -load("//lib/builders.star", "goma", "os", "reclient") +load("//lib/builders.star", "os", "reclient") load("//lib/try.star", "try_") load("//lib/consoles.star", "consoles") @@ -17,7 +17,6 @@ pool = try_.DEFAULT_POOL, service_account = try_.DEFAULT_SERVICE_ACCOUNT, execution_timeout = try_.DEFAULT_EXECUTION_TIMEOUT, - goma_backend = None, reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, ) @@ -65,8 +64,6 @@ # TODO(crbug.com/1279290) builds with PGO change take long time. # Keep in sync with mac-official in ci/chromium.star. execution_timeout = 9 * time.hour, - goma_backend = goma.backend.RBE_PROD, - reclient_instance = None, ) try_.builder(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.updater.star b/infra/config/subprojects/chromium/try/tryserver.chromium.updater.star index bfac244..b081627 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.updater.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.updater.star
@@ -3,7 +3,7 @@ # found in the LICENSE file. """Definitions of builders in the tryserver.chromium.updater builder group.""" -load("//lib/builders.star", "goma", "os", "reclient") +load("//lib/builders.star", "os", "reclient") load("//lib/try.star", "try_") load("//lib/consoles.star", "consoles") @@ -14,7 +14,8 @@ pool = try_.DEFAULT_POOL, service_account = try_.DEFAULT_SERVICE_ACCOUNT, execution_timeout = try_.DEFAULT_EXECUTION_TIMEOUT, - goma_backend = goma.backend.RBE_PROD, + reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, + reclient_jobs = reclient.jobs.LOW_JOBS_FOR_CQ, ) consoles.list_view( @@ -28,9 +29,6 @@ def updater_windows_builder(*, name, **kwargs): kwargs.setdefault("cores", 8) kwargs.setdefault("os", os.WINDOWS_DEFAULT) - kwargs.setdefault("goma_backend", None) - kwargs.setdefault("reclient_instance", reclient.instance.DEFAULT_UNTRUSTED) - kwargs.setdefault("reclient_jobs", reclient.jobs.LOW_JOBS_FOR_CQ) return try_.builder(name = name, **kwargs) updater_mac_builder(
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 3d77431..96a20d5 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -735,6 +735,9 @@ <message name="IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE" desc="Context menu text for option to search an image with Google [Length: 25em] [iOS only]"> Search Image with Google </message> + <message name="IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE_ALT_TEXT" desc="Context menu alternate text for option to search an image with Google [Length: 25em] [iOS only]"> + Search inside image with Google + </message> <message name="IDS_IOS_COPY_VERSION_HINT" desc="The accessibility hint for the label showing the Chrome version. [iOS only]"> Double tap to copy. </message> @@ -1887,6 +1890,15 @@ <message name="IDS_IOS_PAGE_LOADED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement when a page has loaded. [Length: unlimited] [iOS only]"> Webpage loaded </message> + <message name="IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE" desc="Title of the sheet that notifies the user they are saving passwords to their Google Account. [Length: unlimited] [iOS only]"> + Passwords on all your devices + </message> + <message name="IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_SUBTITLE" desc="Subtitle of the sheet that notifies the user they are saving passwords to their Google Account. [Length: unlimited] [iOS only]"> + Passwords are now saved to your Google Account (<ph name="ACCOUNT">$1<ex>foo@gmail.com</ex></ph>). You can use them wherever you're signed in. To turn this off, go to <ph name="BEGIN_LINK">BEGIN_LINK</ph>settings<ph name="END_LINK">END_LINK</ph>. + </message> + <message name="IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT" desc="Button text for the sheet that notifies the user they are saving passwords to their Google Account. [Length: unlimited] [iOS only]"> + Got it + </message> <message name="IDS_IOS_PASSWORD_LEAK_CHANGE_CREDENTIALS" desc="The text of the OK button in the dialog for credentials leaked on the current site."> Got It </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE_ALT_TEXT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE_ALT_TEXT.png.sha1 new file mode 100644 index 0000000..0b61dd6 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE_ALT_TEXT.png.sha1
@@ -0,0 +1 @@ +64b2f2b7f88a9a85cc5adf1f8f56affbb9e81234 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..fa29e6c --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +32bd1a897859f0ec1382170c6a411307bf349b76 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_SUBTITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_SUBTITLE.png.sha1 new file mode 100644 index 0000000..fa29e6c --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +32bd1a897859f0ec1382170c6a411307bf349b76 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE.png.sha1 new file mode 100644 index 0000000..fa29e6c --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE.png.sha1
@@ -0,0 +1 @@ +32bd1a897859f0ec1382170c6a411307bf349b76 \ No newline at end of file
diff --git a/ios/chrome/browser/find_in_page/find_in_page_controller.mm b/ios/chrome/browser/find_in_page/find_in_page_controller.mm index e9c94c7..c55bed6 100644 --- a/ios/chrome/browser/find_in_page/find_in_page_controller.mm +++ b/ios/chrome/browser/find_in_page/find_in_page_controller.mm
@@ -3,12 +3,15 @@ // found in the LICENSE file. #import "ios/chrome/browser/find_in_page/find_in_page_controller.h" + +#import "components/ukm/ios/ukm_url_recorder.h" #import "ios/chrome/browser/find_in_page/find_in_page_model.h" #import "ios/chrome/browser/find_in_page/find_in_page_response_delegate.h" #import "ios/public/provider/chrome/browser/find_in_page/find_in_page_api.h" #import "ios/web/public/find_in_page/find_in_page_manager.h" #import "ios/web/public/find_in_page/find_in_page_manager_delegate_bridge.h" #import "ios/web/public/web_state.h" +#import "services/metrics/public/cpp/ukm_builders.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -22,6 +25,9 @@ @interface FindInPageController () <CRWFindInPageManagerDelegate> +// Records UKM metric for Find in Page search matches. +- (void)logFindInPageSearchUKM; + @end @implementation FindInPageController { @@ -90,6 +96,17 @@ [self.findInPageModel updateQuery:gSearchTerm matches:0]; } +#pragma mark - Private + +- (void)logFindInPageSearchUKM { + ukm::SourceId sourceID = ukm::GetSourceIdForWebStateDocument(_webState); + if (sourceID != ukm::kInvalidSourceId) { + ukm::builders::IOS_FindInPageSearchMatches(sourceID) + .SetHasMatches(_findInPageModel.matches > 0) + .Record(ukm::UkmRecorder::Get()); + } +} + #pragma mark - CRWFindInPageManagerDelegate - (void)findInPageManager:(web::AbstractFindInPageManager*)manager @@ -99,6 +116,7 @@ if (matchCount == 0 && !query) { // StopFinding responds with `matchCount` as 0 and `query` as nil. [self.responseDelegate findDidStop]; + [self logFindInPageSearchUKM]; return; } [self.findInPageModel updateQuery:query matches:matchCount]; @@ -122,12 +140,11 @@ } - (void)detachFromWebState { + _findInPageManager->SetDelegate(nullptr); + _findInPageManager = nullptr; + _findInPageDelegateBridge.reset(); // Remove Find in Page manager from web state. web::FindInPageManager::RemoveFromWebState(_webState); - - _findInPageManager->SetDelegate(nullptr); - _findInPageDelegateBridge.reset(); - _findInPageManager = nullptr; _webState = nullptr; }
diff --git a/ios/chrome/browser/find_in_page/find_in_page_model.h b/ios/chrome/browser/find_in_page/find_in_page_model.h index 16282b8..3114a975 100644 --- a/ios/chrome/browser/find_in_page/find_in_page_model.h +++ b/ios/chrome/browser/find_in_page/find_in_page_model.h
@@ -14,7 +14,10 @@ // Should find in page be displayed. @property(nonatomic, assign) BOOL enabled; -// The current search string. +// The current search string. If the system Find panel is used as opposed to the +// Chrome Find bar, then this will not be updated as the user types a query in +// the Find panel text field. Instead it will contain the text with which the +// Find panel was prepopulated before being presented. @property(copy, nonatomic, readonly) NSString* text; // The number of matches for `text`.
diff --git a/ios/chrome/browser/find_in_page/find_in_page_model.mm b/ios/chrome/browser/find_in_page/find_in_page_model.mm index 09bf81b..e2c9650 100644 --- a/ios/chrome/browser/find_in_page/find_in_page_model.mm +++ b/ios/chrome/browser/find_in_page/find_in_page_model.mm
@@ -20,13 +20,6 @@ @synthesize currentPoint = _currentPoint; @synthesize text = _text; -- (void)setEnabled:(BOOL)enabled { - _enabled = enabled; - _matches = 0; - _currentIndex = 0; - _currentPoint = CGPointZero; -} - - (void)updateQuery:(NSString*)query matches:(NSUInteger)matches { if (query) self.text = query;
diff --git a/ios/chrome/browser/find_in_page/find_tab_helper.mm b/ios/chrome/browser/find_in_page/find_tab_helper.mm index 2bf1601..69d1624 100644 --- a/ios/chrome/browser/find_in_page/find_tab_helper.mm +++ b/ios/chrome/browser/find_in_page/find_tab_helper.mm
@@ -23,6 +23,10 @@ FindTabHelper::~FindTabHelper() {} void FindTabHelper::DismissFindNavigator() { + if (!IsFindUIActive()) { + // If Find UI is not active then there is no Find session to stop. + return; + } // Same as `StopFinding()` except the UI is not marked as inactive so it can // be set back up if needed later. [controller_ disableFindInPage];
diff --git a/ios/chrome/browser/find_in_page/java_script_find_in_page_controller.mm b/ios/chrome/browser/find_in_page/java_script_find_in_page_controller.mm index 8f8264a..95739c8 100644 --- a/ios/chrome/browser/find_in_page/java_script_find_in_page_controller.mm +++ b/ios/chrome/browser/find_in_page/java_script_find_in_page_controller.mm
@@ -205,10 +205,10 @@ if (matchCount == 0 && !query) { // StopFinding responds with `matchCount` as 0 and `query` as nil. [self.responseDelegate findDidStop]; + [self logFindInPageSearchUKM]; return; } [self.findInPageModel updateQuery:query matches:matchCount]; - [self logFindInPageSearchUKM]; [self.responseDelegate findDidFinishWithUpdatedModel:self.findInPageModel]; }
diff --git a/ios/chrome/browser/find_in_page/java_script_find_in_page_controller_unittest.mm b/ios/chrome/browser/find_in_page/java_script_find_in_page_controller_unittest.mm index 8e410e3..3e8f285 100644 --- a/ios/chrome/browser/find_in_page/java_script_find_in_page_controller_unittest.mm +++ b/ios/chrome/browser/find_in_page/java_script_find_in_page_controller_unittest.mm
@@ -34,6 +34,8 @@ - (void)findDidFinishWithUpdatedModel:(FindInPageModel*)model { self.model = model; } +- (void)findDidStop { +} @end namespace { @@ -90,6 +92,7 @@ base::RunLoop().RunUntilIdle(); return delegate_.model != nil; })); + [find_in_page_controller_ disableFindInPage]; // Single true entry should be recorded for the interaction above. const auto& entries = test_ukm_recorder_.GetEntriesByName(kFindInPageUkmSearchMatchesEvent); @@ -109,6 +112,7 @@ base::RunLoop().RunUntilIdle(); return delegate_.model != nil; })); + [find_in_page_controller_ disableFindInPage]; // Single false entry should be recorded for the interaction above. const auto& entries = test_ukm_recorder_.GetEntriesByName(kFindInPageUkmSearchMatchesEvent);
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index 9ae620d..9a38f2f 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -82,6 +82,7 @@ "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags", "//ios/chrome/browser/ui/post_restore_signin:features", "//ios/chrome/browser/ui/start_surface:feature_flags", + "//ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs:features", "//ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs:features", "//ios/chrome/browser/ui/toolbar_container:feature_flags", "//ios/chrome/browser/ui/whats_new:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index bf9a2863..6e808572 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -95,6 +95,7 @@ #import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h" #import "ios/chrome/browser/ui/post_restore_signin/features.h" #import "ios/chrome/browser/ui/start_surface/start_surface_features.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/features.h" #import "ios/chrome/browser/ui/toolbar_container/toolbar_container_features.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" @@ -502,6 +503,25 @@ {"With Chrome Find Bar", kNativeFindInPageWithChromeFindBar, std::size(kNativeFindInPageWithChromeFindBar), nullptr}}; +const FeatureEntry::FeatureParam kTabInactivityThresholdOneWeek[] = { + {kTabInactivityThresholdParameterName, + kTabInactivityThresholdOneWeekParam}}; +const FeatureEntry::FeatureParam kTabInactivityThresholdTwoWeeks[] = { + {kTabInactivityThresholdParameterName, + kTabInactivityThresholdTwoWeeksParam}}; +const FeatureEntry::FeatureParam kTabInactivityThresholdThreeWeeks[] = { + {kTabInactivityThresholdParameterName, + kTabInactivityThresholdThreeWeeksParam}}; + +const FeatureEntry::FeatureVariation kTabInactivityThresholdVariations[] = { + {"One week", kTabInactivityThresholdOneWeek, + std::size(kTabInactivityThresholdOneWeek), nullptr}, + {"Two weeks", kTabInactivityThresholdTwoWeeks, + std::size(kTabInactivityThresholdTwoWeeks), nullptr}, + {"Three weeks", kTabInactivityThresholdThreeWeeks, + std::size(kTabInactivityThresholdThreeWeeks), nullptr}, +}; + // To add a new entry, add to the end of kFeatureEntries. There are four // distinct types of entries: // . ENABLE_DISABLE_VALUE: entry is either enabled, disabled, or uses the @@ -769,6 +789,10 @@ {"enable-lens-in-ntp", flag_descriptions::kEnableLensInNTPName, flag_descriptions::kEnableLensInNTPDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableLensInNTP)}, + {"enable-lens-context-menu-alt-text", + flag_descriptions::kEnableLensContextMenuAltTextName, + flag_descriptions::kEnableLensContextMenuAltTextDescription, + flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableLensContextMenuAltText)}, {"enable-lens-in-omnibox-copied-image", flag_descriptions::kEnableLensInOmniboxCopiedImageName, flag_descriptions::kEnableLensInOmniboxCopiedImageDescription, @@ -1245,6 +1269,11 @@ {"ios-tabstrip-context-menu", flag_descriptions::kTabStripContextMenuName, flag_descriptions::kTabStripContextMenuDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kTabStripContextMenu)}, + {"tab-inactivity-threshold", flag_descriptions::kTabInactivityThresholdName, + flag_descriptions::kTabInactivityThresholdDescription, flags_ui::kOsIos, + FEATURE_WITH_PARAMS_VALUE_TYPE(kTabInactivityThreshold, + kTabInactivityThresholdVariations, + "TabInactivityThreshold")}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 04e0f26..76d74247 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -861,6 +861,12 @@ "menu when Google is the selected search engine, accessible from the" "new tab page."; +const char kEnableLensContextMenuAltTextName[] = + "Enable alternate text for Google Lens in Context Menu"; +const char kEnableLensContextMenuAltTextDescription[] = + "When enabled, use the alternate text for the search image with Google " + "Lens context menu string."; + const char kEnableLensInOmniboxCopiedImageName[] = "Enable Google Lens in the Omnibox for Copied Images"; const char kEnableLensInOmniboxCopiedImageDescription[] = @@ -876,6 +882,11 @@ const char kTabStripContextMenuDescription[] = "Add context menu to tab strip items."; +const char kTabInactivityThresholdName[] = "Change Tab inactivity threshold"; +const char kTabInactivityThresholdDescription[] = + "When enabled, the tabs older than the threshold are considered inactive " + "and set aside in the Inactive Tabs section of the TabGrid."; + const char kUseLoadSimulatedRequestForOfflinePageName[] = "Use loadSimulatedRequest:responseHTMLString: when displaying offline " "pages";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index d687c6a..9f6dea7 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -756,6 +756,11 @@ extern const char kEnableLensInNTPName[]; extern const char kEnableLensInNTPDescription[]; +// Title and description for the flag to enable using alternate Lens context +// menu string. +extern const char kEnableLensContextMenuAltTextName[]; +extern const char kEnableLensContextMenuAltTextDescription[]; + // Title and description for the flag to enable using Lens to search using // copied images in the omnibox. extern const char kEnableLensInOmniboxCopiedImageName[]; @@ -769,6 +774,11 @@ extern const char kTabStripContextMenuName[]; extern const char kTabStripContextMenuDescription[]; +// Title and description for the flag to determine tab inactivity in the +// TabGrid. +extern const char kTabInactivityThresholdName[]; +extern const char kTabInactivityThresholdDescription[]; + // Title and description for the flag to enable using the // loadSimulatedRequest:responseHTMLString: API for displaying error pages in // CRWWKNavigationHandler.
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.h index 4b329ab..1bf2ba0e 100644 --- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.h +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.h
@@ -21,14 +21,12 @@ : public autofill::AutofillSaveCardInfoBarDelegateMobile { public: MockAutofillSaveCardInfoBarDelegateMobile( - bool upload, autofill::AutofillClient::SaveCreditCardOptions options, const autofill::CreditCard& card, + absl::variant<autofill::AutofillClient::LocalSaveCardPromptCallback, + autofill::AutofillClient::UploadSaveCardPromptCallback> + callback, const autofill::LegalMessageLines& legal_message_lines, - autofill::AutofillClient::UploadSaveCardPromptCallback - upload_save_card_prompt_callback, - autofill::AutofillClient::LocalSaveCardPromptCallback - local_save_card_prompt_callback, const AccountInfo& displayed_target_account); ~MockAutofillSaveCardInfoBarDelegateMobile() override;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.mm index f4b3e611..ceae9fb 100644 --- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.mm +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_autofill_save_card_infobar_delegate_mobile.mm
@@ -15,23 +15,18 @@ MockAutofillSaveCardInfoBarDelegateMobile:: MockAutofillSaveCardInfoBarDelegateMobile( - bool upload, autofill::AutofillClient::SaveCreditCardOptions options, const autofill::CreditCard& card, + absl::variant<autofill::AutofillClient::LocalSaveCardPromptCallback, + autofill::AutofillClient::UploadSaveCardPromptCallback> + callback, const autofill::LegalMessageLines& legal_message_lines, - autofill::AutofillClient::UploadSaveCardPromptCallback - upload_save_card_prompt_callback, - autofill::AutofillClient::LocalSaveCardPromptCallback - local_save_card_prompt_callback, const AccountInfo& displayed_target_account) - : AutofillSaveCardInfoBarDelegateMobile( - upload, - options, - card, - legal_message_lines, - std::move(upload_save_card_prompt_callback), - std::move(local_save_card_prompt_callback), - displayed_target_account) {} + : AutofillSaveCardInfoBarDelegateMobile(options, + card, + std::move(callback), + legal_message_lines, + displayed_target_account) {} MockAutofillSaveCardInfoBarDelegateMobile:: ~MockAutofillSaveCardInfoBarDelegateMobile() = default; @@ -50,12 +45,15 @@ CreateMockAutofillSaveCardInfoBarDelegateMobileFactory( bool upload, autofill::CreditCard card) { + using Variant = + absl::variant<autofill::AutofillClient::LocalSaveCardPromptCallback, + autofill::AutofillClient::UploadSaveCardPromptCallback>; + autofill::AutofillClient::UploadSaveCardPromptCallback upload_cb = + base::DoNothing(); + autofill::AutofillClient::LocalSaveCardPromptCallback local_cb = + base::DoNothing(); return std::make_unique<MockAutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/upload, autofill::AutofillClient::SaveCreditCardOptions(), - card, autofill::LegalMessageLines(), - autofill::AutofillClient::UploadSaveCardPromptCallback(), - base::BindOnce( - ^(autofill::AutofillClient::SaveCardOfferUserDecision user_decision){ - }), - AccountInfo()); + autofill::AutofillClient::SaveCreditCardOptions(), card, + upload ? Variant(std::move(upload_cb)) : Variant(std::move(local_cb)), + autofill::LegalMessageLines(), AccountInfo()); }
diff --git a/ios/chrome/browser/main/browser_util.h b/ios/chrome/browser/main/browser_util.h index eb31be6..5928764 100644 --- a/ios/chrome/browser/main/browser_util.h +++ b/ios/chrome/browser/main/browser_util.h
@@ -7,8 +7,18 @@ #import <Foundation/Foundation.h> +#import "ios/chrome/browser/web_state_list/web_state_list.h" + class Browser; +// Moves the tab to the `destination_tab_index` in `destination_browser` with +// the given flag. It is an error to try to move a tab across profiles +// (incognito <-> regular). +void MoveTabToBrowser(NSString* tab_id, + Browser* destination_browser, + int destination_tab_index, + WebStateList::InsertionFlags flags); + // Moves the tab to the `destination_tab_index` in `destination_browser`. It is // an error to try to move a tab across profiles (incognito <-> regular). void MoveTabToBrowser(NSString* tab_id,
diff --git a/ios/chrome/browser/main/browser_util.mm b/ios/chrome/browser/main/browser_util.mm index 4781a3d..9d10595e 100644 --- a/ios/chrome/browser/main/browser_util.mm +++ b/ios/chrome/browser/main/browser_util.mm
@@ -15,7 +15,6 @@ #import "ios/chrome/browser/main/browser_list_factory.h" #import "ios/chrome/browser/snapshots/snapshot_browser_agent.h" #import "ios/chrome/browser/snapshots/snapshot_cache.h" -#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/web/public/web_state.h" @@ -85,7 +84,8 @@ void MoveTabToBrowser(NSString* tab_id, Browser* destination_browser, - int destination_tab_index) { + int destination_tab_index, + WebStateList::InsertionFlags flags) { DCHECK(tab_id.length); ChromeBrowserState* browser_state = destination_browser->GetBrowserState(); BrowserList* browser_list = @@ -107,11 +107,23 @@ MoveSnapshot(tab_id, source_browser, destination_browser); std::unique_ptr<web::WebState> web_state = source_browser->GetWebStateList()->DetachWebStateAt(source_tab_index); - int insertion_flags = WebStateList::INSERT_FORCE_INDEX; - if (destination_browser->GetWebStateList()->empty()) { - insertion_flags = WebStateList::INSERT_ACTIVATE; + + int insertion_flags = flags; + if (insertion_flags == WebStateList::InsertionFlags::INSERT_NO_FLAGS) { + insertion_flags = WebStateList::INSERT_FORCE_INDEX; + if (destination_browser->GetWebStateList()->empty()) { + insertion_flags = WebStateList::INSERT_ACTIVATE; + } } + destination_browser->GetWebStateList()->InsertWebState( destination_tab_index, std::move(web_state), insertion_flags, WebStateOpener()); } + +void MoveTabToBrowser(NSString* tab_id, + Browser* destination_browser, + int destination_tab_index) { + MoveTabToBrowser(tab_id, destination_browser, destination_tab_index, + WebStateList::InsertionFlags::INSERT_NO_FLAGS); +}
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.mm index eee0164..e5bf0d5 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.mm +++ b/ios/chrome/browser/overlays/public/infobar_banner/save_card_infobar_banner_overlay_request_config.mm
@@ -33,10 +33,10 @@ expiration_date_month_ = delegate->expiration_date_month(); expiration_date_year_ = delegate->expiration_date_year(); button_label_text_ = - delegate->upload() + delegate->is_for_upload() ? l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_SAVE_ELLIPSIS) : delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK); - should_upload_credentials_ = delegate->upload(); + should_upload_credentials_ = delegate->is_for_upload(); } SaveCardBannerRequestConfig::~SaveCardBannerRequestConfig() = default;
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.mm index 9fa9b16f..aa51511 100644 --- a/ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.mm +++ b/ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.mm
@@ -33,7 +33,7 @@ issuer_icon_id_ = delegate->issuer_icon_id(); legal_message_lines_ = LegalMessagesForModal(delegate); current_card_saved_ = infobar->accepted(); - should_upload_credentials_ = delegate->upload(); + should_upload_credentials_ = delegate->is_for_upload(); displayed_target_account_email_ = delegate->displayed_target_account_email(); displayed_target_account_avatar_ = delegate->displayed_target_account_avatar(); @@ -54,7 +54,7 @@ [[NSMutableArray alloc] init]; // Only display legal Messages if the card is being uploaded and there are // any. - if (delegate->upload() && !delegate->legal_message_lines().empty()) { + if (delegate->is_for_upload() && !delegate->legal_message_lines().empty()) { for (const auto& line : delegate->legal_message_lines()) { SaveCardMessageWithLinks* message = [[SaveCardMessageWithLinks alloc] init];
diff --git a/ios/chrome/browser/promos_manager/promos_manager_impl.mm b/ios/chrome/browser/promos_manager/promos_manager_impl.mm index 5a551ee..4fa8cc9 100644 --- a/ios/chrome/browser/promos_manager/promos_manager_impl.mm +++ b/ios/chrome/browser/promos_manager/promos_manager_impl.mm
@@ -192,7 +192,10 @@ promo_impression_limits_ = std::move(promo_impression_limits); } -// TODO: write unit test. +// Determines which promo to display next. +// Candidates are from active promos and the pending promos that can become +// active at the time this function is called. Coordinate with other internal +// functions to rank and validate the candidates. absl::optional<promos_manager::Promo> PromosManagerImpl::NextPromoForDisplay() { // Construct a map with the promo from (1) single-display and // (2) continuous-display promo campaigns. (3) single-display pending promos
diff --git a/ios/chrome/browser/promos_manager/promos_manager_impl_unittest.mm b/ios/chrome/browser/promos_manager/promos_manager_impl_unittest.mm index c4b35c4f..7988d57f 100644 --- a/ios/chrome/browser/promos_manager/promos_manager_impl_unittest.mm +++ b/ios/chrome/browser/promos_manager/promos_manager_impl_unittest.mm
@@ -37,9 +37,12 @@ } const base::TimeDelta kTimeDelta1Day = base::Days(1); +const base::TimeDelta kTimeDelta1Hour = base::Hours(1); + const PromoContext kPromoContextForActive = PromoContext{ .was_pending = false, }; + } // namespace class PromosManagerImplTest : public PlatformTest { @@ -1465,3 +1468,103 @@ local_state_->GetDict(prefs::kIosPromosManagerSingleDisplayPendingPromos) .empty()); } + +// Tests `NextPromoForDisplay` returns a pending promo that has become active +// and takes precedence over other active promos. +TEST_F(PromosManagerImplTest, NextPromoForDisplayReturnsPendingPromo) { + CreatePromosManager(); + + promos_manager_->single_display_active_promos_ = { + promos_manager::Promo::Test, + }; + promos_manager_->single_display_pending_promos_ = { + {promos_manager::Promo::CredentialProviderExtension, + test_clock_.Now() + kTimeDelta1Day}, + {promos_manager::Promo::AppStoreRating, + test_clock_.Now() + kTimeDelta1Day * 2}, + }; + + // Advance to so that the CredentialProviderExtension becomes active. + test_clock_.Advance(kTimeDelta1Day + kTimeDelta1Hour); + + absl::optional<promos_manager::Promo> promo = + promos_manager_->NextPromoForDisplay(); + EXPECT_TRUE(promo.has_value()); + EXPECT_EQ(promo.value(), promos_manager::Promo::CredentialProviderExtension); +} + +// Tests `NextPromoForDisplay` returns an active promo whose type has the +// highest priority can take precedence over other pending-becomes-active +// promos. +TEST_F(PromosManagerImplTest, + NextPromoForDisplayReturnsActivePromoOfPrioritizedType) { + CreatePromosManager(); + + promos_manager_->single_display_active_promos_ = { + promos_manager::Promo::PostRestoreSignInFullscreen, + }; + promos_manager_->single_display_pending_promos_ = { + {promos_manager::Promo::CredentialProviderExtension, + test_clock_.Now() + kTimeDelta1Day}, + }; + + // Advance to so that the CredentialProviderExtension becomes active. + test_clock_.Advance(kTimeDelta1Day + kTimeDelta1Hour); + + absl::optional<promos_manager::Promo> promo = + promos_manager_->NextPromoForDisplay(); + + EXPECT_TRUE(promo.has_value()); + EXPECT_EQ(promo.value(), promos_manager::Promo::PostRestoreSignInFullscreen); +} + +// Tests `NextPromoForDisplay` returns empty when non of the pending promos can +// become active. +TEST_F(PromosManagerImplTest, NextPromoForDisplayReturnsEmpty) { + CreatePromosManager(); + + promos_manager_->single_display_active_promos_ = {}; + promos_manager_->single_display_pending_promos_ = { + {promos_manager::Promo::Test, test_clock_.Now() + kTimeDelta1Hour * 2}, + {promos_manager::Promo::CredentialProviderExtension, + test_clock_.Now() + kTimeDelta1Day}, + }; + + // Advance to so that the none of the pending promo can become active. + test_clock_.Advance(kTimeDelta1Hour); + + absl::optional<promos_manager::Promo> promo = + promos_manager_->NextPromoForDisplay(); + + EXPECT_FALSE(promo.has_value()); +} + +// Tests `NextPromoForDisplay` returns empty when non of the promos can pass the +// onceEveryTwoDays impression limit check. +TEST_F(PromosManagerImplTest, + NextPromoForDisplayReturnsEmptyAfterImpressionCheck) { + CreatePromosManager(); + + promos_manager_->single_display_active_promos_ = { + promos_manager::Promo::AppStoreRating}; + promos_manager_->single_display_pending_promos_ = { + {promos_manager::Promo::Test, test_clock_.Now() + kTimeDelta1Hour}, + {promos_manager::Promo::CredentialProviderExtension, + test_clock_.Now() + kTimeDelta1Hour}, + }; + + int today = TodaysDay(); + const std::vector<promos_manager::Impression> impressions = { + promos_manager::Impression(promos_manager::Promo::Test, today), + }; + promos_manager_->impression_history_ = impressions; + + // Advance the time so that all pending promos can become active, but will + // fall into the two-day window since the last impression. + test_clock_.Advance(kTimeDelta1Day); + + absl::optional<promos_manager::Promo> promo = + promos_manager_->NextPromoForDisplay(); + + EXPECT_FALSE(promo.has_value()); +}
diff --git a/ios/chrome/browser/segmentation_platform/segmentation_platform_service_factory.mm b/ios/chrome/browser/segmentation_platform/segmentation_platform_service_factory.mm index c91f5d9..0ebffee 100644 --- a/ios/chrome/browser/segmentation_platform/segmentation_platform_service_factory.mm +++ b/ios/chrome/browser/segmentation_platform/segmentation_platform_service_factory.mm
@@ -48,6 +48,21 @@ return instance.get(); } +std::unique_ptr<processing::InputDelegateHolder> SetUpInputDelegates( + std::vector<std::unique_ptr<Config>>& configs) { + auto input_delegate_holder = + std::make_unique<processing::InputDelegateHolder>(); + for (auto& config : configs) { + for (auto& id : config->input_delegates) { + input_delegate_holder->SetDelegate(id.first, std::move(id.second)); + } + } + + // Add shareable input delegates here. + + return input_delegate_holder; +} + // Observes existance of Incognito tabs in the application. class IncognitoObserver : public OTRWebStateObserver::ObserverClient, public base::SupportsUserData::Data { @@ -116,6 +131,7 @@ params->device_info_tracker = DeviceInfoSyncServiceFactory::GetForBrowserState(chrome_browser_state) ->GetDeviceInfoTracker(); + params->input_delegate_holder = SetUpInputDelegates(params->configs); auto service = std::make_unique<SegmentationPlatformServiceImpl>(std::move(params));
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm index a78106c1..9b3e853 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -273,10 +273,8 @@ LocalSaveCardPromptCallback callback) { DCHECK(options.show_prompt); infobar_manager_->AddInfoBar(CreateSaveCardInfoBarMobile( - std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/false, options, card, LegalMessageLines(), - /*upload_save_card_callback=*/UploadSaveCardPromptCallback(), - /*local_save_card_callback=*/std::move(callback), AccountInfo()))); + AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( + options, card, std::move(callback)))); } void ChromeAutofillClientIOS::ConfirmAccountNameFixFlow( @@ -317,10 +315,9 @@ AccountInfo account_info = identity_manager_->FindExtendedAccountInfo( identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)); infobar_manager_->AddInfoBar(CreateSaveCardInfoBarMobile( - std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/true, options, card, legal_message_lines, - /*upload_save_card_callback=*/std::move(callback), - LocalSaveCardPromptCallback(), account_info))); + AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( + options, card, std::move(callback), legal_message_lines, + account_info))); } void ChromeAutofillClientIOS::CreditCardUploadCompleted(bool card_saved) {
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn index 679223ca1..5714e63 100644 --- a/ios/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -14,13 +14,6 @@ "bookmarks_coordinator.h", "bookmarks_coordinator.mm", "bookmarks_coordinator_delegate.h", - "bookmarks_home_consumer.h", - "bookmarks_home_mediator.h", - "bookmarks_home_mediator.mm", - "bookmarks_home_shared_state.h", - "bookmarks_home_shared_state.mm", - "bookmarks_home_view_controller.h", - "bookmarks_home_view_controller.mm", "synced_bookmarks_bridge.h", "synced_bookmarks_bridge.mm", ] @@ -30,68 +23,43 @@ "resources:bookmark_blue_check", "resources:bookmark_blue_folder", "resources:bookmark_blue_new_folder", - "resources:bookmark_empty", "resources:bookmark_empty_star", "//base", "//components/bookmarks/browser", - "//components/bookmarks/common", - "//components/bookmarks/managed", "//components/prefs", - "//components/prefs/ios", - "//components/signin/public/identity_manager", "//components/signin/public/identity_manager/objc", - "//components/strings", - "//components/sync/driver", - "//ios/chrome/app:tests_hook", "//ios/chrome/app/strings", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/drag_and_drop", - "//ios/chrome/browser/favicon", "//ios/chrome/browser/main:public", "//ios/chrome/browser/metrics:metrics_internal", - "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", "//ios/chrome/browser/tabs", - "//ios/chrome/browser/ui:feature_flags", - "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/authentication", - "//ios/chrome/browser/ui/authentication:signin_presenter", "//ios/chrome/browser/ui/authentication/cells", - "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils", - "//ios/chrome/browser/ui/bookmarks/cells", "//ios/chrome/browser/ui/bookmarks/editor", "//ios/chrome/browser/ui/bookmarks/folder_chooser", "//ios/chrome/browser/ui/bookmarks/folder_editor", + "//ios/chrome/browser/ui/bookmarks/home", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/default_promo:utils", - "//ios/chrome/browser/ui/elements", - "//ios/chrome/browser/ui/incognito_reauth:incognito_reauth_scene_agent", - "//ios/chrome/browser/ui/keyboard", - "//ios/chrome/browser/ui/list_model", - "//ios/chrome/browser/ui/main:scene_state_header", - "//ios/chrome/browser/ui/menu", - "//ios/chrome/browser/ui/sharing", - "//ios/chrome/browser/ui/sharing/activity_services", "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:presentation", - "//ios/chrome/browser/ui/table_view:styler", - "//ios/chrome/browser/ui/table_view:utils", - "//ios/chrome/browser/ui/table_view:views", + "//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util:url_with_title", "//ios/chrome/browser/url_loading", "//ios/chrome/browser/web_state_list", - "//ios/chrome/browser/window_activities", "//ios/chrome/common/ui/colors", - "//ios/chrome/common/ui/favicon:favicon", - "//ios/chrome/common/ui/favicon:favicon_constants", "//ios/chrome/common/ui/util", "//ios/third_party/material_components_ios", "//ui/base", ] frameworks = [ "UIKit.framework" ] + + # TODO(crbug.com/1409490): Remove the circular dependency. + allow_circular_includes_from = [ "//ios/chrome/browser/ui/bookmarks/home" ] } source_set("core") { @@ -147,29 +115,16 @@ sources = [ "bookmark_path_cache_unittest.mm", "bookmark_utils_ios_unittest.mm", - "bookmarks_home_view_controller_unittest.mm", ] deps = [ ":bookmarks", - ":constants", ":core", "//base", - "//base/test:test_support", "//components/bookmarks/browser", - "//components/bookmarks/test", "//components/sync_preferences:test_support", - "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/bookmarks:test_support", - "//ios/chrome/browser/bookmarks:test_support", - "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/flags:system_flags", - "//ios/chrome/browser/main:public", - "//ios/chrome/browser/main:test_support", - "//ios/chrome/browser/ui/commands", - "//ios/chrome/test:test_support", - "//ios/web/public/test", "//testing/gtest", - "//third_party/ocmock:ocmock", ] } @@ -204,7 +159,7 @@ "//ios/chrome/test/earl_grey:eg_test_support+eg2", "//ios/testing/earl_grey:eg_test_support+eg2", "//ios/third_party/earl_grey2:test_lib", - "//ios/web/public/test/http_server:http_server", + "//ios/web/public/test/http_server", "//net", "//net:test_support", "//ui/base",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm index bbd951bf..15f8b918 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm
@@ -28,10 +28,10 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" #import "ios/chrome/browser/ui/bookmarks/bookmarks_coordinator_delegate.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/snackbar_commands.h"
diff --git a/ios/chrome/browser/ui/bookmarks/folder_editor/BUILD.gn b/ios/chrome/browser/ui/bookmarks/folder_editor/BUILD.gn index b634535c..e2fb103c 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_editor/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/folder_editor/BUILD.gn
@@ -36,6 +36,8 @@ "//ios/chrome/common/ui/util", "//ui/base", ] + + # TODO(crbug.com/1409488): Remove the circular dependency. allow_circular_includes_from = [ "//ios/chrome/browser/ui/bookmarks/folder_chooser" ] }
diff --git a/ios/chrome/browser/ui/bookmarks/home/BUILD.gn b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn new file mode 100644 index 0000000..faff5da --- /dev/null +++ b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn
@@ -0,0 +1,84 @@ +source_set("home") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "bookmarks_home_consumer.h", + "bookmarks_home_mediator.h", + "bookmarks_home_mediator.mm", + "bookmarks_home_shared_state.h", + "bookmarks_home_shared_state.mm", + "bookmarks_home_view_controller.h", + "bookmarks_home_view_controller.mm", + ] + deps = [ + "//components/bookmarks/browser", + "//components/bookmarks/common", + "//components/bookmarks/managed", + "//components/prefs", + "//components/prefs/ios", + "//components/strings:components_strings_grit", + "//ios/chrome/app:tests_hook", + "//ios/chrome/app/strings:ios_strings_grit", + "//ios/chrome/browser/bookmarks", + "//ios/chrome/browser/bookmarks:bookmarks_utils", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/drag_and_drop", + "//ios/chrome/browser/favicon", + "//ios/chrome/browser/metrics:metrics_internal", + "//ios/chrome/browser/policy:policy_util", + "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/alert_coordinator", + "//ios/chrome/browser/ui/authentication", + "//ios/chrome/browser/ui/authentication:signin_presenter", + "//ios/chrome/browser/ui/authentication/cells", + "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils", + "//ios/chrome/browser/ui/bookmarks:constants", + "//ios/chrome/browser/ui/bookmarks:core", + "//ios/chrome/browser/ui/bookmarks/cells", + "//ios/chrome/browser/ui/bookmarks/editor", + "//ios/chrome/browser/ui/bookmarks/folder_chooser", + "//ios/chrome/browser/ui/bookmarks/resources:bookmark_empty", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/default_promo:utils", + "//ios/chrome/browser/ui/elements", + "//ios/chrome/browser/ui/incognito_reauth:incognito_reauth_scene_agent", + "//ios/chrome/browser/ui/keyboard", + "//ios/chrome/browser/ui/list_model:list_model", + "//ios/chrome/browser/ui/main:scene_state_header", + "//ios/chrome/browser/ui/menu", + "//ios/chrome/browser/ui/sharing", + "//ios/chrome/browser/ui/sharing/activity_services", + "//ios/chrome/browser/ui/table_view", + "//ios/chrome/browser/ui/table_view:constants", + "//ios/chrome/browser/ui/table_view:styler", + "//ios/chrome/browser/ui/table_view:utils", + "//ios/chrome/browser/ui/table_view:views", + "//ios/chrome/browser/ui/util", + "//ios/chrome/browser/url_loading", + "//ios/chrome/browser/web_state_list", + "//ios/chrome/browser/window_activities", + "//ios/chrome/common/ui/colors", + "//ios/chrome/common/ui/favicon", + "//ios/chrome/common/ui/favicon:favicon_constants", + "//ios/chrome/common/ui/util", + "//ios/web/public/navigation", + "//ios/web/public/navigation:referrer", + "//ui/base", + ] + frameworks = [ "UIKit.framework" ] +} + +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ "bookmarks_home_view_controller_unittest.mm" ] + deps = [ + "//base/test:test_support", + "//components/bookmarks/browser", + "//ios/chrome/browser/bookmarks:test_support", + "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/main:public", + "//ios/chrome/browser/ui/bookmarks/home", + "//ios/chrome/browser/ui/commands", + "//third_party/ocmock:ocmock", + ] +}
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_consumer.h b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_consumer.h similarity index 88% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_consumer.h rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_consumer.h index 1bed4d7..c30d702 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_consumer.h +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_consumer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_CONSUMER_H_ -#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_CONSUMER_H_ +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_CONSUMER_H_ #import "ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h" @@ -51,4 +51,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_CONSUMER_H_ +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.h b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h similarity index 86% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.h rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h index a42468f..9f9e4458 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.h +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_MEDIATOR_H_ -#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_MEDIATOR_H_ +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_MEDIATOR_H_ #import <Foundation/Foundation.h> @@ -44,4 +44,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_MEDIATOR_H_ +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm similarity index 98% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.mm rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm index eed10ca..e28aa1ae3 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h" #import "base/check.h" #import "base/mac/foundation_util.h" @@ -25,9 +25,9 @@ #import "ios/chrome/browser/ui/authentication/signin_presenter.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_promo_controller.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_consumer.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h" #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_home_node_item.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_consumer.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h" #import "ios/chrome/browser/ui/bookmarks/synced_bookmarks_bridge.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" #import "ios/chrome/browser/ui/table_view/table_view_model.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h similarity index 93% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h index f33bc4f..73be797 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_SHARED_STATE_H_ -#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_SHARED_STATE_H_ +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_SHARED_STATE_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_SHARED_STATE_H_ #import <UIKit/UIKit.h> @@ -117,4 +117,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_SHARED_STATE_H_ +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_SHARED_STATE_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.mm similarity index 97% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.mm rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.mm index 53de20b..bb2f31b1 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h" #import "base/check.h" #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell_title_editing.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h similarity index 91% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h index 4f64eec..5370e96 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_VIEW_CONTROLLER_H_ #import <UIKit/UIKit.h> @@ -74,4 +74,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARKS_HOME_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_BOOKMARKS_HOME_BOOKMARKS_HOME_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm similarity index 99% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.mm rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm index e65ba9d..0513486 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h" #import "base/ios/ios_util.h" #import "base/mac/foundation_util.h" @@ -40,14 +40,14 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" #import "ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.h" #import "ios/chrome/browser/ui/bookmarks/bookmarks_coordinator_delegate.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_consumer.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_mediator.h" -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_shared_state.h" #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_folder_item.h" #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_home_node_item.h" #import "ios/chrome/browser/ui/bookmarks/cells/bookmark_table_cell_title_edit_delegate.h" #import "ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.h" #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_consumer.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_shared_state.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/snackbar_commands.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller_unittest.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm similarity index 97% rename from ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller_unittest.mm rename to ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm index c916098..5a79f84 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/bookmarks/bookmarks_home_view_controller.h" +#import "ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.h" #import "base/test/metrics/user_action_tester.h" #import "components/bookmarks/browser/bookmark_model.h"
diff --git a/ios/chrome/browser/ui/default_promo/BUILD.gn b/ios/chrome/browser/ui/default_promo/BUILD.gn index 4a28895..b4c1218 100644 --- a/ios/chrome/browser/ui/default_promo/BUILD.gn +++ b/ios/chrome/browser/ui/default_promo/BUILD.gn
@@ -9,9 +9,10 @@ "default_browser_utils.mm", ] deps = [ - "//base", + "//components/feature_engagement/public", "//ios/chrome/browser/ui:feature_flags", ] + public_deps = [ "//base" ] frameworks = [ "Foundation.framework" ] }
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_utils.h b/ios/chrome/browser/ui/default_promo/default_browser_utils.h index d692b9f..e0f352a 100644 --- a/ios/chrome/browser/ui/default_promo/default_browser_utils.h +++ b/ios/chrome/browser/ui/default_promo/default_browser_utils.h
@@ -7,6 +7,12 @@ #import <UIKit/UIKit.h> +#import "base/feature_list.h" + +namespace feature_engagement { +class Tracker; +} + // Enum for the different types of default browser modal promo. These are stored // as values, if adding a new one, make sure to add it at the end. typedef NS_ENUM(NSUInteger, DefaultPromoType) { @@ -49,6 +55,13 @@ // delay time threshold has been met. bool ShouldShowRemindMeLaterDefaultBrowserFullscreenPromo(); +// Returns true if the passed default browser badge `feature` should be shown. +// Also makes the necessary calls to the FET for keeping track of usage, as well +// as checking that the correct preconditions are met. +bool ShouldTriggerDefaultBrowserBlueDotBadgeFeature( + const base::Feature& feature, + feature_engagement::Tracker* tracker); + // Returns true if the user is in the group that will be shown the Remind Me // Later button in the fullscreen promo. bool IsInRemindMeLaterGroup(); @@ -57,6 +70,13 @@ // description and "Learn More" text. bool IsInModifiedStringsGroup(); +// Returns true if the user is in the default browser blue dot experiment. +bool IsInBlueDotExperiment(); + +// Returns true if the user is in the default browser blue dot experiment and in +// the blue dot active/enabled group. +bool IsInBlueDotExperimentEnabledGroup(); + // Returns true if the user is in the CTA experiment in the open links group. bool IsInCTAOpenLinksGroup(); @@ -103,6 +123,10 @@ // the last 7 days and records the current paste. bool HasRecentValidURLPastesAndRecordsCurrentPaste(); +// Returns YES if the last timestamp passed as `eventKey` is part of the current +// user session (6 hours). If not, it records the timestamp. +bool HasRecentTimestampForKey(NSString* eventKey); + // Returns true if the last URL open is within the time threshold that would // indicate Chrome is likely still the default browser. Returns false otherwise. bool IsChromeLikelyDefaultBrowser();
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_utils.mm b/ios/chrome/browser/ui/default_promo/default_browser_utils.mm index bd81567..ccfd2eb 100644 --- a/ios/chrome/browser/ui/default_promo/default_browser_utils.mm +++ b/ios/chrome/browser/ui/default_promo/default_browser_utils.mm
@@ -4,12 +4,13 @@ #import "ios/chrome/browser/ui/default_promo/default_browser_utils.h" -#import "base/feature_list.h" #import "base/ios/ios_util.h" #import "base/mac/foundation_util.h" #import "base/metrics/field_trial_params.h" #import "base/notreached.h" #import "base/time/time.h" +#import "components/feature_engagement/public/feature_constants.h" +#import "components/feature_engagement/public/tracker.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -128,9 +129,8 @@ constexpr base::TimeDelta kMaximumTimeBetweenFirstPartyAppLaunches = base::Days(7); -// Minimum time range between first-party app launches to notify the FET. -constexpr base::TimeDelta kMinimumTimeBetweenFirstPartyAppLaunches = - base::Hours(6); +// Maximum time representing one user session. +constexpr base::TimeDelta kMaximumTimeOneUserSession = base::Hours(6); // Maximum time range between valid user URL pastes to notify the FET. constexpr base::TimeDelta kMaximumTimeBetweenValidURLPastes = base::Days(7); @@ -351,6 +351,34 @@ kRemindMeLaterPromoActionInteraction, kRemindMeLaterPresentationDelay); } +bool ShouldTriggerDefaultBrowserBlueDotBadgeFeature( + const base::Feature& feature, + feature_engagement::Tracker* tracker) { + if (!IsInBlueDotExperimentEnabledGroup() || IsChromeLikelyDefaultBrowser()) { + return false; + } + + // We need to ask the FET whether or not we should show this IPH because if + // yes, this will automatically notify the other dependent FET features that + // their criteria have been met. We then automatically dismiss it. Since it's + // just a shadow feature to enable the other two needed for the blue dot + // promo, we ignore `ShouldTriggerHelpUI`'s return value. + if (tracker->ShouldTriggerHelpUI( + feature_engagement::kIPHiOSDefaultBrowserBadgeEligibilityFeature)) { + tracker->Dismissed( + feature_engagement::kIPHiOSDefaultBrowserBadgeEligibilityFeature); + } + + // Now, we ask the appropriate FET feature if it should trigger, i.e. if we + // should show the blue dot promo badge. + if (tracker->ShouldTriggerHelpUI(feature)) { + tracker->Dismissed(feature); + return true; + } + + return false; +} + bool IsInRemindMeLaterGroup() { std::string paramValue = base::GetFieldTrialParamValueByFeature( kDefaultBrowserFullscreenPromoExperiment, @@ -365,6 +393,19 @@ return !paramValue.empty(); } +bool IsInBlueDotExperiment() { + return base::FeatureList::IsEnabled(kDefaultBrowserBlueDotPromo); +} + +bool IsInBlueDotExperimentEnabledGroup() { + if (base::FeatureList::IsEnabled(kDefaultBrowserBlueDotPromo)) { + return kBlueDotPromoUserGroupParam.Get() == + BlueDotPromoUserGroup::kOnlyBlueDotPromoEnabled; + } + + return false; +} + bool NonModalPromosEnabled() { // Default browser isn't enabled until iOS 14.0.1, regardless of flag state. return base::ios::IsRunningOnOrLater(14, 0, 1); @@ -446,7 +487,7 @@ kMaximumTimeBetweenFirstPartyAppLaunches)) { if (HasRecordedEventForKeyMoreThanDelay( kTimestampAppLastOpenedViaFirstPartyIntent, - kMinimumTimeBetweenFirstPartyAppLaunches)) { + kMaximumTimeOneUserSession)) { SetObjectIntoStorageForKey(kTimestampAppLastOpenedViaFirstPartyIntent, [NSDate date]); return YES; @@ -471,6 +512,16 @@ return NO; } +bool HasRecentTimestampForKey(NSString* eventKey) { + if (HasRecordedEventForKeyLessThanDelay(eventKey, + kMaximumTimeOneUserSession)) { + return YES; + } + + SetObjectIntoStorageForKey(eventKey, [NSDate date]); + return NO; +} + bool IsChromeLikelyDefaultBrowser7Days() { return HasRecordedEventForKeyLessThanDelay(kLastHTTPURLOpenTime, base::Days(7));
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index e5f0ca0d..86dfd3b0 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -338,9 +338,12 @@ UIImage* image = UseSymbols() ? CustomSymbolWithPointSize( kCameraLensSymbol, kSymbolActionPointSize) : [UIImage imageNamed:@"lens_icon"]; + int actionTitleMessageId = + base::FeatureList::IsEnabled(kEnableLensContextMenuAltText) + ? IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE_ALT_TEXT + : IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE; UIAction* action = - [self actionWithTitle:l10n_util::GetNSString( - IDS_IOS_CONTEXT_MENU_SEARCHIMAGEWITHGOOGLE) + [self actionWithTitle:l10n_util::GetNSString(actionTitleMessageId) image:image type:MenuActionType::SearchImageWithLens block:block];
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator_unittest.mm index 2a41f00..ae23696 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator_unittest.mm
@@ -50,16 +50,9 @@ "https://www.example.com/"); std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile> passed_delegate = - std::make_unique<autofill::AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/false, + autofill::AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( autofill::AutofillClient::SaveCreditCardOptions(), credit_card, - autofill::LegalMessageLines(), - autofill::AutofillClient::UploadSaveCardPromptCallback(), - base::BindOnce( - ^(autofill::AutofillClient::SaveCardOfferUserDecision - user_decision){ - }), - AccountInfo()); + base::DoNothing()); autofill::AutofillSaveCardInfoBarDelegateMobile* delegate = passed_delegate.get(); InfoBarIOS infobar(InfobarType::kInfobarTypeSaveCard, @@ -93,18 +86,9 @@ "https://www.example.com/"); std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile> passed_delegate = - std::make_unique<autofill::AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/true, + autofill::AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( autofill::AutofillClient::SaveCreditCardOptions(), credit_card, - autofill::LegalMessageLines(), - base::BindOnce( - ^(autofill::AutofillClient::SaveCardOfferUserDecision - user_decision, - const autofill::AutofillClient::UserProvidedCardDetails& - user_provided_card_details){ - }), - autofill::AutofillClient::LocalSaveCardPromptCallback(), - AccountInfo()); + base::DoNothing(), autofill::LegalMessageLines(), AccountInfo()); InfoBarIOS infobar(InfobarType::kInfobarTypeSaveCard, std::move(passed_delegate)); @@ -133,16 +117,9 @@ "https://www.example.com/"); std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile> passed_delegate = - std::make_unique<autofill::AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/false, + autofill::AutofillSaveCardInfoBarDelegateMobile::CreateForLocalSave( autofill::AutofillClient::SaveCreditCardOptions(), credit_card, - autofill::LegalMessageLines(), - autofill::AutofillClient::UploadSaveCardPromptCallback(), - base::BindOnce( - ^(autofill::AutofillClient::SaveCardOfferUserDecision - user_decision){ - }), - AccountInfo()); + base::DoNothing()); InfoBarIOS infobar(InfobarType::kInfobarTypeSaveCard, std::move(passed_delegate));
diff --git a/ios/chrome/browser/ui/overlays/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm index 66d942a..c3552697 100644 --- a/ios/chrome/browser/ui/overlays/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm
@@ -82,19 +82,11 @@ autofill::LegalMessageLines( {autofill::TestLegalMessageLine("Test message")}); std::unique_ptr<autofill::AutofillSaveCardInfoBarDelegateMobile> delegate = - std::make_unique<autofill::AutofillSaveCardInfoBarDelegateMobile>( - /*upload=*/true, autofill::AutofillClient::SaveCreditCardOptions(), + autofill::AutofillSaveCardInfoBarDelegateMobile::CreateForUploadSave( + autofill::AutofillClient::SaveCreditCardOptions(), autofill::CreditCard(base::GenerateGUID(), "https://www.example.com/"), - legal_message_lines, - base::BindOnce( - ^(autofill::AutofillClient::SaveCardOfferUserDecision - user_decision, - const autofill::AutofillClient::UserProvidedCardDetails& - user_provided_card_details){ - }), - autofill::AutofillClient::LocalSaveCardPromptCallback(), - AccountInfo()); + base::DoNothing(), legal_message_lines, AccountInfo()); delegate_ = delegate.get(); infobar_ = std::make_unique<InfoBarIOS>(InfobarType::kInfobarTypeSaveCard, std::move(delegate));
diff --git a/ios/chrome/browser/ui/passwords/BUILD.gn b/ios/chrome/browser/ui/passwords/BUILD.gn index d3a3b4c..42bd4426 100644 --- a/ios/chrome/browser/ui/passwords/BUILD.gn +++ b/ios/chrome/browser/ui/passwords/BUILD.gn
@@ -22,6 +22,7 @@ "password_suggestion_view_controller.h", "password_suggestion_view_controller.mm", ] + public_deps = [ "account_storage_notice" ] deps = [ ":constants", "resources",
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/BUILD.gn b/ios/chrome/browser/ui/passwords/account_storage_notice/BUILD.gn new file mode 100644 index 0000000..9eeaa0c44 --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("account_storage_notice") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "passwords_account_storage_notice_view_controller.h", + "passwords_account_storage_notice_view_controller.mm", + ] + deps = [ + "resources:illustration", + "//base", + "//ios/chrome/app/strings", + "//ios/chrome/common:string_util", + "//ios/chrome/common/ui/confirmation_alert", + "//ui/base", + ] +}
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.h b/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.h new file mode 100644 index 0000000..3dbcd6e0 --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.h
@@ -0,0 +1,49 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_PASSWORDS_ACCOUNT_STORAGE_NOTICE_PASSWORDS_ACCOUNT_STORAGE_NOTICE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_PASSWORDS_ACCOUNT_STORAGE_NOTICE_PASSWORDS_ACCOUNT_STORAGE_NOTICE_VIEW_CONTROLLER_H_ + +#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h" +#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h" + +#import <Foundation/Foundation.h> + +// Handles user interactions with PasswordsAccountStorageNoticeViewController. +@protocol + PasswordsAccountStorageNoticeActionHandler <ConfirmationAlertActionHandler> + +// The link to password settings was tapped. +- (void)confirmationAlertSettingsAction; + +// The sheet was dismissed by sliding. +- (void)confirmationAlertSwipeDismissAction; + +@end + +// Bottom sheet that notifies the user they are now saving passwords to their +// Google Account. The sheet contains: +// - An OK button, in case the user wants to keep the feature enabled. +// - A link to the password settings page, in case the user wants to disable +// the feature via the appropriate switch. +@interface PasswordsAccountStorageNoticeViewController + : ConfirmationAlertViewController + +- (instancetype)initWithActionHandler: + (id<PasswordsAccountStorageNoticeActionHandler>) + actionHandler + accountStoringPasswords:(NSString*)accountStoringPasswords + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithNibName:(NSString*)name + bundle:(NSBundle*)bundle NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; + +// The action handler for interactions in this View Controller. +@property(nonatomic, weak) id<PasswordsAccountStorageNoticeActionHandler> + actionHandler; + +@end + +#endif // IOS_CHROME_BROWSER_UI_PASSWORDS_ACCOUNT_STORAGE_NOTICE_PASSWORDS_ACCOUNT_STORAGE_NOTICE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.mm b/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.mm new file mode 100644 index 0000000..0ec5a6d --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.mm
@@ -0,0 +1,122 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/passwords/account_storage_notice/passwords_account_storage_notice_view_controller.h" + +#import "base/check_op.h" +#import "base/strings/sys_string_conversions.h" +#import "ios/chrome/common/string_util.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#pragma mark - PasswordsAccountStorageNoticeViewController + +@interface PasswordsAccountStorageNoticeViewController () < + UIAdaptivePresentationControllerDelegate, + UITextViewDelegate> + +@property(nonatomic, strong, readonly) NSString* accountStoringPasswords; + +@end + +@implementation PasswordsAccountStorageNoticeViewController + +@dynamic actionHandler; + +- (instancetype)initWithActionHandler: + (id<PasswordsAccountStorageNoticeActionHandler>) + actionHandler + accountStoringPasswords:(NSString*)accountStoringPasswords { + self = [super initWithNibName:nil bundle:nil]; + if (!self) { + return nil; + } + + _accountStoringPasswords = accountStoringPasswords; + self.actionHandler = actionHandler; + self.presentationController.delegate = self; + if (@available(iOS 15, *)) { + self.modalPresentationStyle = UIModalPresentationPageSheet; + self.sheetPresentationController.preferredCornerRadius = 20; + // Both prefersEdgeAttachedInCompactHeight and mediumDetent serve to keep + // the sheet at half-height. + self.sheetPresentationController.prefersEdgeAttachedInCompactHeight = YES; + self.sheetPresentationController.detents = @[ + UISheetPresentationControllerDetent.mediumDetent, + ]; + } else { + self.modalPresentationStyle = UIModalPresentationFormSheet; + } + return self; +} + +- (void)viewDidLoad { + self.image = + [UIImage imageNamed:@"passwords_account_storage_notice_illustration"]; + self.imageHasFixedSize = YES; + self.showDismissBarButton = NO; + self.customSpacingAfterImage = 32; + self.customSpacingBeforeImageIfNoNavigationBar = 16; + self.titleTextStyle = UIFontTextStyleTitle2; + self.topAlignedLayout = YES; + self.titleString = + l10n_util::GetNSString(IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_TITLE); + self.subtitleString = [self subtitleStringWithTag].string; + self.primaryActionString = l10n_util::GetNSString( + IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_BUTTON_TEXT); + + [super viewDidLoad]; +} + +#pragma mark - ConfirmationAlertViewController + +- (void)customizeSubtitle:(UITextView*)subtitle { + subtitle.delegate = self; + // Makes the link clickable. + subtitle.selectable = YES; + // Inherits the default styling already applied to `subtitle`. + NSMutableAttributedString* newSubtitle = [[NSMutableAttributedString alloc] + initWithAttributedString:subtitle.attributedText]; + // The URL value is arbitrary because the click will be handled via the + // UITextViewDelegate implementation. + [newSubtitle addAttribute:NSLinkAttributeName + value:@"" + range:[self subtitleStringWithTag].range]; + subtitle.attributedText = newSubtitle; +} + +#pragma mark - UITextViewDelegate + +- (BOOL)textView:(UITextView*)textView + shouldInteractWithURL:(NSURL*)URL + inRange:(NSRange)characterRange + interaction:(UITextItemInteraction)interaction { + [self.actionHandler confirmationAlertSettingsAction]; + // `self` might be deleted. + return NO; +} + +#pragma mark - UIAdaptivePresentationControllerDelegate + +- (void)presentationControllerDidDismiss: + (UIPresentationController*)presentationController { + [self.actionHandler confirmationAlertSwipeDismissAction]; + // `self` might be deleted. +} + +#pragma mark - Private + +- (StringWithTag)subtitleStringWithTag { + StringWithTags stringWithTags = ParseStringWithLinks(l10n_util::GetNSStringF( + IDS_IOS_PASSWORDS_ACCOUNT_STORAGE_NOTICE_SUBTITLE, + base::SysNSStringToUTF16(self.accountStoringPasswords))); + DCHECK_EQ(stringWithTags.ranges.size(), 1u); + return {stringWithTags.string, stringWithTags.ranges[0]}; +} + +@end
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/resources/BUILD.gn b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/BUILD.gn new file mode 100644 index 0000000..d5906015 --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/BUILD.gn
@@ -0,0 +1,13 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/asset_catalog.gni") + +imageset("illustration") { + sources = [ + "passwords_account_storage_notice_illustration.imageset/Contents.json", + "passwords_account_storage_notice_illustration.imageset/illustration_dark.pdf", + "passwords_account_storage_notice_illustration.imageset/illustration_light.pdf", + ] +}
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/Contents.json b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/Contents.json new file mode 100644 index 0000000..25765954 --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/Contents.json
@@ -0,0 +1,25 @@ +{ + "images" : [ + { + "filename" : "illustration_light.pdf", + "idiom" : "universal" + }, + { + "filename" : "illustration_dark.pdf", + "idiom" : "universal", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ] + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +}
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_dark.pdf b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_dark.pdf new file mode 100644 index 0000000..806c778e --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_dark.pdf
@@ -0,0 +1,624 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 107.554688 2.000000 cm +0.235294 0.250980 0.262745 scn +126.525101 77.330658 m +126.618629 76.786346 127.135696 76.420914 127.680000 76.514442 c +128.224304 76.607971 128.589737 77.125038 128.496216 77.669342 c +126.525101 77.330658 l +h +126.067139 45.682381 m +126.242554 46.206062 125.960228 46.772804 125.436539 46.948219 c +124.912857 47.123634 124.346115 46.841309 124.170700 46.317619 c +126.067139 45.682381 l +h +-0.991446 75.130524 m +-1.063529 74.582962 -0.678079 74.080643 -0.130519 74.008553 c +0.417041 73.936470 0.919362 74.321922 0.991446 74.869476 c +-0.991446 75.130524 l +h +8.797826 34.996849 m +8.523426 35.476143 7.912436 35.642242 7.433141 35.367836 c +6.953847 35.093437 6.787748 34.482452 7.062148 34.003151 c +8.797826 34.996849 l +h +98.630516 119.698715 m +99.092865 119.396637 99.712555 119.526566 100.014633 119.988914 c +100.316711 120.451263 100.186783 121.070953 99.724434 121.373032 c +98.630516 119.698715 l +h +117.585968 104.097939 m +117.268585 104.549927 116.644897 104.659042 116.192909 104.341660 c +115.740929 104.024277 115.631813 103.400589 115.949188 102.948608 c +117.585968 104.097939 l +h +96.921394 12.223000 m +96.449677 11.935776 96.300110 11.320534 96.587334 10.848808 c +96.874557 10.377090 97.489799 10.227524 97.961525 10.514748 c +96.921394 12.223000 l +h +81.604309 3.408424 m +82.136230 3.557007 82.446991 4.108665 82.298416 4.640587 c +82.149834 5.172508 81.598175 5.483269 81.066254 5.334694 c +81.604309 3.408424 l +h +20.445116 115.470490 m +20.032339 115.103569 19.995171 114.471497 20.362095 114.058716 c +20.729021 113.645943 21.361094 113.608772 21.773870 113.975693 c +20.445116 115.470490 l +h +11.295550 102.012276 m +11.604806 102.469856 11.484565 103.091499 11.026985 103.400757 c +10.569405 103.710007 9.947762 103.589767 9.638507 103.132187 c +11.295550 102.012276 l +h +63.944908 3.000000 m +40.340767 3.000000 19.743305 15.878403 8.797826 34.996849 c +7.062148 34.003151 l +18.349339 14.287842 39.594734 1.000000 63.944908 1.000000 c +63.944908 3.000000 l +h +63.944908 130.000000 m +76.746124 130.000000 88.659821 126.213097 98.630516 119.698715 c +99.724434 121.373032 l +89.438385 128.093445 77.146339 132.000000 63.944908 132.000000 c +63.944908 130.000000 l +h +115.949188 102.948608 m +121.221542 95.440208 124.908478 86.739120 126.525101 77.330658 c +128.496216 77.669342 l +126.828247 87.376656 123.024094 96.353455 117.585968 104.097939 c +115.949188 102.948608 l +h +124.170700 46.317619 m +119.373344 31.995720 109.608574 19.947990 96.921394 12.223000 c +97.961525 10.514748 l +111.045662 18.481438 121.117622 30.906212 126.067139 45.682381 c +124.170700 46.317619 l +h +81.066254 5.334694 m +75.620590 3.813583 69.878578 3.000000 63.944908 3.000000 c +63.944908 1.000000 l +70.062187 1.000000 75.985161 1.838867 81.604309 3.408424 c +81.066254 5.334694 l +h +21.773870 113.975693 m +32.989281 123.945305 47.758816 130.000000 63.944908 130.000000 c +63.944908 132.000000 l +47.250359 132.000000 32.012478 125.752953 20.445116 115.470490 c +21.773870 113.975693 l +h +0.991446 74.869476 m +2.302594 84.829193 5.921991 94.061462 11.295550 102.012276 c +9.638507 103.132187 l +4.095732 94.931000 0.361261 85.405914 -0.991446 75.130524 c +0.991446 74.869476 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 93.944336 0.121460 cm +0.235294 0.250980 0.262745 scn +127.944687 3.049438 m +127.507614 2.711823 127.426994 2.083817 127.764610 1.646744 c +128.102234 1.209671 128.730240 1.129044 129.167313 1.466675 c +127.944687 3.049438 l +h +25.944679 1.466675 m +26.381752 1.129044 27.009762 1.209671 27.347382 1.646744 c +27.684999 2.083817 27.604378 2.711823 27.167305 3.049438 c +25.944679 1.466675 l +h +129.167313 135.290527 m +128.730240 135.628159 128.102234 135.547531 127.764610 135.110458 c +127.426994 134.673386 127.507614 134.045380 127.944687 133.707764 c +129.167313 135.290527 l +h +27.167305 133.707748 m +27.604378 134.045364 27.684999 134.673386 27.347382 135.110458 c +27.009762 135.547531 26.381752 135.628143 25.944679 135.290527 c +27.167305 133.707748 l +h +154.183548 99.007576 m +154.388702 98.494804 154.970688 98.245430 155.483459 98.450577 c +155.996216 98.655724 156.245605 99.237709 156.040451 99.750481 c +154.183548 99.007576 l +h +158.360245 43.586021 m +158.522064 44.114067 158.225174 44.673317 157.697128 44.835136 c +157.169083 44.996964 156.609833 44.700081 156.448013 44.172035 c +158.360245 43.586021 l +h +-0.928452 99.750481 m +-1.133600 99.237709 -0.884222 98.655724 -0.371452 98.450577 c +0.141318 98.245430 0.723305 98.494804 0.928452 99.007576 c +-0.928452 99.750481 l +h +3.576396 31.822723 m +3.331352 32.317665 2.731471 32.520248 2.236525 32.275208 c +1.741579 32.030167 1.538993 31.430283 1.784037 30.935333 c +3.576396 31.822723 l +h +127.944687 133.707764 m +139.527466 124.760582 148.664581 112.802315 154.183548 99.007576 c +156.040451 99.750481 l +150.386902 113.881638 141.028549 126.128265 129.167313 135.290527 c +127.944687 133.707764 l +h +156.448013 44.172035 m +151.389328 27.664886 141.290588 13.358551 127.944687 3.049438 c +129.167313 1.466675 l +142.833740 12.023376 153.177780 26.675041 158.360245 43.586021 c +156.448013 44.172035 l +h +0.928452 99.007576 m +6.447410 112.802307 15.584533 124.760574 27.167305 133.707748 c +25.944679 135.290527 l +14.083455 126.128265 4.725099 113.881638 -0.928452 99.750481 c +0.928452 99.007576 l +h +27.167305 3.049438 m +17.277472 10.688904 9.170437 20.523735 3.576396 31.822723 c +1.784037 30.935333 l +7.514006 19.361801 15.816860 9.289955 25.944679 1.466675 c +27.167305 3.049438 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 138.000000 52.000000 cm +0.258824 0.521569 0.956863 scn +22.985996 12.750000 m +21.683998 10.511999 19.271999 9.000000 16.499998 9.000000 c +12.365999 9.000000 8.999999 12.365999 8.999999 16.500000 c +8.999999 20.633999 12.365999 24.000000 16.499998 24.000000 c +19.265999 24.000000 21.683998 22.487999 22.985996 20.250000 c +32.567997 20.250000 l +30.863998 27.546000 24.311995 33.000000 16.505995 33.000000 c +7.403996 33.000000 0.000000 25.596001 0.000000 16.500000 c +0.000000 7.403999 7.404000 0.000000 16.499998 0.000000 c +24.305998 0.000000 30.864000 5.453999 32.562000 12.750000 c +22.985996 12.750000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 170.250000 64.000244 cm +0.984314 0.737255 0.015686 scn +16.500000 9.000000 m +0.000000 9.000000 l +0.000000 0.000000 l +16.500000 0.000000 l +16.500000 9.000000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 186.000000 55.000000 cm +0.203922 0.658824 0.325490 scn +18.000000 9.750000 m +18.000000 0.000000 l +12.000000 0.000000 l +12.000000 3.000000 l +12.000000 4.656000 10.656000 6.000000 9.000000 6.000000 c +7.344000 6.000000 6.000000 4.656000 6.000000 3.000000 c +6.000000 0.000000 l +0.000000 0.000000 l +0.000000 9.750000 l +18.000000 9.750000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 186.000000 64.000244 cm +0.094118 0.501961 0.219608 scn +18.000000 9.000000 m +0.000000 9.000000 l +0.000000 0.000000 l +18.000000 0.000000 l +18.000000 9.000000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 160.500000 64.000244 cm +0.917647 0.262745 0.207843 scn +9.869999 9.000000 m +0.000000 9.000000 l +0.000000 8.982000 l +0.936000 7.728001 1.500000 6.180000 1.500000 4.500000 c +1.500000 2.820000 0.936000 1.271999 0.000000 0.017999 c +0.000000 0.000000 l +9.869999 0.000000 l +10.277999 1.434000 10.500000 2.940000 10.500000 4.500000 c +10.500000 6.060000 10.277999 7.566000 9.869999 9.000000 c +h +f +n +Q +q +301.533813 79.116898 m +302.079285 81.257629 300.786072 83.435234 298.645325 83.980698 c +247.501740 97.012314 l +245.361008 97.557785 243.183411 96.264557 242.637939 94.123825 c +234.020126 60.302536 l +233.474655 58.161804 234.767883 55.984207 236.908615 55.438736 c +288.052216 42.407127 l +290.192932 41.861656 292.370544 43.154877 292.916016 45.295616 c +301.533813 79.116898 l +h +W* +n +q +-0.969037 0.246915 0.246915 0.969037 288.550903 28.164371 cm +0.603922 0.627451 0.650980 scn +4.000000 54.580566 m +56.777737 54.580566 l +56.777737 58.580566 l +4.000000 58.580566 l +4.000000 54.580566 l +h +58.777737 52.580566 m +58.777737 17.678619 l +62.777737 17.678619 l +62.777737 52.580566 l +58.777737 52.580566 l +h +56.777737 15.678623 m +4.000002 15.678623 l +4.000002 11.678623 l +56.777737 11.678623 l +56.777737 15.678623 l +h +2.000000 17.678623 m +2.000000 52.580570 l +-2.000000 52.580570 l +-2.000000 17.678623 l +2.000000 17.678623 l +h +4.000002 15.678623 m +2.895431 15.678623 2.000000 16.574055 2.000000 17.678623 c +-2.000000 17.678623 l +-2.000000 14.364914 0.686294 11.678623 4.000002 11.678623 c +4.000002 15.678623 l +h +58.777737 17.678619 m +58.777737 16.574051 57.882309 15.678623 56.777737 15.678623 c +56.777737 11.678623 l +60.091442 11.678623 62.777737 14.364910 62.777737 17.678619 c +58.777737 17.678619 l +h +56.777737 54.580566 m +57.882305 54.580566 58.777737 53.685135 58.777737 52.580566 c +62.777737 52.580566 l +62.777737 55.894276 60.091442 58.580566 56.777737 58.580566 c +56.777737 54.580566 l +h +4.000000 58.580566 m +0.686294 58.580566 -2.000000 55.894279 -2.000000 52.580570 c +2.000000 52.580570 l +2.000000 53.685139 2.895428 54.580566 4.000000 54.580566 c +4.000000 58.580566 l +h +f +n +Q +Q +q +-0.969037 0.246915 0.246915 0.969037 293.197144 17.438866 cm +0.603922 0.627451 0.650980 scn +0.000000 21.136353 m +75.078392 21.136353 l +75.078392 21.136353 l +75.078392 19.655468 73.877899 18.454975 72.397011 18.454975 c +2.681383 18.454975 l +1.200499 18.454975 0.000000 19.655468 0.000000 21.136353 c +0.000000 21.136353 l +h +f +n +Q +q +-0.969037 0.246915 0.246915 0.969037 272.839752 86.222839 cm +0.741176 0.756863 0.776471 scn +1.411972 1.010933 m +1.411972 0.621027 1.095891 0.304947 0.705986 0.304947 c +0.316081 0.304947 0.000000 0.621027 0.000000 1.010933 c +0.000000 1.400838 0.316081 1.716919 0.705986 1.716919 c +1.095891 1.716919 1.411972 1.400838 1.411972 1.010933 c +h +f +n +Q +q +70.066856 86.143921 m +69.477646 88.273041 70.725990 90.476669 72.855103 91.065880 c +94.058167 96.933578 l +96.187286 97.522789 98.390923 96.274445 98.980125 94.145332 c +112.849243 44.028992 l +113.438446 41.899879 112.190109 39.696243 110.060989 39.107033 c +88.857925 33.239334 l +86.728813 32.650124 84.525177 33.898468 83.935966 36.027580 c +70.066856 86.143921 l +h +W* +n +q +0.963776 0.266714 -0.266714 0.963776 86.557228 26.555592 cm +0.603922 0.627451 0.650980 scn +4.000000 63.828003 m +26.000000 63.828003 l +26.000000 67.828003 l +4.000000 67.828003 l +4.000000 63.828003 l +h +28.000000 61.828003 m +28.000000 9.828003 l +32.000000 9.828003 l +32.000000 61.828003 l +28.000000 61.828003 l +h +26.000000 7.828003 m +4.000000 7.828003 l +4.000000 3.828003 l +26.000000 3.828003 l +26.000000 7.828003 l +h +2.000000 9.828003 m +2.000000 61.828003 l +-2.000000 61.828003 l +-2.000000 9.828003 l +2.000000 9.828003 l +h +4.000000 7.828003 m +2.895431 7.828003 2.000000 8.723434 2.000000 9.828003 c +-2.000000 9.828003 l +-2.000000 6.514294 0.686291 3.828003 4.000000 3.828003 c +4.000000 7.828003 l +h +28.000000 9.828003 m +28.000000 8.723434 27.104570 7.828003 26.000000 7.828003 c +26.000000 3.828003 l +29.313707 3.828003 32.000000 6.514294 32.000000 9.828003 c +28.000000 9.828003 l +h +26.000000 63.828003 m +27.104568 63.828003 28.000000 62.932571 28.000000 61.828003 c +32.000000 61.828003 l +32.000000 65.141708 29.313709 67.828003 26.000000 67.828003 c +26.000000 63.828003 l +h +4.000000 67.828003 m +0.686292 67.828003 -2.000000 65.141708 -2.000000 61.828003 c +2.000000 61.828003 l +2.000000 62.932571 2.895431 63.828003 4.000000 63.828003 c +4.000000 67.828003 l +h +f +n +Q +Q +q +0.963776 0.266714 -0.266714 0.963776 73.444611 85.155014 cm +0.741176 0.756863 0.776471 scn +1.979617 1.446105 m +1.979617 0.899449 1.536464 0.456296 0.989808 0.456296 c +0.443152 0.456296 0.000000 0.899449 0.000000 1.446105 c +0.000000 1.992761 0.443152 2.435913 0.989808 2.435913 c +1.536464 2.435913 1.979617 1.992761 1.979617 1.446105 c +h +f +n +Q +q +-0.963776 -0.266714 -0.266714 0.963776 104.782501 38.713654 cm +0.741176 0.756863 0.776471 scn +0.000000 4.085997 m +0.000000 4.632653 0.443152 5.075806 0.989809 5.075806 c +10.887890 5.075806 l +11.434546 5.075806 11.877700 4.632653 11.877700 4.085997 c +11.877700 4.085997 l +11.877700 3.539341 11.434547 3.096189 10.887891 3.096189 c +0.989810 3.096189 l +0.443154 3.096189 0.000000 3.539341 0.000000 4.085997 c +0.000000 4.085997 l +h +f +n +Q +q +-0.779502 0.626400 0.626400 0.779502 121.170578 103.252815 cm +0.203922 0.658824 0.325490 scn +0.000000 9.247192 m +0.000000 10.351762 0.895431 11.247192 2.000000 11.247192 c +6.000000 11.247192 l +7.104569 11.247192 8.000000 10.351762 8.000000 9.247192 c +8.000000 5.247192 l +8.000000 4.142623 7.104569 3.247192 6.000000 3.247192 c +2.000000 3.247192 l +0.895431 3.247192 0.000000 4.142623 0.000000 5.247192 c +0.000000 9.247192 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 194.500000 6.000000 cm +0.949020 0.545098 0.509804 scn +6.000000 3.000000 m +6.000000 1.343146 4.656854 0.000000 3.000000 0.000000 c +1.343146 0.000000 0.000000 1.343146 0.000000 3.000000 c +0.000000 4.656854 1.343146 6.000000 3.000000 6.000000 c +4.656854 6.000000 6.000000 4.656854 6.000000 3.000000 c +h +f +n +Q +q +0.998537 -0.054068 0.054068 0.998537 209.982742 114.693565 cm +0.541176 0.705882 0.972549 scn +6.000000 3.315674 m +6.000000 1.658820 4.656854 0.315674 3.000000 0.315674 c +1.343146 0.315674 0.000000 1.658820 0.000000 3.315674 c +0.000000 4.972528 1.343146 6.315674 3.000000 6.315674 c +4.656854 6.315674 6.000000 4.972528 6.000000 3.315674 c +h +f +n +Q +q +0.998537 -0.054068 0.054068 0.998537 216.632156 108.702354 cm +0.541176 0.705882 0.972549 scn +6.000000 3.315674 m +6.000000 1.658820 4.656854 0.315674 3.000000 0.315674 c +1.343146 0.315674 0.000000 1.658820 0.000000 3.315674 c +0.000000 4.972528 1.343146 6.315674 3.000000 6.315674 c +4.656854 6.315674 6.000000 4.972528 6.000000 3.315674 c +h +f +n +Q +q +0.999896 0.014439 -0.014439 0.999896 84.711609 61.445076 cm +0.541176 0.705882 0.972549 scn +0.000000 10.114014 m +0.000000 12.323153 1.790861 14.114014 4.000000 14.114014 c +4.000000 14.114014 l +6.209139 14.114014 8.000000 12.323153 8.000000 10.114014 c +8.000000 4.114014 l +8.000000 1.904875 6.209139 0.114014 4.000000 0.114014 c +4.000000 0.114014 l +1.790861 0.114014 0.000000 1.904875 0.000000 4.114014 c +0.000000 10.114014 l +h +f +n +Q +q +0.996851 0.079301 -0.079301 0.996851 86.616531 50.022411 cm +0.992157 0.839216 0.388235 scn +6.000000 3.456909 m +6.000000 1.800055 4.656854 0.456909 3.000000 0.456909 c +1.343146 0.456909 0.000000 1.800055 0.000000 3.456909 c +0.000000 5.113763 1.343146 6.456909 3.000000 6.456909 c +4.656854 6.456909 6.000000 5.113763 6.000000 3.456909 c +h +f +n +Q +q +0.996851 0.079301 -0.079301 0.996851 86.616531 79.606392 cm +0.203922 0.658824 0.325490 scn +6.000000 3.456909 m +6.000000 1.800055 4.656854 0.456909 3.000000 0.456909 c +1.343146 0.456909 0.000000 1.800055 0.000000 3.456909 c +0.000000 5.113763 1.343146 6.456909 3.000000 6.456909 c +4.656854 6.456909 6.000000 5.113763 6.000000 3.456909 c +h +f +n +Q +q +0.999083 0.042821 -0.042821 0.999083 251.166351 65.505699 cm +0.992157 0.839216 0.388235 scn +0.000000 10.329712 m +0.000000 12.538851 1.790861 14.329712 4.000000 14.329712 c +4.000000 14.329712 l +6.209139 14.329712 8.000000 12.538851 8.000000 10.329712 c +8.000000 4.329712 l +8.000000 2.120573 6.209139 0.329712 4.000000 0.329712 c +4.000000 0.329712 l +1.790861 0.329712 0.000000 2.120573 0.000000 4.329712 c +0.000000 10.329712 l +h +f +n +Q +q +0.974310 -0.225212 0.225212 0.974310 248.831268 83.833580 cm +0.949020 0.545098 0.509804 scn +6.000000 4.197144 m +6.000000 2.540289 4.656854 1.197144 3.000000 1.197144 c +1.343146 1.197144 0.000000 2.540289 0.000000 4.197144 c +0.000000 5.853998 1.343146 7.197144 3.000000 7.197144 c +4.656854 7.197144 6.000000 5.853998 6.000000 4.197144 c +h +f +n +Q +q +0.974310 -0.225212 0.225212 0.974310 250.283417 55.339314 cm +0.235294 0.250980 0.262745 scn +6.000000 4.197144 m +6.000000 2.540289 4.656854 1.197144 3.000000 1.197144 c +1.343146 1.197144 0.000000 2.540289 0.000000 4.197144 c +0.000000 5.853998 1.343146 7.197144 3.000000 7.197144 c +4.656854 7.197144 6.000000 5.853998 6.000000 4.197144 c +h +f +n +Q + +endstream +endobj + +3 0 obj + 15857 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 343.000000 137.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000015947 00000 n +0000015971 00000 n +0000016146 00000 n +0000016220 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +16279 +%%EOF \ No newline at end of file
diff --git a/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_light.pdf b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_light.pdf new file mode 100644 index 0000000..dedbce9 --- /dev/null +++ b/ios/chrome/browser/ui/passwords/account_storage_notice/resources/passwords_account_storage_notice_illustration.imageset/illustration_light.pdf
@@ -0,0 +1,656 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 107.554688 2.000000 cm +0.909804 0.917647 0.929412 scn +126.525101 77.330658 m +126.618629 76.786346 127.135696 76.420914 127.680000 76.514442 c +128.224304 76.607971 128.589737 77.125038 128.496216 77.669342 c +126.525101 77.330658 l +h +126.067139 45.682381 m +126.242554 46.206062 125.960228 46.772804 125.436539 46.948219 c +124.912857 47.123634 124.346115 46.841309 124.170700 46.317619 c +126.067139 45.682381 l +h +-0.991446 75.130524 m +-1.063529 74.582962 -0.678079 74.080643 -0.130519 74.008553 c +0.417041 73.936470 0.919362 74.321922 0.991446 74.869476 c +-0.991446 75.130524 l +h +8.797826 34.996849 m +8.523426 35.476143 7.912436 35.642242 7.433141 35.367836 c +6.953847 35.093437 6.787748 34.482452 7.062148 34.003151 c +8.797826 34.996849 l +h +98.630516 119.698715 m +99.092865 119.396637 99.712555 119.526566 100.014633 119.988914 c +100.316711 120.451263 100.186783 121.070953 99.724434 121.373032 c +98.630516 119.698715 l +h +117.585968 104.097939 m +117.268585 104.549927 116.644897 104.659042 116.192909 104.341660 c +115.740929 104.024277 115.631813 103.400589 115.949188 102.948608 c +117.585968 104.097939 l +h +96.921394 12.223000 m +96.449677 11.935776 96.300110 11.320534 96.587334 10.848808 c +96.874557 10.377090 97.489799 10.227524 97.961525 10.514748 c +96.921394 12.223000 l +h +81.604309 3.408424 m +82.136230 3.557007 82.446991 4.108665 82.298416 4.640587 c +82.149834 5.172508 81.598175 5.483269 81.066254 5.334694 c +81.604309 3.408424 l +h +20.445116 115.470490 m +20.032339 115.103569 19.995171 114.471497 20.362095 114.058716 c +20.729021 113.645943 21.361094 113.608772 21.773870 113.975693 c +20.445116 115.470490 l +h +11.295550 102.012276 m +11.604806 102.469856 11.484565 103.091499 11.026985 103.400757 c +10.569405 103.710007 9.947762 103.589767 9.638507 103.132187 c +11.295550 102.012276 l +h +63.944908 3.000000 m +40.340767 3.000000 19.743305 15.878403 8.797826 34.996849 c +7.062148 34.003151 l +18.349339 14.287842 39.594734 1.000000 63.944908 1.000000 c +63.944908 3.000000 l +h +63.944908 130.000000 m +76.746124 130.000000 88.659821 126.213097 98.630516 119.698715 c +99.724434 121.373032 l +89.438385 128.093445 77.146339 132.000000 63.944908 132.000000 c +63.944908 130.000000 l +h +115.949188 102.948608 m +121.221542 95.440208 124.908478 86.739120 126.525101 77.330658 c +128.496216 77.669342 l +126.828247 87.376656 123.024094 96.353455 117.585968 104.097939 c +115.949188 102.948608 l +h +124.170700 46.317619 m +119.373344 31.995720 109.608574 19.947990 96.921394 12.223000 c +97.961525 10.514748 l +111.045662 18.481438 121.117622 30.906212 126.067139 45.682381 c +124.170700 46.317619 l +h +81.066254 5.334694 m +75.620590 3.813583 69.878578 3.000000 63.944908 3.000000 c +63.944908 1.000000 l +70.062187 1.000000 75.985161 1.838867 81.604309 3.408424 c +81.066254 5.334694 l +h +21.773870 113.975693 m +32.989281 123.945305 47.758816 130.000000 63.944908 130.000000 c +63.944908 132.000000 l +47.250359 132.000000 32.012478 125.752953 20.445116 115.470490 c +21.773870 113.975693 l +h +0.991446 74.869476 m +2.302594 84.829193 5.921991 94.061462 11.295550 102.012276 c +9.638507 103.132187 l +4.095732 94.931000 0.361261 85.405914 -0.991446 75.130524 c +0.991446 74.869476 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 93.944336 0.121460 cm +0.909804 0.917647 0.929412 scn +127.944687 3.049438 m +127.507614 2.711823 127.426994 2.083817 127.764610 1.646744 c +128.102234 1.209671 128.730240 1.129044 129.167313 1.466675 c +127.944687 3.049438 l +h +25.944679 1.466675 m +26.381752 1.129044 27.009762 1.209671 27.347382 1.646744 c +27.684999 2.083817 27.604378 2.711823 27.167305 3.049438 c +25.944679 1.466675 l +h +129.167313 135.290527 m +128.730240 135.628159 128.102234 135.547531 127.764610 135.110458 c +127.426994 134.673386 127.507614 134.045380 127.944687 133.707764 c +129.167313 135.290527 l +h +27.167305 133.707748 m +27.604378 134.045364 27.684999 134.673386 27.347382 135.110458 c +27.009762 135.547531 26.381752 135.628143 25.944679 135.290527 c +27.167305 133.707748 l +h +154.183548 99.007576 m +154.388702 98.494804 154.970688 98.245430 155.483459 98.450577 c +155.996216 98.655724 156.245605 99.237709 156.040451 99.750481 c +154.183548 99.007576 l +h +158.360245 43.586021 m +158.522064 44.114067 158.225174 44.673317 157.697128 44.835136 c +157.169083 44.996964 156.609833 44.700081 156.448013 44.172035 c +158.360245 43.586021 l +h +-0.928452 99.750481 m +-1.133600 99.237709 -0.884222 98.655724 -0.371452 98.450577 c +0.141318 98.245430 0.723305 98.494804 0.928452 99.007576 c +-0.928452 99.750481 l +h +3.576396 31.822723 m +3.331352 32.317665 2.731471 32.520248 2.236525 32.275208 c +1.741579 32.030167 1.538993 31.430283 1.784037 30.935333 c +3.576396 31.822723 l +h +127.944687 133.707764 m +139.527466 124.760582 148.664581 112.802315 154.183548 99.007576 c +156.040451 99.750481 l +150.386902 113.881638 141.028549 126.128265 129.167313 135.290527 c +127.944687 133.707764 l +h +156.448013 44.172035 m +151.389328 27.664886 141.290588 13.358551 127.944687 3.049438 c +129.167313 1.466675 l +142.833740 12.023376 153.177780 26.675041 158.360245 43.586021 c +156.448013 44.172035 l +h +0.928452 99.007576 m +6.447410 112.802307 15.584533 124.760574 27.167305 133.707748 c +25.944679 135.290527 l +14.083455 126.128265 4.725099 113.881638 -0.928452 99.750481 c +0.928452 99.007576 l +h +27.167305 3.049438 m +17.277472 10.688904 9.170437 20.523735 3.576396 31.822723 c +1.784037 30.935333 l +7.514006 19.361801 15.816860 9.289955 25.944679 1.466675 c +27.167305 3.049438 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 138.000000 52.000000 cm +0.258824 0.521569 0.956863 scn +22.985996 12.750000 m +21.683998 10.511999 19.271999 9.000000 16.499998 9.000000 c +12.365999 9.000000 8.999999 12.365999 8.999999 16.500000 c +8.999999 20.633999 12.365999 24.000000 16.499998 24.000000 c +19.265999 24.000000 21.683998 22.487999 22.985996 20.250000 c +32.567997 20.250000 l +30.863998 27.546000 24.311995 33.000000 16.505995 33.000000 c +7.403996 33.000000 0.000000 25.596001 0.000000 16.500000 c +0.000000 7.403999 7.404000 0.000000 16.499998 0.000000 c +24.305998 0.000000 30.864000 5.453999 32.562000 12.750000 c +22.985996 12.750000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 170.250000 64.000244 cm +0.984314 0.737255 0.015686 scn +16.500000 9.000000 m +0.000000 9.000000 l +0.000000 0.000000 l +16.500000 0.000000 l +16.500000 9.000000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 186.000000 55.000000 cm +0.203922 0.658824 0.325490 scn +18.000000 9.750000 m +18.000000 0.000000 l +12.000000 0.000000 l +12.000000 3.000000 l +12.000000 4.656000 10.656000 6.000000 9.000000 6.000000 c +7.344000 6.000000 6.000000 4.656000 6.000000 3.000000 c +6.000000 0.000000 l +0.000000 0.000000 l +0.000000 9.750000 l +18.000000 9.750000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 186.000000 64.000244 cm +0.094118 0.501961 0.219608 scn +18.000000 9.000000 m +0.000000 9.000000 l +0.000000 0.000000 l +18.000000 0.000000 l +18.000000 9.000000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 160.500000 64.000244 cm +0.917647 0.262745 0.207843 scn +9.869999 9.000000 m +0.000000 9.000000 l +0.000000 8.982000 l +0.936000 7.728001 1.500000 6.180000 1.500000 4.500000 c +1.500000 2.820000 0.936000 1.271999 0.000000 0.017999 c +0.000000 0.000000 l +9.869999 0.000000 l +10.277999 1.434000 10.500000 2.940000 10.500000 4.500000 c +10.500000 6.060000 10.277999 7.566000 9.869999 9.000000 c +h +f +n +Q +q +q +-0.969037 0.246915 0.246915 0.969037 288.550903 28.164371 cm +0.972549 0.976471 0.980392 scn +0.000000 52.580570 m +0.000000 54.789707 1.790861 56.580566 4.000000 56.580566 c +56.777737 56.580566 l +58.986874 56.580566 60.777737 54.789703 60.777737 52.580566 c +60.777737 17.678619 l +60.777737 15.469482 58.986877 13.678623 56.777737 13.678623 c +4.000002 13.678623 l +1.790863 13.678623 0.000000 15.469486 0.000000 17.678623 c +0.000000 52.580570 l +h +f +n +Q +301.533813 79.116898 m +302.079285 81.257629 300.786072 83.435234 298.645325 83.980698 c +247.501740 97.012314 l +245.361008 97.557785 243.183411 96.264557 242.637939 94.123825 c +234.020126 60.302536 l +233.474655 58.161804 234.767883 55.984207 236.908615 55.438736 c +288.052216 42.407127 l +290.192932 41.861656 292.370544 43.154877 292.916016 45.295616 c +301.533813 79.116898 l +h +W* +n +q +-0.969037 0.246915 0.246915 0.969037 288.550903 28.164371 cm +0.603922 0.627451 0.650980 scn +4.000000 54.580566 m +56.777737 54.580566 l +56.777737 58.580566 l +4.000000 58.580566 l +4.000000 54.580566 l +h +58.777737 52.580566 m +58.777737 17.678619 l +62.777737 17.678619 l +62.777737 52.580566 l +58.777737 52.580566 l +h +56.777737 15.678623 m +4.000002 15.678623 l +4.000002 11.678623 l +56.777737 11.678623 l +56.777737 15.678623 l +h +2.000000 17.678623 m +2.000000 52.580570 l +-2.000000 52.580570 l +-2.000000 17.678623 l +2.000000 17.678623 l +h +4.000002 15.678623 m +2.895431 15.678623 2.000000 16.574055 2.000000 17.678623 c +-2.000000 17.678623 l +-2.000000 14.364914 0.686294 11.678623 4.000002 11.678623 c +4.000002 15.678623 l +h +58.777737 17.678619 m +58.777737 16.574051 57.882309 15.678623 56.777737 15.678623 c +56.777737 11.678623 l +60.091442 11.678623 62.777737 14.364910 62.777737 17.678619 c +58.777737 17.678619 l +h +56.777737 54.580566 m +57.882305 54.580566 58.777737 53.685135 58.777737 52.580566 c +62.777737 52.580566 l +62.777737 55.894276 60.091442 58.580566 56.777737 58.580566 c +56.777737 54.580566 l +h +4.000000 58.580566 m +0.686294 58.580566 -2.000000 55.894279 -2.000000 52.580570 c +2.000000 52.580570 l +2.000000 53.685139 2.895428 54.580566 4.000000 54.580566 c +4.000000 58.580566 l +h +f +n +Q +Q +q +-0.969037 0.246915 0.246915 0.969037 293.197144 17.438866 cm +0.603922 0.627451 0.650980 scn +0.000000 21.136353 m +75.078392 21.136353 l +75.078392 21.136353 l +75.078392 19.655468 73.877899 18.454975 72.397011 18.454975 c +2.681383 18.454975 l +1.200499 18.454975 0.000000 19.655468 0.000000 21.136353 c +0.000000 21.136353 l +h +f +n +Q +q +-0.969037 0.246915 0.246915 0.969037 272.839752 86.222839 cm +0.741176 0.756863 0.776471 scn +1.411972 1.010933 m +1.411972 0.621027 1.095891 0.304947 0.705986 0.304947 c +0.316081 0.304947 0.000000 0.621027 0.000000 1.010933 c +0.000000 1.400838 0.316081 1.716919 0.705986 1.716919 c +1.095891 1.716919 1.411972 1.400838 1.411972 1.010933 c +h +f +n +Q +q +q +0.963776 0.266714 -0.266714 0.963776 86.557228 26.555592 cm +0.972549 0.976471 0.980392 scn +0.000000 61.828003 m +0.000000 64.037140 1.790861 65.828003 4.000000 65.828003 c +26.000000 65.828003 l +28.209139 65.828003 30.000000 64.037140 30.000000 61.828003 c +30.000000 9.828003 l +30.000000 7.618862 28.209139 5.828003 26.000000 5.828003 c +4.000000 5.828003 l +1.790861 5.828003 0.000000 7.618866 0.000000 9.828003 c +0.000000 61.828003 l +h +f +n +Q +70.066856 86.143921 m +69.477646 88.273041 70.725990 90.476669 72.855103 91.065880 c +94.058167 96.933578 l +96.187286 97.522789 98.390923 96.274445 98.980125 94.145332 c +112.849243 44.028992 l +113.438446 41.899879 112.190109 39.696243 110.060989 39.107033 c +88.857925 33.239334 l +86.728813 32.650124 84.525177 33.898468 83.935966 36.027580 c +70.066856 86.143921 l +h +W* +n +q +0.963776 0.266714 -0.266714 0.963776 86.557228 26.555592 cm +0.603922 0.627451 0.650980 scn +4.000000 63.828003 m +26.000000 63.828003 l +26.000000 67.828003 l +4.000000 67.828003 l +4.000000 63.828003 l +h +28.000000 61.828003 m +28.000000 9.828003 l +32.000000 9.828003 l +32.000000 61.828003 l +28.000000 61.828003 l +h +26.000000 7.828003 m +4.000000 7.828003 l +4.000000 3.828003 l +26.000000 3.828003 l +26.000000 7.828003 l +h +2.000000 9.828003 m +2.000000 61.828003 l +-2.000000 61.828003 l +-2.000000 9.828003 l +2.000000 9.828003 l +h +4.000000 7.828003 m +2.895431 7.828003 2.000000 8.723434 2.000000 9.828003 c +-2.000000 9.828003 l +-2.000000 6.514294 0.686291 3.828003 4.000000 3.828003 c +4.000000 7.828003 l +h +28.000000 9.828003 m +28.000000 8.723434 27.104570 7.828003 26.000000 7.828003 c +26.000000 3.828003 l +29.313707 3.828003 32.000000 6.514294 32.000000 9.828003 c +28.000000 9.828003 l +h +26.000000 63.828003 m +27.104568 63.828003 28.000000 62.932571 28.000000 61.828003 c +32.000000 61.828003 l +32.000000 65.141708 29.313709 67.828003 26.000000 67.828003 c +26.000000 63.828003 l +h +4.000000 67.828003 m +0.686292 67.828003 -2.000000 65.141708 -2.000000 61.828003 c +2.000000 61.828003 l +2.000000 62.932571 2.895431 63.828003 4.000000 63.828003 c +4.000000 67.828003 l +h +f +n +Q +Q +q +0.963776 0.266714 -0.266714 0.963776 73.444611 85.155014 cm +0.741176 0.756863 0.776471 scn +1.979617 1.446105 m +1.979617 0.899449 1.536464 0.456296 0.989808 0.456296 c +0.443152 0.456296 0.000000 0.899449 0.000000 1.446105 c +0.000000 1.992761 0.443152 2.435913 0.989808 2.435913 c +1.536464 2.435913 1.979617 1.992761 1.979617 1.446105 c +h +f +n +Q +q +-0.963776 -0.266714 -0.266714 0.963776 104.782501 38.713654 cm +0.741176 0.756863 0.776471 scn +0.000000 4.085997 m +0.000000 4.632653 0.443152 5.075806 0.989809 5.075806 c +10.887890 5.075806 l +11.434546 5.075806 11.877700 4.632653 11.877700 4.085997 c +11.877700 4.085997 l +11.877700 3.539341 11.434547 3.096189 10.887891 3.096189 c +0.989810 3.096189 l +0.443154 3.096189 0.000000 3.539341 0.000000 4.085997 c +0.000000 4.085997 l +h +f +n +Q +q +-0.779502 0.626400 0.626400 0.779502 121.170578 103.252815 cm +0.203922 0.658824 0.325490 scn +0.000000 9.247192 m +0.000000 10.351762 0.895431 11.247192 2.000000 11.247192 c +6.000000 11.247192 l +7.104569 11.247192 8.000000 10.351762 8.000000 9.247192 c +8.000000 5.247192 l +8.000000 4.142623 7.104569 3.247192 6.000000 3.247192 c +2.000000 3.247192 l +0.895431 3.247192 0.000000 4.142623 0.000000 5.247192 c +0.000000 9.247192 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 194.500000 6.000000 cm +0.917647 0.262745 0.207843 scn +6.000000 3.000000 m +6.000000 1.343146 4.656854 0.000000 3.000000 0.000000 c +1.343146 0.000000 0.000000 1.343146 0.000000 3.000000 c +0.000000 4.656854 1.343146 6.000000 3.000000 6.000000 c +4.656854 6.000000 6.000000 4.656854 6.000000 3.000000 c +h +f +n +Q +q +0.998537 -0.054068 0.054068 0.998537 209.982742 114.693565 cm +0.258824 0.521569 0.956863 scn +6.000000 3.315674 m +6.000000 1.658820 4.656854 0.315674 3.000000 0.315674 c +1.343146 0.315674 0.000000 1.658820 0.000000 3.315674 c +0.000000 4.972528 1.343146 6.315674 3.000000 6.315674 c +4.656854 6.315674 6.000000 4.972528 6.000000 3.315674 c +h +f +n +Q +q +0.998537 -0.054068 0.054068 0.998537 216.632156 108.702354 cm +0.258824 0.521569 0.956863 scn +6.000000 3.315674 m +6.000000 1.658820 4.656854 0.315674 3.000000 0.315674 c +1.343146 0.315674 0.000000 1.658820 0.000000 3.315674 c +0.000000 4.972528 1.343146 6.315674 3.000000 6.315674 c +4.656854 6.315674 6.000000 4.972528 6.000000 3.315674 c +h +f +n +Q +q +0.999896 0.014439 -0.014439 0.999896 84.711609 61.445076 cm +0.258824 0.521569 0.956863 scn +0.000000 10.114014 m +0.000000 12.323153 1.790861 14.114014 4.000000 14.114014 c +4.000000 14.114014 l +6.209139 14.114014 8.000000 12.323153 8.000000 10.114014 c +8.000000 4.114014 l +8.000000 1.904875 6.209139 0.114014 4.000000 0.114014 c +4.000000 0.114014 l +1.790861 0.114014 0.000000 1.904875 0.000000 4.114014 c +0.000000 10.114014 l +h +f +n +Q +q +0.996851 0.079301 -0.079301 0.996851 86.616531 50.022411 cm +0.984314 0.737255 0.015686 scn +6.000000 3.456909 m +6.000000 1.800055 4.656854 0.456909 3.000000 0.456909 c +1.343146 0.456909 0.000000 1.800055 0.000000 3.456909 c +0.000000 5.113763 1.343146 6.456909 3.000000 6.456909 c +4.656854 6.456909 6.000000 5.113763 6.000000 3.456909 c +h +f +n +Q +q +0.996851 0.079301 -0.079301 0.996851 86.616531 79.606392 cm +0.203922 0.658824 0.325490 scn +6.000000 3.456909 m +6.000000 1.800055 4.656854 0.456909 3.000000 0.456909 c +1.343146 0.456909 0.000000 1.800055 0.000000 3.456909 c +0.000000 5.113763 1.343146 6.456909 3.000000 6.456909 c +4.656854 6.456909 6.000000 5.113763 6.000000 3.456909 c +h +f +n +Q +q +0.999083 0.042821 -0.042821 0.999083 251.166351 65.505699 cm +0.984314 0.737255 0.015686 scn +0.000000 10.329712 m +0.000000 12.538851 1.790861 14.329712 4.000000 14.329712 c +4.000000 14.329712 l +6.209139 14.329712 8.000000 12.538851 8.000000 10.329712 c +8.000000 4.329712 l +8.000000 2.120573 6.209139 0.329712 4.000000 0.329712 c +4.000000 0.329712 l +1.790861 0.329712 0.000000 2.120573 0.000000 4.329712 c +0.000000 10.329712 l +h +f +n +Q +q +0.974310 -0.225212 0.225212 0.974310 248.831268 83.833580 cm +0.917647 0.262745 0.207843 scn +6.000000 4.197144 m +6.000000 2.540289 4.656854 1.197144 3.000000 1.197144 c +1.343146 1.197144 0.000000 2.540289 0.000000 4.197144 c +0.000000 5.853998 1.343146 7.197144 3.000000 7.197144 c +4.656854 7.197144 6.000000 5.853998 6.000000 4.197144 c +h +f +n +Q +q +0.974310 -0.225212 0.225212 0.974310 250.283417 55.339314 cm +0.909804 0.917647 0.929412 scn +6.000000 4.197144 m +6.000000 2.540289 4.656854 1.197144 3.000000 1.197144 c +1.343146 1.197144 0.000000 2.540289 0.000000 4.197144 c +0.000000 5.853998 1.343146 7.197144 3.000000 7.197144 c +4.656854 7.197144 6.000000 5.853998 6.000000 4.197144 c +h +f +n +Q + +endstream +endobj + +3 0 obj + 16750 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 343.000000 137.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000016840 00000 n +0000016864 00000 n +0000017039 00000 n +0000017113 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +17172 +%%EOF \ No newline at end of file
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn index afb71e4..a5d147b 100644 --- a/ios/chrome/browser/ui/popup_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -137,10 +137,7 @@ source_set("metrics_protocols") { configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "popup_menu_carousel_metrics_delegate.h", - "popup_menu_metrics_handler.h", - ] + sources = [ "popup_menu_metrics_handler.h" ] } source_set("unit_tests") {
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift index 8645f77..3a4f7f9 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_list.swift
@@ -103,13 +103,10 @@ private func scrollView(in geometry: GeometryProxy) -> some View { ScrollViewReader { proxy in ScrollView(.horizontal, showsIndicators: false) { - let spacing = destinationSpacing(forScreenWidth: geometry.size.width) - let layoutParameters: OverflowMenuDestinationView.LayoutParameters = - sizeCategory >= .accessibilityMedium - ? .horizontal(itemWidth: geometry.size.width - Constants.largeTextSizeSpace) - : .vertical( - iconSpacing: spacing.iconSpacing, - iconPadding: spacing.iconPadding) + let spacing = OverflowMenuDestinationList.destinationSpacing( + forScreenWidth: geometry.size.width) + let layoutParameters = OverflowMenuDestinationList.layoutParameters( + forScreenWidth: geometry.size.width, forSizeCategory: sizeCategory) let alignment: VerticalAlignment = sizeCategory >= .accessibilityMedium ? .center : .top ZStack { @@ -151,7 +148,7 @@ /// /// Returns `nil` for either end if `width` is above or below the largest or /// smallest breakpoint. - private func findBreakpoints(forScreenWidth width: CGFloat) -> (CGFloat?, CGFloat?) { + private static func findBreakpoints(forScreenWidth width: CGFloat) -> (CGFloat?, CGFloat?) { // Add extra sentinel values to either end of the breakpoint array. let x = zip( Constants.lowerWidthBreakpoints, Constants.upperWidthBreakpoints @@ -170,7 +167,7 @@ } /// Calculates the icon spacing and padding for the given `width`. - private func destinationSpacing(forScreenWidth width: CGFloat) -> ( + private static func destinationSpacing(forScreenWidth width: CGFloat) -> ( iconSpacing: CGFloat, iconPadding: CGFloat ) { let (lowerBreakpoint, upperBreakpoint) = findBreakpoints( @@ -203,9 +200,34 @@ return (iconSpacing: iconSpacing, iconPadding: iconPadding) } + private static func layoutParameters( + forScreenWidth width: CGFloat, forSizeCategory sizeCategory: ContentSizeCategory + ) -> OverflowMenuDestinationView.LayoutParameters { + let spacing = OverflowMenuDestinationList.destinationSpacing(forScreenWidth: width) + + return sizeCategory >= .accessibilityMedium + ? .horizontal(itemWidth: width - Constants.largeTextSizeSpace) + : .vertical( + iconSpacing: spacing.iconSpacing, + iconPadding: spacing.iconPadding) + } + + public static func numDestinationsVisibleWithoutHorizontalScrolling( + forScreenWidth width: CGFloat, forSizeCategory sizeCategory: ContentSizeCategory + ) + -> CGFloat + { + let layoutParameters = OverflowMenuDestinationList.layoutParameters( + forScreenWidth: width, forSizeCategory: sizeCategory) + let destinationWidth = OverflowMenuDestinationButton.destinationWidth( + forLayoutParameters: layoutParameters) + + return (width / destinationWidth).rounded(.up) + } + /// Maps the given `number` from its relative position in `inRange` to its /// relative position in `outRange`. - private func mapNumber<F: FloatingPoint>( + private static func mapNumber<F: FloatingPoint>( _ number: F, from inRange: ClosedRange<F>, to outRange: ClosedRange<F> ) -> F { let scalingFactor =
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift index 6337fd2..ea4c550 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_destination_view.swift
@@ -5,14 +5,6 @@ import SwiftUI import ios_chrome_common_ui_colors_swift -/// PreferenceKey to listen to visibility changes for a given destination. -struct DestinationVisibilityPreferenceKey: PreferenceKey { - static var defaultValue: Int = 0 - static func reduce(value: inout Int, nextValue: () -> Int) { - value += nextValue() - } -} - /// Style based on state for an OverflowMenuDestinationView. @available(iOS 15, *) struct OverflowMenuDestinationButton: ButtonStyle { @@ -57,40 +49,32 @@ /// The layout parameters for this view. var layoutParameters: OverflowMenuDestinationView.LayoutParameters - /// Tracks if the destination icon is visible in the carousel. - @State var isIconVisible = false - - /// Tracks if the destination name is visible in the carousel. - @State var isTextVisible = false - weak var metricsHandler: PopupMenuMetricsHandler? func makeBody(configuration: Configuration) -> some View { + let destinationWidth = OverflowMenuDestinationButton.destinationWidth( + forLayoutParameters: layoutParameters) Group { switch layoutParameters { - case .vertical(let iconSpacing, let iconPadding): + case .vertical: VStack { icon(configuration: configuration) text } - .frame(width: Dimensions.imageWidth + 2 * iconSpacing + 2 * iconPadding) - case .horizontal(let itemWidth): + .frame(width: destinationWidth) + case .horizontal: HStack { icon(configuration: configuration) Spacer().frame(width: Dimensions.horizontalLayoutIconSpacing) text } - .frame(width: itemWidth, alignment: .leading) + .frame(width: destinationWidth, alignment: .leading) // In horizontal layout, the item itself has leading and trailing // padding. .padding([.leading, .trailing], Dimensions.horizontalLayoutViewPadding) } } .contentShape(Rectangle()) - .preference( - key: DestinationVisibilityPreferenceKey.self, - value: (isIconVisible || isTextVisible) ? 1 : 0 - ) } /// Background color for the icon. @@ -186,12 +170,6 @@ // VoiceOver will occasionally read out icons it thinks it can // recognize. .accessibilityHidden(true) - .onAppear { - isIconVisible = true - } - .onDisappear { - isIconVisible = false - } if !destination.symbolName.isEmpty { configuredImage @@ -220,12 +198,17 @@ .padding([.leading, .trailing], textSpacing) .multilineTextAlignment(.center) .lineLimit(maximumLines) - .onAppear { - isTextVisible = true - } - .onDisappear { - isTextVisible = false - } + } + + static public func destinationWidth( + forLayoutParameters layoutParameters: OverflowMenuDestinationView.LayoutParameters + ) -> CGFloat { + switch layoutParameters { + case .vertical(let iconSpacing, let iconPadding): + return Dimensions.imageWidth + 2 * iconSpacing + 2 * iconPadding + case .horizontal(let itemWidth): + return itemWidth + } } }
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h index 25a121c..ca33be5 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h
@@ -10,7 +10,6 @@ #import "ios/chrome/browser/follow/follow_action_state.h" #import "ios/chrome/browser/ui/browser_container/browser_container_consumer.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift.h" -#import "ios/chrome/browser/ui/popup_menu/popup_menu_carousel_metrics_delegate.h" namespace bookmarks { class BookmarkModel; @@ -37,8 +36,7 @@ // Mediator for the overflow menu. This object is in charge of creating and // updating the items of the overflow menu. -@interface OverflowMenuMediator - : NSObject <BrowserContainerConsumer, PopupMenuCarouselMetricsDelegate> +@interface OverflowMenuMediator : NSObject <BrowserContainerConsumer> // The data model for the overflow menu. @property(nonatomic, readonly) OverflowMenuModel* overflowMenuModel; @@ -95,6 +93,10 @@ // The FollowBrowserAgent used to manage web channels subscriptions. @property(nonatomic, assign) FollowBrowserAgent* followBrowserAgent; +// The number of destinations immediately visible to the user when opening the +// new overflow menu (i.e. the number of "above-the-fold" destinations). +@property(nonatomic, assign) int numAboveFoldDestinations; + // Disconnect the mediator. - (void)disconnect;
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm index 7264a04e..0500360 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -95,6 +95,11 @@ namespace { +// Key used for storing NSUserDefault entry to keep track of the last timestamp +// we've shown the default browser blue dot promo. +NSString* const kMostRecentTimestampBlueDotPromoShownInOverflowMenu = + @"MostRecentTimestampBlueDotPromoShownInOverflowMenu"; + typedef void (^Handler)(void); OverflowMenuAction* CreateOverflowMenuActionWithString( @@ -205,10 +210,6 @@ // Whether the web content is currently being blocked. @property(nonatomic, assign) BOOL contentBlocked; -// The number of destinations immediately visible to the user when opening the -// new overflow menu (i.e. the number of "above-the-fold" destinations). -@property(nonatomic, assign) int numAboveFoldDestinations; - @property(nonatomic, strong) OverflowMenuDestination* bookmarksDestination; @property(nonatomic, strong) OverflowMenuDestination* downloadsDestination; @property(nonatomic, strong) OverflowMenuDestination* historyDestination; @@ -1061,6 +1062,49 @@ return newDestinations; } +// Decides whether the default browser blue dot promo should be active, and if +// it is, move the settings destination to the front and add the blue dot badge. +- (NSArray<OverflowMenuDestination*>*)maybeActivateDefaultBrowserBlueDotPromo: + (NSArray<OverflowMenuDestination*>*)destinations { + if (!self.engagementTracker) { + return destinations; + } + + if (ShouldTriggerDefaultBrowserBlueDotBadgeFeature( + feature_engagement::kIPHiOSDefaultBrowserOverflowMenuBadgeFeature, + self.engagementTracker)) { + // Add the blue dot promo badge to the settings destination. + self.settingsDestination.badge = BadgeTypeBlueDot; + + // Move the settings destination to the front of the destinations, otherwise + // respecting the original order. + NSMutableArray<OverflowMenuDestination*>* newDestinations = + [[NSMutableArray alloc] init]; + + [newDestinations addObject:self.settingsDestination]; + for (OverflowMenuDestination* destination in destinations) { + if (destination != self.settingsDestination) { + [newDestinations addObject:destination]; + } + } + + // If we've only started showing the blue dot recently (<6 hours), don't + // notify the FET again that the promo is being shown, since we're not in a + // new user session. We record the badge being shown per user session, + // instead of per time it is shown since the badge needs to be shown accross + // 3 user sessions. + if (!HasRecentTimestampForKey( + kMostRecentTimestampBlueDotPromoShownInOverflowMenu)) { + self.engagementTracker->NotifyEvent( + feature_engagement::events::kBlueDotPromoOverflowMenuShownNewSession); + } + + return newDestinations; + } + + return destinations; +} + // Adds SpotlightDebugger to the OverflowMenuDestination to be displayed in the // destinations carousel. - (NSArray<OverflowMenuDestination*>*)insertSpotlightDebuggerToDestinations: @@ -1100,7 +1144,7 @@ generateDestinationsList:baseDestinations]; } - // What's New defy the smart sorting rules of the overflow menu to appear + // What's New defies the smart sorting rules of the overflow menu to appear // either at the front of the carousel or the back. Thus, What's New is // inserted after smart sorting returns the sorted destinations. if (IsWhatsNewEnabled()) { @@ -1112,6 +1156,9 @@ [self insertSpotlightDebuggerToDestinations:baseDestinations]; } + baseDestinations = + [self maybeActivateDefaultBrowserBlueDotPromo:baseDestinations]; + self.overflowMenuModel.destinations = [baseDestinations filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL( id object, @@ -1844,6 +1891,11 @@ // Dismisses the menu and opens settings. - (void)openSettings { + if (self.settingsDestination.badge == BadgeTypeBlueDot && + self.engagementTracker) { + self.engagementTracker->NotifyEvent( + feature_engagement::events::kBlueDotPromoOverflowMenuDismissed); + } [self.popupMenuCommandsHandler dismissPopupMenuAnimated:YES]; profile_metrics::BrowserProfileType type = self.isIncognito ? profile_metrics::BrowserProfileType::kIncognito @@ -1865,17 +1917,4 @@ [self.dispatcher showSpotlightDebugger]; } -#pragma mark - PopupMenuCarouselMetricsDelegate - -- (void)visibleDestinationCountDidChange:(NSInteger)numVisibleDestinations { - // Exit early if numAboveFoldDestinations is already set to a non-zero value; - // this class only cares about the first time this method is called with a - // non-zero value; for that reason, exit early on subsequent calls to this - // method if numAboveFoldDestinations is already set. - if (self.numAboveFoldDestinations) - return; - - self.numAboveFoldDestinations = numVisibleDestinations; -} - @end
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift_bridge.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift_bridge.h index 6b8def7..7b505bd 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift_bridge.h +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift_bridge.h
@@ -10,7 +10,6 @@ #include "ios/chrome/grit/ios_strings.h" -#import "ios/chrome/browser/ui/popup_menu/popup_menu_carousel_metrics_delegate.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_metrics_handler.h" #include "ui/base/l10n/l10n_util_mac_bridge.h"
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_ui_configuration.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_ui_configuration.swift index 8c541c8..ad5b02d6 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_ui_configuration.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_ui_configuration.swift
@@ -14,6 +14,16 @@ /// The destination list's frame in screen coordinates. public var destinationListScreenFrame: CGRect = .zero + @available(iOS 15, *) + static public func numDestinationsVisibleWithoutHorizontalScrolling( + forScreenWidth width: CGFloat, forContentSizeCategory sizeCategory: UIContentSizeCategory + ) -> CGFloat { + let contentSizeCategory = ContentSizeCategory(sizeCategory) ?? .medium + + return OverflowMenuDestinationList.numDestinationsVisibleWithoutHorizontalScrolling( + forScreenWidth: width, forSizeCategory: contentSizeCategory) + } + public init( presentingViewControllerHorizontalSizeClass: UIUserInterfaceSizeClass, presentingViewControllerVerticalSizeClass: UIUserInterfaceSizeClass
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view.swift index ea478a1..54cc300 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view.swift
@@ -16,8 +16,6 @@ weak var metricsHandler: PopupMenuMetricsHandler? - weak var carouselMetricsDelegate: PopupMenuCarouselMetricsDelegate? - var body: some View { VStack( alignment: .leading, @@ -28,12 +26,7 @@ OverflowMenuDestinationList( destinations: model.destinations, metricsHandler: metricsHandler, uiConfiguration: uiConfiguration - ).onPreferenceChange( - DestinationVisibilityPreferenceKey.self - ) { - (value: DestinationVisibilityPreferenceKey.Value) in - carouselMetricsDelegate?.visibleDestinationCountDidChange(value) - }.frame(height: Dimensions.destinationListHeight) + ).frame(height: Dimensions.destinationListHeight) Divider() OverflowMenuActionList(actionGroups: model.actionGroups, metricsHandler: metricsHandler) // Add a spacer on iPad to make sure there's space below the list.
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view_provider.swift b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view_provider.swift index ba995474..ee748cd 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view_provider.swift +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_view_provider.swift
@@ -12,13 +12,11 @@ public static func makeViewController( withModel model: OverflowMenuModel, uiConfiguration: OverflowMenuUIConfiguration, - metricsHandler: PopupMenuMetricsHandler, - carouselMetricsDelegate: PopupMenuCarouselMetricsDelegate + metricsHandler: PopupMenuMetricsHandler ) -> UIViewController { return OverflowMenuHostingController( rootView: OverflowMenuView( - model: model, uiConfiguration: uiConfiguration, metricsHandler: metricsHandler, - carouselMetricsDelegate: carouselMetricsDelegate), + model: model, uiConfiguration: uiConfiguration, metricsHandler: metricsHandler), uiConfiguration: uiConfiguration) } }
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_carousel_metrics_delegate.h b/ios/chrome/browser/ui/popup_menu/popup_menu_carousel_metrics_delegate.h deleted file mode 100644 index ad30508..0000000 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_carousel_metrics_delegate.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_CAROUSEL_METRICS_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_CAROUSEL_METRICS_DELEGATE_H_ - -#import <Foundation/Foundation.h> - -// Protocol for informing a client of overflow menu, carousel-related metrics, -// like the number of currently visible destinations. -@protocol PopupMenuCarouselMetricsDelegate - -// Called when the popup menu detects the number of visible destinations in the -// carousel changes. -- (void)visibleDestinationCountDidChange:(NSInteger)numVisibleDestinations; - -@end - -#endif // IOS_CHROME_BROWSER_UI_POPUP_MENU_POPUP_MENU_CAROUSEL_METRICS_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm index 08a9e4c..8400c19 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
@@ -390,6 +390,19 @@ if (IsNewOverflowMenuEnabled()) { if (@available(iOS 15, *)) { self.overflowMenuMediator = [[OverflowMenuMediator alloc] init]; + + CGFloat screenWidth = self.baseViewController.view.frame.size.width; + UIContentSizeCategory contentSizeCategory = + self.baseViewController.traitCollection + .preferredContentSizeCategory; + + self.overflowMenuMediator + .numAboveFoldDestinations = [OverflowMenuUIConfiguration + numDestinationsVisibleWithoutHorizontalScrollingForScreenWidth: + screenWidth + forContentSizeCategory: + contentSizeCategory]; + self.overflowMenuMediator.dispatcher = static_cast< id<ActivityServiceCommands, ApplicationCommands, BrowserCommands, BrowserCoordinatorCommands, FindInPageCommands, @@ -444,8 +457,7 @@ makeViewControllerWithModel:self.overflowMenuMediator .overflowMenuModel uiConfiguration:uiConfiguration - metricsHandler:self - carouselMetricsDelegate:self.overflowMenuMediator]; + metricsHandler:self]; LayoutGuideCenter* layoutGuideCenter = LayoutGuideCenterForBrowser(self.browser);
diff --git a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm index 1bbc7eb..9a9a809 100644 --- a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm +++ b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm
@@ -205,13 +205,14 @@ int64_t amountMicro = forCurrentPrice ? productInfo->amount_micros : productInfo->previous_amount_micros.value(); - float price = amountMicro / commerce::kToMicroCurrency; - std::unique_ptr<payments::CurrencyFormatter> formatter = - std::make_unique<payments::CurrencyFormatter>(productInfo->currency_code, - productInfo->country_code); - formatter->SetMaxFractionalDigits(2); + float price = static_cast<float>(amountMicro) / + static_cast<float>(commerce::kToMicroCurrency); + payments::CurrencyFormatter formatter(productInfo->currency_code, + productInfo->country_code); + + formatter.SetMaxFractionalDigits(2); return base::SysUTF16ToNSString( - formatter->Format(base::NumberToString(price))); + formatter.Format(base::NumberToString(price))); } // This function handles the response from the user attempting to subscribe to
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index e2d702c..0cebf288 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -174,6 +174,7 @@ "//ios/chrome/browser/ui/content_suggestions:feature_flags", "//ios/chrome/browser/ui/content_suggestions/cells", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/ui/default_promo:utils", "//ios/chrome/browser/ui/elements:elements_internal", "//ios/chrome/browser/ui/first_run:field_trial", "//ios/chrome/browser/ui/icons",
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index f255a12..a00c846 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -13,6 +13,9 @@ #import "base/strings/sys_string_conversions.h" #import "build/branding_buildflags.h" #import "components/autofill/core/common/autofill_prefs.h" +#import "components/feature_engagement/public/event_constants.h" +#import "components/feature_engagement/public/feature_constants.h" +#import "components/feature_engagement/public/tracker.h" #import "components/keyed_service/core/service_access_type.h" #import "components/password_manager/core/browser/manage_passwords_referrer.h" #import "components/password_manager/core/common/password_manager_pref_names.h" @@ -32,6 +35,7 @@ #import "ios/chrome/browser/application_context/application_context.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/commerce/push_notification/push_notification_feature.h" +#import "ios/chrome/browser/feature_engagement/tracker_factory.h" #import "ios/chrome/browser/flags/system_flags.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/net/crurl.h" @@ -63,6 +67,7 @@ #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/snackbar_commands.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" +#import "ios/chrome/browser/ui/default_promo/default_browser_utils.h" #import "ios/chrome/browser/ui/icons/buildflags.h" #import "ios/chrome/browser/ui/icons/symbols.h" #import "ios/chrome/browser/ui/main/scene_state.h" @@ -150,6 +155,11 @@ // The size of trailing symbol icons for unsafe state. NSInteger kTrailingSymbolImagePointSize = 18; +// Key used for storing NSUserDefault entry to keep track of the last timestamp +// we've shown the default browser blue dot promo. +NSString* const kMostRecentTimestampBlueDotPromoShownInSettingsMenu = + @"MostRecentTimestampBlueDotPromoShownInSettingsMenu"; + #if BUILDFLAG(CHROMIUM_BRANDING) && !defined(NDEBUG) NSString* kDevViewSourceKey = @"DevViewSource"; #endif // BUILDFLAG(CHROMIUM_BRANDING) && !defined(NDEBUG) @@ -310,6 +320,10 @@ id<ApplicationCommands, BrowserCommands, BrowsingDataCommands> dispatcher; +// YES if the default browser settings row is currently showing the notification +// dot. +@property(nonatomic, assign) BOOL showingDefaultBrowserNotificationDot; + // YES if the sign-in is in progress. @property(nonatomic, assign) BOOL isSigninInProgress; @@ -806,6 +820,8 @@ [UIImage imageNamed:kDefaultBrowserWorldImageName]; } + [self maybeActivateDefaultBrowserBlueDotPromo:defaultBrowser]; + return defaultBrowser; } @@ -1539,11 +1555,24 @@ } break; } - case SettingsItemTypeDefaultBrowser: + case SettingsItemTypeDefaultBrowser: { base::RecordAction( base::UserMetricsAction("Settings.ShowDefaultBrowser")); + + if (self.showingDefaultBrowserNotificationDot) { + feature_engagement::Tracker* tracker = + feature_engagement::TrackerFactory::GetForBrowserState( + _browserState); + if (tracker) { + tracker->NotifyEvent( + feature_engagement::events::kBlueDotPromoSettingsDismissed); + } + [self reloadData]; + } + controller = [[DefaultBrowserSettingsTableViewController alloc] init]; break; + } case SettingsItemTypeSearchEngine: base::RecordAction(base::UserMetricsAction("EditSearchEngines")); controller = [[SearchEngineTableViewController alloc] @@ -2001,6 +2030,42 @@ : l10n_util::GetNSString(IDS_IOS_DISCOVER_FEED_TITLE); } +// Decides whether the default browser blue dot promo should be active, and adds +// the blue dot badge to the right settings row if it is. +- (void)maybeActivateDefaultBrowserBlueDotPromo: + (TableViewDetailIconItem*)defaultBrowserCellItem { + self.showingDefaultBrowserNotificationDot = NO; + + if (!_browserState) { + return; + } + + feature_engagement::Tracker* tracker = + feature_engagement::TrackerFactory::GetForBrowserState(_browserState); + if (!tracker) { + return; + } + + if (ShouldTriggerDefaultBrowserBlueDotBadgeFeature( + feature_engagement::kIPHiOSDefaultBrowserSettingsBadgeFeature, + tracker)) { + // Add the blue dot promo badge to the default browser row. + defaultBrowserCellItem.showNotificationDot = YES; + self.showingDefaultBrowserNotificationDot = YES; + + // If we've only started showing the blue dot recently (<6 hours), don't + // notify the FET again that the promo is being shown, since we're not in a + // new user session. We record the badge being shown per user session, + // instead of per time it is shown since the badge needs to be shown accross + // 3 user sessions. + if (!HasRecentTimestampForKey( + kMostRecentTimestampBlueDotPromoShownInSettingsMenu)) { + tracker->NotifyEvent( + feature_engagement::events::kBlueDotPromoSettingsShownNewSession); + } + } +} + #pragma mark - SigninPresenter - (void)showSignin:(ShowSigninCommand*)command {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn index f170d3817..c00b5e76 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
@@ -274,6 +274,7 @@ "//components/bookmarks/common", "//ios/chrome/app/strings", "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/bookmarks:eg_test_support+eg2", "//ios/chrome/browser/ui/fullscreen:feature_flags", "//ios/chrome/browser/ui/history:constants", "//ios/chrome/browser/ui/popup_menu:constants",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm index b7719fd..564bdf08 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -34,6 +34,7 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller+private.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/horizontal_layout.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/plus_sign_cell.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/features.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/suggested_actions/suggested_actions_delegate.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/suggested_actions/suggested_actions_grid_cell.h" #import "ios/chrome/browser/ui/tab_switcher/tab_grid/suggested_actions/suggested_actions_view_controller.h" @@ -951,6 +952,22 @@ } } +- (void)collectionView:(UICollectionView*)collectionView + dropSessionDidEnter:(id<UIDropSession>)session { + if (IsPinnedTabsEnabled()) { + // Notify the delegate that a drag cames from another app. + [self.delegate gridViewControllerDragSessionWillBegin:self]; + } +} + +- (void)collectionView:(UICollectionView*)collectionView + dropSessionDidEnd:(id<UIDropSession>)session { + if (IsPinnedTabsEnabled()) { + // Notify the delegate that a drag ends from another app. + [self.delegate gridViewControllerDropAnimationDidEnd:self]; + } +} + #pragma mark - UIScrollViewDelegate - (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView*)scrollView {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn new file mode 100644 index 0000000..7697ba17 --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/BUILD.gn
@@ -0,0 +1,12 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("features") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "features.h", + "features.mm", + ] + public_deps = [ "//base" ] +}
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/OWNERS b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/OWNERS new file mode 100644 index 0000000..f17c9220c --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/OWNERS
@@ -0,0 +1,2 @@ +alionadangla@google.com +lpromero@google.com
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.h new file mode 100644 index 0000000..67a8da03 --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.h
@@ -0,0 +1,30 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_INACTIVE_TABS_FEATURES_H_ +#define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_INACTIVE_TABS_FEATURES_H_ + +#import "base/feature_list.h" + +namespace base { +class TimeDelta; +} // namespace base + +// Feature flag that sets the tab inactivity threshold. +BASE_DECLARE_FEATURE(kTabInactivityThreshold); + +// Feature parameters for Inactive Tabs. If no parameter is set, the default +// (two weeks) threshold will be used. +extern const char kTabInactivityThresholdParameterName[]; +extern const char kTabInactivityThresholdOneWeekParam[]; +extern const char kTabInactivityThresholdTwoWeeksParam[]; +extern const char kTabInactivityThresholdThreeWeeksParam[]; + +// Convenience method for determining if Inactive Tabs is enabled. +bool IsInactiveTabsEnabled(); + +// Convenience method for determining the tab inactivity threshold. +base::TimeDelta TabInactivityThreshold(); + +#endif // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_INACTIVE_TABS_FEATURES_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.mm new file mode 100644 index 0000000..42664a7e --- /dev/null +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.mm
@@ -0,0 +1,42 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/features.h" + +#import "base/metrics/field_trial_params.h" +#import "base/time/time.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +BASE_FEATURE(kTabInactivityThreshold, + "TabInactivityThreshold", + base::FEATURE_DISABLED_BY_DEFAULT); + +const char kTabInactivityThresholdParameterName[] = "default"; +const char kTabInactivityThresholdOneWeekParam[] = + "tab-inactivity-threshold-one-week"; +const char kTabInactivityThresholdTwoWeeksParam[] = + "tab-inactivity-threshold-two-weeks"; +const char kTabInactivityThresholdThreeWeeksParam[] = + "tab-inactivity-threshold-three-weeks"; + +bool IsInactiveTabsEnabled() { + return base::FeatureList::IsEnabled(kTabInactivityThreshold); +} + +base::TimeDelta TabInactivityThreshold() { + DCHECK(IsInactiveTabsEnabled()); + std::string featureParam = base::GetFieldTrialParamValueByFeature( + kTabInactivityThreshold, kTabInactivityThresholdParameterName); + if (featureParam == kTabInactivityThresholdOneWeekParam) { + return base::Days(8); + } else if (featureParam == kTabInactivityThresholdTwoWeeksParam) { + return base::Days(15); + } else if (featureParam == kTabInactivityThresholdThreeWeeksParam) { + return base::Days(22); + } + return base::Days(15); +}
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm index e5a44b1d..f6129f99 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
@@ -447,7 +447,8 @@ // Move tab across Browsers. base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin, DragItemOrigin::kOtherBrwoser); - MoveTabToBrowser(tabInfo.tabID, self.browser, destinationIndex); + MoveTabToBrowser(tabInfo.tabID, self.browser, destinationIndex, + WebStateList::INSERT_PINNED); return; } base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm index d7b5019c..52173c4 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm
@@ -10,6 +10,7 @@ #import "base/test/ios/wait_util.h" #import "base/time/time.h" #import "components/bookmarks/common/bookmark_pref_names.h" +#import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" #import "ios/chrome/browser/ui/history/history_ui_constants.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_app_interface.h" @@ -551,6 +552,7 @@ [ChromeEarlGrey loadURL:_URL1]; [ChromeEarlGrey waitForWebStateContainingText:kResponse1]; + [BookmarkEarlGrey waitForBookmarkModelLoaded:YES]; [ChromeEarlGreyUI openTabGrid]; [self longPressTabWithTitle:[NSString stringWithUTF8String:kTitle1]]; @@ -569,6 +571,10 @@ chrome_test_util::NavigationBarTitleWithAccessibilityLabelId( IDS_IOS_BOOKMARK_EDIT_SCREEN_TITLE)] assertWithMatcher:grey_notNil()]; + + [BookmarkEarlGrey + verifyExistenceOfBookmarkWithURL:base::SysUTF8ToNSString(_URL1.spec()) + name:base::SysUTF8ToNSString(kTitle1)]; } // Tests that Add to Bookmarks action is greyed out when editBookmarksEnabled @@ -1260,9 +1266,10 @@ [ChromeEarlGrey waitForWebStateContainingText:kResponse2]; [ChromeEarlGrey openNewTab]; - [ChromeEarlGrey loadURL:_URL3]; - [ChromeEarlGrey waitForWebStateContainingText:kResponse3]; + [ChromeEarlGrey loadURL:_URL4]; + [ChromeEarlGrey waitForWebStateContainingText:kResponse4]; + [BookmarkEarlGrey waitForBookmarkModelLoaded:YES]; [ChromeEarlGreyUI openTabGrid]; [[EarlGrey selectElementWithMatcher:VisibleTabGridEditButton()] @@ -1302,6 +1309,15 @@ grey_descendant(grey_text( @"Mobile Bookmarks")), nil)]; + + [BookmarkEarlGrey + verifyExistenceOfBookmarkWithURL:base::SysUTF8ToNSString(_URL1.spec()) + name:base::SysUTF8ToNSString(kTitle1)]; + [BookmarkEarlGrey + verifyExistenceOfBookmarkWithURL:base::SysUTF8ToNSString(_URL4.spec()) + name:base::SysUTF8ToNSString(kTitle4)]; + [BookmarkEarlGrey + verifyAbsenceOfBookmarkWithURL:base::SysUTF8ToNSString(_URL2.spec())]; } // Tests adding items to the readinglist from the tab grid edit mode.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm index 314c132..b3e1580d 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -898,8 +898,11 @@ if (!fromSameCollection) { // Try to unpin the tab. If the returned index is invalid that means the // tab lives in another Browser. - int tabIndex = SetWebStatePinnedState(self.webStateList, tabInfo.tabID, - /*pin_state=*/NO); + int tabIndex = WebStateList::kInvalidIndex; + if (IsPinnedTabsEnabled()) { + tabIndex = SetWebStatePinnedState(self.webStateList, tabInfo.tabID, + /*pin_state=*/NO); + } if (tabIndex == WebStateList::kInvalidIndex) { // Move tab across Browsers. base::UmaHistogramEnumeration(kUmaGridViewDragOrigin,
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index 72bedb44..c2b3993 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -89,6 +89,7 @@ const CGFloat kNewTabOverlap = 13.0; const CGFloat kMaxTabWidthStacked = 265.0; const CGFloat kMaxTabWidthUnstacked = 225.0; +const CGFloat kPinnedTabWidth = 78.0; const CGFloat kMinTabWidthStacked = 200.0; const CGFloat kMinTabWidthUnstacked = 160.0; @@ -203,7 +204,7 @@ // and cleared in layoutSubviews. BOOL _animateLayout; - // The current tab width. Recomputed whenever a tab is added or removed. + // The current tab width. Recomputed whenever a tab is added or removed. CGFloat _currentTabWidth; // View used to dim unselected tabs when in reordering mode. Nil when not @@ -237,6 +238,9 @@ // used as the new WebStateList index of the dragged tab when it is dropped. int _placeholderGapWebStateListIndex; + // The number of pinned tabs. + NSUInteger _pinnedTabCount; + // YES if this tab strip is representing an incognito browser. BOOL _isIncognito; @@ -447,6 +451,8 @@ _webStateList, _webStateObserver.get()); _style = style; + _pinnedTabCount = _webStateList->GetIndexOfFirstNonPinnedWebState(); + // `self.view` setup. _useTabStacking = [self shouldUseTabStacking]; CGRect tabStripFrame = SceneStateBrowserAgent::FromBrowser(browser) @@ -1219,6 +1225,15 @@ [self updateTabView:view withWebState:newWebState]; } +- (void)webStateList:(WebStateList*)webStateList + didChangePinnedStateForWebState:(web::WebState*)webState + atIndex:(int)index { + DCHECK_EQ(_webStateList, webStateList); + _pinnedTabCount = webStateList->GetIndexOfFirstNonPinnedWebState(); + + [self layoutTabStripSubviews]; +} + #pragma mark - #pragma mark WebStateFaviconDriverObserver @@ -1277,7 +1292,8 @@ - (void)updateContentSizeAndRepositionViews { // TODO(rohitrao): The following lines are duplicated in // layoutTabStripSubviews. Find a way to consolidate this logic. - const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; + const NSUInteger tabCount = + [_tabArray count] - [_closingTabs count] - _pinnedTabCount; if (!tabCount) return; const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); @@ -1290,7 +1306,8 @@ // Set the content size to be large enough to contain all the tabs at the // desired width, with the standard overlap, plus the new tab button. CGSize contentSize = CGSizeMake( - _currentTabWidth * tabCount - ([self tabOverlap] * (tabCount - 1)) + + (_currentTabWidth * tabCount) + (kPinnedTabWidth * _pinnedTabCount) - + ([self tabOverlap] * (tabCount + _pinnedTabCount - 1)) + CGRectGetWidth([_buttonNewTab frame]) - kNewTabOverlap, tabHeight); if (CGSizeEqualToSize([_tabStripView contentSize], contentSize)) @@ -1309,11 +1326,23 @@ } - (CGRect)scrollViewFrameForTab:(TabView*)view { - int index = [self webStateListIndexForTabView:view]; + NSUInteger index = [self webStateListIndexForTabView:view]; CGRect frame = [view frame]; - frame.origin.x = - (_currentTabWidth * index) - ([self tabOverlap] * (index - 1)); + + if (_pinnedTabCount > 0) { + if (index < _pinnedTabCount) { + frame.origin.x = (kPinnedTabWidth * index); + } else { + frame.origin.x = (kPinnedTabWidth * _pinnedTabCount) + + (_currentTabWidth * (index - _pinnedTabCount)) - + ([self tabOverlap] * (index - 1)); + } + } else { + frame.origin.x = + (_currentTabWidth * index) - ([self tabOverlap] * (index - 1)); + } + return frame; } @@ -1378,21 +1407,28 @@ } NSUInteger numNonClosingTabsToLeft = 0; + NSUInteger numPinnedTabsToLeft = 0; + int i = 0; for (TabView* tab in _tabArray) { if ([_closingTabs containsObject:tab]) ++i; - if (i == tabIndex) + if (i == static_cast<int>(tabIndex)) { break; - - ++numNonClosingTabsToLeft; + } + if (i < static_cast<int>(_pinnedTabCount)) { + ++numPinnedTabsToLeft; + } else { + ++numNonClosingTabsToLeft; + } ++i; } const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); CGRect scrollRect = - CGRectMake(_currentTabWidth * numNonClosingTabsToLeft - + CGRectMake((_currentTabWidth * numNonClosingTabsToLeft) + + (kPinnedTabWidth * numPinnedTabsToLeft) - ([self tabOverlap] * (numNonClosingTabsToLeft - 1)), 0, _currentTabWidth, tabHeight); [_tabStripView scrollRectToVisible:scrollRect animated:YES]; @@ -1500,6 +1536,10 @@ ++arrayIndex) { TabView* view = (TabView*)[_tabArray objectAtIndex:arrayIndex]; + CGFloat currentTabWith = + arrayIndex < _pinnedTabCount ? kPinnedTabWidth : _currentTabWidth; + view.pinned = arrayIndex < _pinnedTabCount; + // Arrange the tabs in a V going backwards from the selected tab. This // differs from desktop in order to make the tab overflow behavior work (on // desktop, the tabs are arranged going backwards from left to right, with @@ -1583,8 +1623,8 @@ // If this tab is to the right of the currently dragged tab, add a // placeholder gap. if (_isReordering && !hasPlaceholderGap && - CGRectGetMinX(dragFrame) < virtualMinX + (_currentTabWidth / 2.0)) { - virtualMinX += _currentTabWidth - [self tabOverlap]; + CGRectGetMinX(dragFrame) < virtualMinX + (currentTabWith / 2.0)) { + virtualMinX += currentTabWith - [self tabOverlap]; hasPlaceholderGap = YES; // Fix up the z-ordering of the current view. It was placed assuming that @@ -1604,12 +1644,13 @@ // by trying to place the tab at the computed `virtualMinX`, then constrain // that by `realMinX` and `realMaxX`. CGFloat tabX = MAX(virtualMinX, realMinX); - if (tabX + _currentTabWidth > realMaxX) - tabX = realMaxX - _currentTabWidth; + if (tabX + currentTabWith > realMaxX) { + tabX = realMaxX - currentTabWith; + } CGRect frame = CGRectMake(AlignValueToPixel(tabX), 0, - AlignValueToPixel(_currentTabWidth), tabHeight); - virtualMinX += (_currentTabWidth - [self tabOverlap]); + AlignValueToPixel(currentTabWith), tabHeight); + virtualMinX += (currentTabWith - [self tabOverlap]); virtualMaxX = CGRectGetMaxX(frame); // TODO(rohitrao): Temporarily disabled this logic as it does not play well with
diff --git a/ios/chrome/browser/ui/tabs/tab_view.h b/ios/chrome/browser/ui/tabs/tab_view.h index 3f9e95a..cd286489 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.h +++ b/ios/chrome/browser/ui/tabs/tab_view.h
@@ -20,6 +20,7 @@ @property(nonatomic, assign, getter=isCollapsed) BOOL collapsed; @property(nonatomic, strong) UIImage* background; @property(nonatomic, assign) BOOL incognitoStyle; +@property(nonatomic, assign) BOOL pinned; // Designated initializer. Creates a TabView with frame equal to CGRectZero. // If `emptyView` is YES, it creates a TabView without buttons or spinner.
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm index 40067381..cdd455c5 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.mm +++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -72,8 +72,12 @@ // Background image for this tab. UIImageView* _backgroundImageView; + BOOL _incognitoStyle; + // Whether the Tab is pinned or not. + BOOL _pinned; + // Set to YES when the layout constraints have been initialized. BOOL _layoutConstraintsInitialized; @@ -110,6 +114,7 @@ - (id)initWithEmptyView:(BOOL)emptyView selected:(BOOL)selected { if ((self = [super initWithFrame:CGRectZero])) { + _pinned = NO; [self setOpaque:NO]; [self createCommonViews]; if (!emptyView) @@ -139,8 +144,10 @@ } - (void)setCollapsed:(BOOL)collapsed { - if (_collapsed != collapsed) + // If the item is pinned the `_closeButton` should remain hidden. + if (_collapsed != collapsed && !_pinned) { [_closeButton setHidden:collapsed]; + } _collapsed = collapsed; } @@ -180,6 +187,16 @@ return; } +- (void)setPinned:(BOOL)pinned { + if (_pinned == pinned) { + return; + } + _pinned = pinned; + _titleLabel.hidden = pinned; + _closeButton.hidden = pinned; + [self setFrame:self.frame]; +} + - (void)startProgressSpinner { [_activityIndicator startAnimating]; [_activityIndicator setHidden:NO];
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc index 5d42367..fb90b8a 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.cc +++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -83,6 +83,10 @@ "EnableLensInNTP", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kEnableLensContextMenuAltText, + "EnableLensContextMenuAltText", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kEnableLensInOmniboxCopiedImage, "EnableLensInOmniboxCopiedImage", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h index 905f194..d4e92423 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.h +++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -75,6 +75,9 @@ // Feature flag to enable the Lens entrypoint in the new tab page. BASE_DECLARE_FEATURE(kEnableLensInNTP); +// Feature flag to enable the Lens context menu alternate text string. +BASE_DECLARE_FEATURE(kEnableLensContextMenuAltText); + // Feature flag to enable the Lens "Search copied image" omnibox entrypoint. BASE_DECLARE_FEATURE(kEnableLensInOmniboxCopiedImage);
diff --git a/ios/chrome/browser/web/annotations/BUILD.gn b/ios/chrome/browser/web/annotations/BUILD.gn index 9084b1f..fa6920a 100644 --- a/ios/chrome/browser/web/annotations/BUILD.gn +++ b/ios/chrome/browser/web/annotations/BUILD.gn
@@ -11,6 +11,8 @@ "//base", "//components/shared_highlighting/ios", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/mailto_handler", + "//ios/chrome/browser/mailto_handler:mailto_handler_factory", "//ios/chrome/browser/text_selection", "//ios/public/provider/chrome/browser/context_menu:context_menu_api", "//ios/web/annotations",
diff --git a/ios/chrome/browser/web/annotations/annotations_tab_helper.mm b/ios/chrome/browser/web/annotations/annotations_tab_helper.mm index b95f7804..8f8191e 100644 --- a/ios/chrome/browser/web/annotations/annotations_tab_helper.mm +++ b/ios/chrome/browser/web/annotations/annotations_tab_helper.mm
@@ -10,6 +10,8 @@ #import "base/strings/utf_string_conversions.h" #import "base/task/thread_pool.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/mailto_handler/mailto_handler_service.h" +#import "ios/chrome/browser/mailto_handler/mailto_handler_service_factory.h" #import "ios/chrome/browser/text_selection/text_classifier_model_service.h" #import "ios/chrome/browser/text_selection/text_classifier_model_service_factory.h" #import "ios/public/provider/chrome/browser/context_menu/context_menu_api.h" @@ -28,10 +30,6 @@ #error "This file requires ARC support." #endif -static NSString* kDecorationDate = @"DATE"; -static NSString* kDecorationAddress = @"ADDRESS"; -static NSString* kDecorationPhoneNumber = @"PHONE_NUMBER"; - AnnotationsTabHelper::AnnotationsTabHelper(web::WebState* web_state) : web_state_(web_state) { DCHECK(web_state_); @@ -107,13 +105,28 @@ return; } - NSArray<CRWContextMenuItem*>* items = - ios::provider::GetContextMenuElementsToAdd(web_state, match, - base::SysUTF8ToNSString(text), - base_view_controller_); - - if (items.count) { - [web_state_->GetWebViewProxy() showMenuWithItems:items rect:rect]; + if (match.resultType == NSTextCheckingTypePhoneNumber) { + NSString* phone_number = + [match.phoneNumber stringByReplacingOccurrencesOfString:@" " + withString:@""]; + NSString* phone_number_call_format = + [NSString stringWithFormat:@"tel:%@", phone_number]; + [[UIApplication sharedApplication] + openURL:[NSURL URLWithString:phone_number_call_format] + options:@{} + completionHandler:nil]; + } else if (web::annotations::IsNSTextCheckingResultEmail(match)) { + MailtoHandlerServiceFactory::GetForBrowserState( + ChromeBrowserState::FromBrowserState(web_state->GetBrowserState())) + ->HandleMailtoURL(match.URL); + } else { + NSArray<CRWContextMenuItem*>* items = + ios::provider::GetContextMenuElementsToAdd( + web_state, match, base::SysUTF8ToNSString(text), + base_view_controller_); + if (items.count) { + [web_state_->GetWebViewProxy() showMenuWithItems:items rect:rect]; + } } }
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index fdf4692..baf87a1 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -283,6 +283,7 @@ "//ios/chrome/browser/ui/badges:unit_tests", "//ios/chrome/browser/ui/bookmarks:unit_tests", "//ios/chrome/browser/ui/bookmarks/cells:unit_tests", + "//ios/chrome/browser/ui/bookmarks/home:unit_tests", "//ios/chrome/browser/ui/broadcaster:unit_tests", "//ios/chrome/browser/ui/browser_container:unit_tests", "//ios/chrome/browser/ui/browser_view:unit_tests",
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 5512601..8957529 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 @@ -ac99e8b865b36c27ac447091c470c9dc8de30d21 \ No newline at end of file +29c110920d005fb0226f8a26e5b450d5dc289e41 \ 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 9dd2992..7bcfd1f0 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 @@ -2868695d3e37f5c8937f965db22789a389760b86 \ No newline at end of file +470f04ad5485cc654a95c10ff19f4d4181512671 \ 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 d4c3546..f44f357 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 @@ -1922152d833b12b4270cb66b4ffab63b60c272bd \ No newline at end of file +c5719d82faaa5d1124e5d5b882f64f6a50d8a2df \ 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 b71014e..2a3254a 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 @@ -fa1f11109d99f3a637fffd60dc3da8033243115e \ No newline at end of file +5d974014e1bc88ab33945cc32cc1d270d9a34b0c \ 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 c88711c..312ab76 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 @@ -6697b7ba3641596932ee2df04fe4b3c7e1a0236b \ No newline at end of file +dd90526c97737e4a6fc06d4c04ad457326cab990 \ 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 01010da..08176df 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 @@ -d7a4ee3fd47e9d08400784b3ab045e781c46461c \ No newline at end of file +8ad8e8448afc2ebd0716d8fc5bfb3173a61d32b5 \ 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 926f2f6..499d7ee2 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 @@ -b51e791087b959359b201f0906b09df38edb8cde \ No newline at end of file +f1e7f3473384527a94a033754a397716e8ac8cd8 \ 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 868a7c0..2fab557 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 @@ -cdabcbaa79697a25141dc586947566a33f71ba0d \ No newline at end of file +c542d1e3a7470101e52f8e9f856fe07fa2325e7e \ 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 316b963..047f86dd 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 @@ -f1098c119828fda4f6c208c97e4a62848dffba08 \ No newline at end of file +f643e888549c0d536af58c8df18450f64566f0eb \ 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 159ac76..9bbae5e 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 @@ -00cf2834b5dfcbe21dfd0d895bb2b0a4ee77a28e \ No newline at end of file +4f7769f226d7b3f5e80acf9c0539e574c97f5f0d \ 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 e4dcaf0f..eb4ac732 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 @@ -e241b546be349cd2a9a68bd077f460b8df044b11 \ No newline at end of file +a31fc7e5367b95806c143af030f00dca9bfaef9a \ 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 006e8ec3..87f8625 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 @@ -df067bf0d2ba0145c67342944af17adf896c64c9 \ No newline at end of file +d55a7c0c63793aa0ead929584bf4402c93df3d1e \ No newline at end of file
diff --git a/ios/web/annotations/annotations_utils.h b/ios/web/annotations/annotations_utils.h index 4c0d5f9..867de2a 100644 --- a/ios/web/annotations/annotations_utils.h +++ b/ios/web/annotations/annotations_utils.h
@@ -23,6 +23,13 @@ // `NSTextCheckingResult` (without range). NSTextCheckingResult* DecodeNSTextCheckingResultData(NSString* base64_data); +// Checks if the detected entity is an URL and more specifically an email. +bool IsNSTextCheckingResultEmail(NSTextCheckingResult* result); + +// Returns a NSTextCheckingTypeLink result from an email string. +NSTextCheckingResult* MakeNSTextCheckingResultEmail(NSString* email, + NSRange range); + // Encapsulates data into a `base::Value::Type::DICTIONARY` that can be // passed to JS. `data` must come from `EncodeNSTextCheckingResultData`. base::Value::Dict ConvertMatchToAnnotation(NSString* source,
diff --git a/ios/web/annotations/annotations_utils.mm b/ios/web/annotations/annotations_utils.mm index 566ff4d..3bf9630 100644 --- a/ios/web/annotations/annotations_utils.mm +++ b/ios/web/annotations/annotations_utils.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/annotations/annotations_text_manager.h" +#import "ios/web/annotations/annotations_utils.h" #import "base/logging.h" #import "base/strings/string_util.h" @@ -22,6 +22,7 @@ static const char kAnnotationsEndKey[] = "end"; static const char kAnnotationsTypeKey[] = "type"; static const char kAnnotationsDataKey[] = "data"; +NSString* const kMailtoPrefixUrl = @"mailto:"; NSString* EncodeNSTextCheckingResultData(NSTextCheckingResult* match) { NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; @@ -48,6 +49,11 @@ if (match.phoneNumber) { [dict setObject:match.phoneNumber forKey:@"phoneNumber"]; } + } else if (IsNSTextCheckingResultEmail(match)) { + [dict setObject:@"email" forKey:@"type"]; + if (match.URL) { + [dict setObject:match.URL.resourceSpecifier forKey:@"email"]; + } } NSError* error = nil; @@ -101,6 +107,9 @@ return [NSTextCheckingResult phoneNumberCheckingResultWithRange:range phoneNumber:phoneNumber]; + } else if ([type isEqualToString:@"email"]) { + NSString* email = dict[@"email"]; + return MakeNSTextCheckingResultEmail(email, range); } return nil; } @@ -120,5 +129,17 @@ return dict; } +bool IsNSTextCheckingResultEmail(NSTextCheckingResult* result) { + return result.resultType == NSTextCheckingTypeLink && + [result.URL.scheme isEqualToString:@"mailto"]; +} + +NSTextCheckingResult* MakeNSTextCheckingResultEmail(NSString* email, + NSRange range) { + NSString* mailto_email = [kMailtoPrefixUrl stringByAppendingString:email]; + NSURL* email_url = [[NSURL alloc] initWithString:mailto_email]; + return [NSTextCheckingResult linkCheckingResultWithRange:range URL:email_url]; +} + } // namespace annotations } // namespace web
diff --git a/ios/web/annotations/resources/annotations.ts b/ios/web/annotations/resources/annotations.ts index 0bd80d4..f44b8c9 100644 --- a/ios/web/annotations/resources/annotations.ts +++ b/ios/web/annotations/resources/annotations.ts
@@ -96,6 +96,9 @@ const decorationStyles = 'border-bottom-width: 1px; ' + 'border-bottom-style: dotted; ' + 'background-color: transparent'; +const decorationStylesForPhoneAndEmail = 'border-bottom-width: 1px; ' + + 'border-bottom-style: solid; ' + + 'background-color: transparent'; const decorationDefaultColor = 'blue'; /** @@ -471,7 +474,13 @@ element.setAttribute('data-data', replacement.data); element.setAttribute('data-annotation', replacement.annotationText); element.innerText = replacement.text; - element.style.cssText = decorationStyles; + + if (replacement.type == 'PHONE_NUMBER' || replacement.type == 'EMAIL') { + element.style.cssText = decorationStylesForPhoneAndEmail; + } else { + element.style.cssText = decorationStyles; + } + element.style.borderBottomColor = textColor; element.addEventListener('click', handleTap.bind(element), true); parts.push(element);
diff --git a/ios/web/find_in_page/BUILD.gn b/ios/web/find_in_page/BUILD.gn index f3c1a63..00dbec3 100644 --- a/ios/web/find_in_page/BUILD.gn +++ b/ios/web/find_in_page/BUILD.gn
@@ -27,6 +27,8 @@ "find_in_page_manager_delegate_bridge.mm", "find_in_page_manager_impl.h", "find_in_page_manager_impl.mm", + "find_in_page_metrics.h", + "find_in_page_metrics.mm", "java_script_find_in_page_manager_impl.h", "java_script_find_in_page_manager_impl.mm", "java_script_find_in_page_request.h",
diff --git a/ios/web/find_in_page/find_in_page_manager_impl.mm b/ios/web/find_in_page/find_in_page_manager_impl.mm index 1cf577d..776212f 100644 --- a/ios/web/find_in_page/find_in_page_manager_impl.mm +++ b/ios/web/find_in_page/find_in_page_manager_impl.mm
@@ -5,6 +5,7 @@ #import <UIKit/UIKit.h> #import "ios/web/find_in_page/find_in_page_manager_impl.h" +#import "ios/web/find_in_page/find_in_page_metrics.h" #import "ios/web/public/find_in_page/find_in_page_manager_delegate.h" #import "ios/web/public/thread/web_task_traits.h" #import "ios/web/public/thread/web_thread.h" @@ -89,6 +90,16 @@ // Executes find logic for `FindInPageSearch` option. void FindInPageManagerImpl::StartSearch(NSString* query) API_AVAILABLE(ios(16)) { + if (!use_find_interaction_) { + // The "IOS.FindInPage.SearchStarted" user action is associated with a new + // text search starting i.e. when the Find UI is presented and then whenever + // the query changes. However, if a Find interaction is used, `StartSearch` + // will only be called when the Find panel is presented. The + // "IOS.FindInPage.SearchStarted" user action should not be recorded in this + // case. + RecordSearchStartedAction(); + } + // Stop polling Find session in case search is already ongoing. StopPollingActiveFindSession(); @@ -134,12 +145,9 @@ } void FindInPageManagerImpl::StopSearch() API_AVAILABLE(ios(16)) { - UIFindSession* find_session = GetActiveFindSession(); - if (!find_session) { - return; - } - StopPollingActiveFindSession(); + + UIFindSession* find_session = GetActiveFindSession(); [find_session invalidateFoundResults]; if (use_find_interaction_) { @@ -207,28 +215,46 @@ return; } - NSInteger result_count = findSession.resultCount; - NSInteger highlighted_result_index = findSession.highlightedResultIndex; + NSInteger new_result_count = findSession.resultCount; + NSInteger new_highlighted_result_index = findSession.highlightedResultIndex; + + // If the index increased by one or wrapped from the last match to the first, + // then it is very likely the user tapped "Next match" or used the associated + // keybinding. + if (new_highlighted_result_index == current_highlighted_result_index_ + 1 || + (current_highlighted_result_index_ == new_result_count - 1 && + new_highlighted_result_index == 0)) { + RecordFindNextAction(); + } + + // If the index decreased by one or wrapped from the first match to the last, + // then it is very likely the user tapped "Previous match" or used the + // associated keybinding. + if (new_highlighted_result_index == current_highlighted_result_index_ - 1 || + (current_highlighted_result_index_ == 0 && + new_highlighted_result_index == new_result_count - 1)) { + RecordFindPreviousAction(); + } // If there are results but none is selected, select the first one. - if (highlighted_result_index == NSNotFound && result_count > 0) { + if (new_highlighted_result_index == NSNotFound && new_result_count > 0) { SelectNextMatch(); } // If the result count differs from the last reported, report the new value. - if (current_result_count_ != result_count) { - delegate_->DidHighlightMatches(this, web_state_, result_count, + if (current_result_count_ != new_result_count) { + delegate_->DidHighlightMatches(this, web_state_, new_result_count, current_query_); - current_result_count_ = result_count; + current_result_count_ = new_result_count; } // If the highlighted result index differs from the last reported, report the // new value. - if (current_highlighted_result_index_ != highlighted_result_index && - highlighted_result_index != NSNotFound) { - delegate_->DidSelectMatch(this, web_state_, highlighted_result_index, + if (current_highlighted_result_index_ != new_highlighted_result_index && + new_highlighted_result_index != NSNotFound) { + delegate_->DidSelectMatch(this, web_state_, new_highlighted_result_index, /*context_string=*/nil); - current_highlighted_result_index_ = highlighted_result_index; + current_highlighted_result_index_ = new_highlighted_result_index; } }
diff --git a/ios/web/find_in_page/find_in_page_metrics.h b/ios/web/find_in_page/find_in_page_metrics.h new file mode 100644 index 0000000..d50ddfa --- /dev/null +++ b/ios/web/find_in_page/find_in_page_metrics.h
@@ -0,0 +1,21 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_FIND_IN_PAGE_FIND_IN_PAGE_METRICS_H_ +#define IOS_WEB_FIND_IN_PAGE_FIND_IN_PAGE_METRICS_H_ + +namespace web { + +// Record "IOS.FindInPage.SearchStarted" user action. +void RecordSearchStartedAction(); + +// Record "IOS.FindInPage.FindNext" user action. +void RecordFindNextAction(); + +// Record "IOS.FindInPage.FindPrevious" user action. +void RecordFindPreviousAction(); + +} // namespace web + +#endif // IOS_WEB_FIND_IN_PAGE_FIND_IN_PAGE_METRICS_H_
diff --git a/ios/web/find_in_page/find_in_page_metrics.mm b/ios/web/find_in_page/find_in_page_metrics.mm new file mode 100644 index 0000000..e677c9f --- /dev/null +++ b/ios/web/find_in_page/find_in_page_metrics.mm
@@ -0,0 +1,28 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/find_in_page/find_in_page_metrics.h" + +#import "base/metrics/user_metrics.h" +#import "base/metrics/user_metrics_action.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +void RecordSearchStartedAction() { + base::RecordAction(base::UserMetricsAction("IOS.FindInPage.SearchStarted")); +} + +void RecordFindNextAction() { + base::RecordAction(base::UserMetricsAction("IOS.FindInPage.FindNext")); +} + +void RecordFindPreviousAction() { + base::RecordAction(base::UserMetricsAction("IOS.FindInPage.FindPrevious")); +} + +} // namespace web
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl.h b/ios/web/find_in_page/java_script_find_in_page_manager_impl.h index 48ea841..fe493e3 100644 --- a/ios/web/find_in_page/java_script_find_in_page_manager_impl.h +++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl.h
@@ -8,6 +8,7 @@ #include <string> #include "base/memory/weak_ptr.h" +#import "base/values.h" #import "ios/web/find_in_page/java_script_find_in_page_request.h" #import "ios/web/public/find_in_page/java_script_find_in_page_manager.h" #include "ios/web/public/web_state_observer.h" @@ -15,13 +16,6 @@ @class NSString; -namespace { -// Find in Page UserAction keys. -const char kFindActionName[] = "Find"; -const char kFindNextActionName[] = "FindNext"; -const char kFindPreviousActionName[] = "FindPrevious"; -} // namespace - namespace web { class WebState;
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm index aa276206..84e8f0a 100644 --- a/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm +++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl.mm
@@ -10,6 +10,7 @@ #import "base/values.h" #import "ios/web/find_in_page/find_in_page_constants.h" #import "ios/web/find_in_page/find_in_page_java_script_feature.h" +#import "ios/web/find_in_page/find_in_page_metrics.h" #import "ios/web/public/find_in_page/find_in_page_manager_delegate.h" #import "ios/web/public/js_messaging/web_frame.h" #import "ios/web/public/js_messaging/web_frame_util.h" @@ -101,7 +102,7 @@ } void JavaScriptFindInPageManagerImpl::StartSearch(NSString* query) { - base::RecordAction(base::UserMetricsAction(kFindActionName)); + RecordSearchStartedAction(); std::set<WebFrame*> all_frames = web_state_->GetWebFramesManager()->GetAllWebFrames(); last_find_request_.Reset(query, all_frames.size()); @@ -251,14 +252,14 @@ } void JavaScriptFindInPageManagerImpl::SelectNextMatch() { - base::RecordAction(base::UserMetricsAction(kFindNextActionName)); + RecordFindNextAction(); if (last_find_request_.GoToNextMatch()) { SelectCurrentMatch(); } } void JavaScriptFindInPageManagerImpl::SelectPreviousMatch() { - base::RecordAction(base::UserMetricsAction(kFindPreviousActionName)); + RecordFindPreviousAction(); if (last_find_request_.GoToPreviousMatch()) { SelectCurrentMatch(); }
diff --git a/ios/web/find_in_page/java_script_find_in_page_manager_impl_unittest.mm b/ios/web/find_in_page/java_script_find_in_page_manager_impl_unittest.mm index c4bdecd..d2eefda 100644 --- a/ios/web/find_in_page/java_script_find_in_page_manager_impl_unittest.mm +++ b/ios/web/find_in_page/java_script_find_in_page_manager_impl_unittest.mm
@@ -727,17 +727,21 @@ // Tests that Find in Page logs correct UserActions for given API calls. TEST_F(JavaScriptFindInPageManagerImplTest, FindUserActions) { - ASSERT_EQ(0, user_action_tester_.GetActionCount(kFindActionName)); + ASSERT_EQ(0, + user_action_tester_.GetActionCount("IOS.FindInPage.SearchStarted")); GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageSearch); - EXPECT_EQ(1, user_action_tester_.GetActionCount(kFindActionName)); + EXPECT_EQ(1, + user_action_tester_.GetActionCount("IOS.FindInPage.SearchStarted")); - ASSERT_EQ(0, user_action_tester_.GetActionCount(kFindNextActionName)); + ASSERT_EQ(0, user_action_tester_.GetActionCount("IOS.FindInPage.FindNext")); GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPageNext); - EXPECT_EQ(1, user_action_tester_.GetActionCount(kFindNextActionName)); + EXPECT_EQ(1, user_action_tester_.GetActionCount("IOS.FindInPage.FindNext")); - ASSERT_EQ(0, user_action_tester_.GetActionCount(kFindPreviousActionName)); + ASSERT_EQ(0, + user_action_tester_.GetActionCount("IOS.FindInPage.FindPrevious")); GetFindInPageManager()->Find(@"foo", FindInPageOptions::FindInPagePrevious); - EXPECT_EQ(1, user_action_tester_.GetActionCount(kFindPreviousActionName)); + EXPECT_EQ(1, + user_action_tester_.GetActionCount("IOS.FindInPage.FindPrevious")); } } // namespace web
diff --git a/ios/web/public/test/fakes/fake_web_state.h b/ios/web/public/test/fakes/fake_web_state.h index bdcc7ac..5efc3555 100644 --- a/ios/web/public/test/fakes/fake_web_state.h +++ b/ios/web/public/test/fakes/fake_web_state.h
@@ -21,7 +21,6 @@ #import "ios/web/public/permissions/permissions.h" #import "ios/web/public/web_state.h" #include "ios/web/public/web_state_observer.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" class SessionCertificatePolicyCache; @@ -87,9 +86,6 @@ const GURL& GetVisibleURL() const override; const GURL& GetLastCommittedURL() const override; GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const override; - base::CallbackListSubscription AddScriptCommandCallback( - const ScriptCommandCallback& callback, - const std::string& command_prefix) override; CRWWebViewProxyType GetWebViewProxy() const override; void AddObserver(WebStateObserver* observer) override; @@ -164,9 +160,6 @@ NSURLResponse* response, WebStatePolicyDecider::ResponseInfo response_info, WebStatePolicyDecider::PolicyDecisionCallback callback); - // Returns a copy of the last added callback, if one has been added. - absl::optional<ScriptCommandCallback> GetLastAddedCallback() const; - std::string GetLastCommandPrefix() const; NSData* GetLastLoadedData() const; bool IsClosed() const; @@ -207,9 +200,6 @@ UIView* view_ = nil; CRWWebViewProxyType web_view_proxy_; NSData* last_loaded_data_ = nil; - base::RepeatingCallbackList<ScriptCommandCallbackSignature> callback_list_; - absl::optional<ScriptCommandCallback> last_added_callback_; - std::string last_command_prefix_; PermissionState camera_permission_state_ = PermissionStateNotAccessible; PermissionState microphone_permission_state_ = PermissionStateNotAccessible;
diff --git a/ios/web/public/test/fakes/fake_web_state.mm b/ios/web/public/test/fakes/fake_web_state.mm index 2deae6e1..632deed 100644 --- a/ios/web/public/test/fakes/fake_web_state.mm +++ b/ios/web/public/test/fakes/fake_web_state.mm
@@ -249,14 +249,6 @@ return url_; } -base::CallbackListSubscription FakeWebState::AddScriptCommandCallback( - const ScriptCommandCallback& callback, - const std::string& command_prefix) { - last_added_callback_ = callback; - last_command_prefix_ = command_prefix; - return callback_list_.Add(callback); -} - void FakeWebState::SetLastActiveTime(base::Time time) { last_active_time_ = time; } @@ -435,15 +427,6 @@ num_decisions_requested); } -absl::optional<WebState::ScriptCommandCallback> -FakeWebState::GetLastAddedCallback() const { - return last_added_callback_; -} - -std::string FakeWebState::GetLastCommandPrefix() const { - return last_command_prefix_; -} - NSData* FakeWebState::GetLastLoadedData() const { return last_loaded_data_; }
diff --git a/ios/web/public/web_state.h b/ios/web/public/web_state.h index 2c3f47c..41014bd 100644 --- a/ios/web/public/web_state.h +++ b/ios/web/public/web_state.h
@@ -15,7 +15,6 @@ #include <utility> #include <vector> -#include "base/callback_list.h" #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_piece.h" @@ -41,10 +40,6 @@ @class UIView; typedef UIView<CRWScrollableContent> CRWContentView; -namespace base { -class Value; -} - namespace gfx { class Image; class RectF; @@ -58,7 +53,6 @@ enum Permission : NSUInteger; enum PermissionState : NSUInteger; class SessionCertificatePolicyCache; -class WebFrame; class WebFramesManager; class WebStateDelegate; class WebStateObserver; @@ -386,27 +380,6 @@ // TODO(crbug.com/457679): Figure out a clean API for this. virtual GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const = 0; - // Callback used to handle script commands. `message` is the JS message sent - // from the `sender_frame` in the page, `page_url` is the URL of page's main - // frame, `user_is_interacting` indicates if the user is interacting with the - // page. - // TODO(crbug.com/881813): remove `page_url`. - using ScriptCommandCallbackSignature = void(const base::Value& message, - const GURL& page_url, - bool user_is_interacting, - web::WebFrame* sender_frame); - using ScriptCommandCallback = - base::RepeatingCallback<ScriptCommandCallbackSignature>; - // Registers `callback` for JS message whose 'command' matches - // `command_prefix`. The returned subscription should be stored by the caller. - // When the description object is destroyed, it will unregister `callback` if - // this WebState is still alive, and do nothing if this WebState is already - // destroyed. Therefore if the caller want to stop receiving JS messages it - // can just destroy the subscription. - [[nodiscard]] virtual base::CallbackListSubscription AddScriptCommandCallback( - const ScriptCommandCallback& callback, - const std::string& command_prefix) = 0; - // Returns the current CRWWebViewProxy object. virtual CRWWebViewProxyType GetWebViewProxy() const = 0;
diff --git a/ios/web/web_state/web_state_impl.h b/ios/web/web_state/web_state_impl.h index 9c155a5..923af182 100644 --- a/ios/web/web_state/web_state_impl.h +++ b/ios/web/web_state/web_state_impl.h
@@ -106,13 +106,6 @@ // Notifies the observers that the render process was terminated. void OnRenderProcessGone(); - // Called when a script command is received. - void OnScriptCommandReceived(const std::string& command, - const base::Value& value, - const GURL& page_url, - bool user_is_interacting, - WebFrame* sender_frame); - // Marks the WebState as loading/not loading. void SetIsLoading(bool is_loading); @@ -328,9 +321,6 @@ const GURL& GetVisibleURL() const final; const GURL& GetLastCommittedURL() const final; GURL GetCurrentURL(URLVerificationTrustLevel* trust_level) const final; - base::CallbackListSubscription AddScriptCommandCallback( - const ScriptCommandCallback& callback, - const std::string& command_prefix) final; id<CRWWebViewProxy> GetWebViewProxy() const final; void DidChangeVisibleSecurityState() final; InterfaceBinder* GetInterfaceBinderForMainFrame() final; @@ -372,17 +362,13 @@ class RealizedWebState; class SerializedData; - // Type aliases for the various ObserverList or ScriptCommandCallback map - // used by WebStateImpl (those are reused by the RealizedWebState class). + // Type aliases for the various ObserverList map used by WebStateImpl (reused + // by the RealizedWebState class). using WebStateObserverList = base::ObserverList<WebStateObserver, true>; using WebStatePolicyDeciderList = base::ObserverList<WebStatePolicyDecider, true>; - using ScriptCommandCallbackMap = - std::map<std::string, - base::RepeatingCallbackList<ScriptCommandCallbackSignature>>; - // Force the WebState to become realized (if in "unrealized" state) and // then return a pointer to the RealizedWebState. Safe to call if the // WebState is already realized. @@ -404,11 +390,6 @@ // allow adding policy decider to an "unrealized" WebState. WebStatePolicyDeciderList policy_deciders_; - // Callbacks associated to command prefixes. This is not stored in - // RealizedWebState/SerializedData to to allow registering command - // callback on an "unrealized" WebState. - ScriptCommandCallbackMap script_command_callbacks_; - // The instances of the two internal classes used to implement the // "unrealized" state of the WebState. One important invariant is // that except at all point either `pimpl_` or `saved_` is valid
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index d9d828a..a90bf7f 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm
@@ -171,15 +171,6 @@ RealizedState()->OnRenderProcessGone(); } -void WebStateImpl::OnScriptCommandReceived(const std::string& command, - const base::Value& value, - const GURL& page_url, - bool user_is_interacting, - WebFrame* sender_frame) { - RealizedState()->OnScriptCommandReceived(command, value, page_url, - user_is_interacting, sender_frame); -} - void WebStateImpl::SetIsLoading(bool is_loading) { RealizedState()->SetIsLoading(is_loading); } @@ -600,16 +591,6 @@ return LIKELY(pimpl_) ? pimpl_->GetCurrentURL(trust_level) : GURL(); } -base::CallbackListSubscription WebStateImpl::AddScriptCommandCallback( - const ScriptCommandCallback& callback, - const std::string& command_prefix) { - DCHECK(!command_prefix.empty()); - DCHECK(command_prefix.find_first_of('.') == std::string::npos); - DCHECK(script_command_callbacks_.count(command_prefix) == 0 || - script_command_callbacks_[command_prefix].empty()); - return script_command_callbacks_[command_prefix].Add(callback); -} - id<CRWWebViewProxy> WebStateImpl::GetWebViewProxy() const { return LIKELY(pimpl_) ? pimpl_->GetWebViewProxy() : nil; }
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.h b/ios/web/web_state/web_state_impl_realized_web_state.h index 786c5d74..f6cf9e31 100644 --- a/ios/web/web_state/web_state_impl_realized_web_state.h +++ b/ios/web/web_state/web_state_impl_realized_web_state.h
@@ -83,11 +83,6 @@ void OnBackForwardStateChanged(); void OnTitleChanged(); void OnRenderProcessGone(); - void OnScriptCommandReceived(const std::string& command, - const base::Value& value, - const GURL& page_url, - bool user_is_interacting, - WebFrame* sender_frame); void SetIsLoading(bool is_loading); void OnPageLoaded(const GURL& url, bool load_success); void OnFaviconUrlUpdated(const std::vector<FaviconURL>& candidates); @@ -232,11 +227,6 @@ return owner_->policy_deciders_; } - // Returns a reference to the owning WebState ScriptCommandCallbackMap. - ScriptCommandCallbackMap& script_command_callbacks() { - return owner_->script_command_callbacks_; - } - // Returns a new callback with the same signature as `callback` which // will clear `running_javascript_dialog_` of the current instance (if // it still exists) and then invoke the original callback.
diff --git a/ios/web/web_state/web_state_impl_realized_web_state.mm b/ios/web/web_state/web_state_impl_realized_web_state.mm index fe5c437..9574a11 100644 --- a/ios/web/web_state/web_state_impl_realized_web_state.mm +++ b/ios/web/web_state/web_state_impl_realized_web_state.mm
@@ -253,24 +253,6 @@ observer.RenderProcessGone(owner_); } -void WebStateImpl::RealizedWebState::OnScriptCommandReceived( - const std::string& command, - const base::Value& value, - const GURL& page_url, - bool user_is_interacting, - WebFrame* sender_frame) { - size_t dot_position = command.find_first_of('.'); - if (dot_position == 0 || dot_position == std::string::npos) - return; - - std::string prefix = command.substr(0, dot_position); - auto it = script_command_callbacks().find(prefix); - if (it == script_command_callbacks().end()) - return; - - it->second.Notify(value, page_url, user_is_interacting, sender_frame); -} - void WebStateImpl::RealizedWebState::SetIsLoading(bool is_loading) { if (is_loading == is_loading_) return;
diff --git a/ios/web/web_state/web_state_impl_serialized_data.h b/ios/web/web_state/web_state_impl_serialized_data.h index 815f1327b..52316c2 100644 --- a/ios/web/web_state/web_state_impl_serialized_data.h +++ b/ios/web/web_state/web_state_impl_serialized_data.h
@@ -67,11 +67,6 @@ return owner_->policy_deciders_; } - // Returns a reference to the owning WebState ScriptCommandCallbackMap. - ScriptCommandCallbackMap& script_command_callbacks() { - return owner_->script_command_callbacks_; - } - // Returns the CRWNavigationItemStorage* corresponding to the last committed // navigation item from the serialized state. May return nil. CRWNavigationItemStorage* GetLastCommittedItem() const;
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm index 25e68c3..c133464 100644 --- a/ios/web/web_state/web_state_impl_unittest.mm +++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -133,25 +133,6 @@ MOCK_METHOD0(WebStateDestroyed, void()); }; -// Test callback for script commands. -// Sets `is_called` to true if it is called, and checks that the parameters -// match their expected values. -void HandleScriptCommand(bool* is_called, - base::Value* expected_value, - const GURL& expected_url, - bool expected_user_is_interacting, - web::WebFrame* expected_sender_frame, - const base::Value& value, - const GURL& url, - bool user_is_interacting, - web::WebFrame* sender_frame) { - *is_called = true; - EXPECT_EQ(*expected_value, value); - EXPECT_EQ(expected_url, url); - EXPECT_EQ(expected_user_is_interacting, user_is_interacting); - EXPECT_EQ(expected_sender_frame, sender_frame); -} - } // namespace // Test fixture for web::WebStateImpl class. @@ -742,104 +723,6 @@ EXPECT_EQ(policy_decision.GetDisplayError().code, error2.code); } -// Tests that script command callbacks are called correctly. -TEST_F(WebStateImplTest, ScriptCommand) { - // Set up three script command callbacks. - const std::string kPrefix1("prefix1"); - const std::string kCommand1("prefix1.command1"); - base::Value value_1(base::Value::Type::DICTIONARY); - value_1.SetStringKey("a", "b"); - const GURL kUrl1("http://foo"); - bool is_called_1 = false; - auto main_frame = FakeWebFrame::CreateMainWebFrame(GURL::EmptyGURL()); - base::CallbackListSubscription subscription_1 = - web_state_->AddScriptCommandCallback( - base::BindRepeating( - &HandleScriptCommand, &is_called_1, &value_1, kUrl1, - /*expected_user_is_interacting*/ false, main_frame.get()), - kPrefix1); - - const std::string kPrefix2("prefix2"); - const std::string kCommand2("prefix2.command2"); - base::Value value_2(base::Value::Type::DICTIONARY); - value_2.SetStringKey("c", "d"); - const GURL kUrl2("http://bar"); - bool is_called_2 = false; - base::CallbackListSubscription subscription_2 = - web_state_->AddScriptCommandCallback( - base::BindRepeating( - &HandleScriptCommand, &is_called_2, &value_2, kUrl2, - /*expected_user_is_interacting*/ false, main_frame.get()), - kPrefix2); - - const std::string kPrefix3("prefix3"); - const std::string kCommand3("prefix3.command3"); - base::Value value_3(base::Value::Type::DICTIONARY); - value_3.SetStringKey("e", "f"); - const GURL kUrl3("http://iframe"); - bool is_called_3 = false; - auto subframe = FakeWebFrame::CreateChildWebFrame(GURL::EmptyGURL()); - base::CallbackListSubscription subscription_3 = - web_state_->AddScriptCommandCallback( - base::BindRepeating( - &HandleScriptCommand, &is_called_3, &value_3, kUrl3, - /*expected_user_is_interacting*/ false, subframe.get()), - kPrefix3); - - // Check that a irrelevant or invalid command does not trigger the callbacks. - web_state_->OnScriptCommandReceived("wohoo.blah", value_1, kUrl1, - /*user_is_interacting*/ false, - /*sender_frame*/ main_frame.get()); - EXPECT_FALSE(is_called_1); - EXPECT_FALSE(is_called_2); - EXPECT_FALSE(is_called_3); - - web_state_->OnScriptCommandReceived("prefix1ButMissingDot", value_1, kUrl1, - /*user_is_interacting*/ false, - /*sender_frame*/ main_frame.get()); - EXPECT_FALSE(is_called_1); - EXPECT_FALSE(is_called_2); - EXPECT_FALSE(is_called_3); - - // Check that only the callback matching the prefix is called, with the - // expected parameters and return value; - - web_state_->OnScriptCommandReceived(kCommand1, value_1, kUrl1, - /*user_is_interacting*/ false, - - /*sender_frame*/ main_frame.get()); - EXPECT_TRUE(is_called_1); - EXPECT_FALSE(is_called_2); - EXPECT_FALSE(is_called_3); - is_called_1 = false; - // Check that sending message from iframe sets `is_main_frame` to false. - web_state_->OnScriptCommandReceived(kCommand3, value_3, kUrl3, - /*user_is_interacting*/ false, - - /*sender_frame*/ subframe.get()); - EXPECT_FALSE(is_called_1); - EXPECT_FALSE(is_called_2); - EXPECT_TRUE(is_called_3); - is_called_3 = false; - - // Remove the callback and check it is no longer called. - subscription_1 = {}; - web_state_->OnScriptCommandReceived(kCommand1, value_1, kUrl1, - /*user_is_interacting*/ false, - /*sender_frame*/ main_frame.get()); - EXPECT_FALSE(is_called_1); - EXPECT_FALSE(is_called_2); - EXPECT_FALSE(is_called_3); - - // Check that a false return value is forwarded correctly. - web_state_->OnScriptCommandReceived(kCommand2, value_2, kUrl2, - /*user_is_interacting*/ false, - /*sender_frame*/ main_frame.get()); - EXPECT_FALSE(is_called_1); - EXPECT_TRUE(is_called_2); - EXPECT_FALSE(is_called_3); -} - // Tests that WebState::CreateParams::created_with_opener is translated to // WebState::HasOpener() return values. TEST_F(WebStateImplTest, CreatedWithOpener) {
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index 6b8bf04..74e8e9e 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc
@@ -1311,7 +1311,7 @@ // deserialized by the traits should always yield a non-empty token. // If deserialization results in an empty token, the data is malformed. absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return false; }
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index c00130f..85aeba88 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -384,6 +384,7 @@ "//gpu/command_buffer/client:raster_interface", "//gpu/command_buffer/common", "//gpu/ipc/common:common", + "//media/cdm:clear_key_cdm_common", "//net", "//skia", "//third_party/libyuv",
diff --git a/media/base/key_system_names.cc b/media/base/key_system_names.cc index 3ecdc56..5475bb9c 100644 --- a/media/base/key_system_names.cc +++ b/media/base/key_system_names.cc
@@ -3,14 +3,12 @@ // found in the LICENSE file. #include "media/base/key_system_names.h" +#include "media/cdm/clear_key_cdm_common.h" namespace media { -const char kClearKey[] = "org.w3.clearkey"; -const char kExternalClearKey[] = "org.chromium.externalclearkey"; - bool IsClearKey(const std::string& key_system) { - return key_system == kClearKey; + return key_system == kClearKeyKeySystem; } bool IsSubKeySystemOf(const std::string& key_system, const std::string& base) { @@ -19,8 +17,8 @@ } bool IsExternalClearKey(const std::string& key_system) { - return key_system == kExternalClearKey || - IsSubKeySystemOf(key_system, kExternalClearKey); + return key_system == kExternalClearKeyKeySystem || + IsSubKeySystemOf(key_system, kExternalClearKeyKeySystem); } } // namespace media
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc index 7d0d480..0ec0277f 100644 --- a/media/base/key_systems.cc +++ b/media/base/key_systems.cc
@@ -26,6 +26,7 @@ #include "media/base/media_client.h" #include "media/base/media_switches.h" #include "media/base/mime_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "third_party/widevine/cdm/widevine_cdm_common.h" @@ -33,8 +34,6 @@ namespace { -const char kClearKeyKeySystem[] = "org.w3.clearkey"; - // These names are used by UMA. Do not change them! const char kClearKeyKeySystemNameForUMA[] = "ClearKey"; const char kUnknownKeySystemNameForUMA[] = "Unknown"; @@ -66,7 +65,7 @@ {"video/mp2t", EME_CODEC_MP2T_VIDEO_ALL}, #endif // BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) -}; // namespace media +}; EmeCodec ToAudioEmeCodec(AudioCodec codec) { switch (codec) { @@ -155,13 +154,13 @@ } EmeConfig::Rule GetEncryptionSchemeConfigRule( - media::EncryptionScheme encryption_scheme) const final { + EncryptionScheme encryption_scheme) const final { switch (encryption_scheme) { - case media::EncryptionScheme::kCenc: - case media::EncryptionScheme::kCbcs: { + case EncryptionScheme::kCenc: + case EncryptionScheme::kCbcs: { return EmeConfig::SupportedRule(); } - case media::EncryptionScheme::kUnencrypted: + case EncryptionScheme::kUnencrypted: break; } NOTREACHED(); @@ -230,8 +229,9 @@ if (key_system == kWidevineKeySystem) return true; - if (key_system == kClearKeyKeySystem) + if (key_system == kClearKeyKeySystem) { return true; + } // External Clear Key is known and supports suffixes for testing. if (IsExternalClearKey(key_system)) @@ -260,10 +260,10 @@ // For External Clear Key, it is either implemented as a library CDM (Clear // Key CDM), which is covered above, or by using AesDecryptor remotely, e.g. // via MojoCdm. In both cases, we can block. This is only used for testing. - if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting) && - IsExternalClearKey(properties.GetBaseKeySystemName())) + if (base::FeatureList::IsEnabled(kExternalClearKeyForTesting) && + IsExternalClearKey(properties.GetBaseKeySystemName())) { return true; - + } #if BUILDFLAG(ENABLE_LIBRARY_CDMS) // When library CDMs are enabled, we are either using AesDecryptor, or using // the library CDM hosted in a sandboxed process. In both cases distinctive @@ -863,8 +863,9 @@ // For Clear Key and unknown key systems we don't to differentiate between // software and hardware security. - if (key_system == kClearKeyKeySystem) + if (key_system == kClearKeyKeySystem) { return kClearKeyKeySystemNameForUMA; + } return kUnknownKeySystemNameForUMA; } @@ -873,8 +874,9 @@ if (key_system == kWidevineKeySystem) return KeySystemForUkm::kWidevineKeySystemForUkm; - if (key_system == kClearKeyKeySystem) + if (key_system == kClearKeyKeySystem) { return KeySystemForUkm::kClearKeyKeySystemForUkm; + } return KeySystemForUkm::kUnknownKeySystemForUkm; }
diff --git a/media/base/key_systems_unittest.cc b/media/base/key_systems_unittest.cc index eccadbb..0a20b4f 100644 --- a/media/base/key_systems_unittest.cc +++ b/media/base/key_systems_unittest.cc
@@ -22,6 +22,7 @@ #include "media/base/key_systems.h" #include "media/base/media.h" #include "media/base/media_client.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -37,9 +38,6 @@ const char kUsesAes[] = "x-org.example.usesaes"; const char kExternal[] = "x-com.example.external"; -const char kClearKey[] = "org.w3.clearkey"; -const char kExternalClearKey[] = "org.chromium.externalclearkey"; - const char kAudioWebM[] = "audio/webm"; const char kVideoWebM[] = "video/webm"; const char kAudioFoo[] = "audio/foo"; @@ -131,10 +129,10 @@ EmeConfig::Rule GetEncryptionSchemeConfigRule( EncryptionScheme encryption_scheme) const override { switch (encryption_scheme) { - case media::EncryptionScheme::kUnencrypted: - case media::EncryptionScheme::kCenc: + case EncryptionScheme::kUnencrypted: + case EncryptionScheme::kCenc: return EmeConfig::SupportedRule(); - case media::EncryptionScheme::kCbcs: + case EncryptionScheme::kCbcs: return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kNotAllowed}; } NOTREACHED(); @@ -246,15 +244,15 @@ // MediaClient implementation. void GetSupportedKeySystems(GetSupportedKeySystemsCB cb) final; - bool IsSupportedAudioType(const media::AudioType& type) final; - bool IsSupportedVideoType(const media::VideoType& type) final; + bool IsSupportedAudioType(const AudioType& type) final; + bool IsSupportedVideoType(const VideoType& type) final; bool IsSupportedBitstreamAudioCodec(AudioCodec codec) final; // Helper function to disable "kExternal" key system support so that we can // test the key system update case. void DisableExternalKeySystemSupport(); - absl::optional<::media::AudioRendererAlgorithmParameters> + absl::optional<AudioRendererAlgorithmParameters> GetAudioRendererAlgorithmParameters(AudioParameters audio_parameters) final; private: @@ -274,11 +272,11 @@ get_supported_key_systems_cb_.Run(GetSupportedKeySystemsInternal()); } -bool TestMediaClient::IsSupportedAudioType(const media::AudioType& type) { +bool TestMediaClient::IsSupportedAudioType(const AudioType& type) { return true; } -bool TestMediaClient::IsSupportedVideoType(const media::VideoType& type) { +bool TestMediaClient::IsSupportedVideoType(const VideoType& type) { return true; } @@ -291,7 +289,7 @@ get_supported_key_systems_cb_.Run(GetSupportedKeySystemsInternal()); } -absl::optional<::media::AudioRendererAlgorithmParameters> +absl::optional<AudioRendererAlgorithmParameters> TestMediaClient::GetAudioRendererAlgorithmParameters( AudioParameters audio_parameters) { return absl::nullopt; @@ -446,22 +444,22 @@ // Clear Key is the only key system registered in content. TEST_F(KeySystemsTest, ClearKey) { - EXPECT_TRUE(IsSupportedKeySystem(kClearKey)); + EXPECT_TRUE(IsSupportedKeySystem(kClearKeyKeySystem)); EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType(kVideoWebM, no_codecs(), - kClearKey)); + kClearKeyKeySystem)); - EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKey)); + EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKeyKeySystem)); } TEST_F(KeySystemsTest, ClearKeyWithInitDataType) { - EXPECT_TRUE(IsSupportedKeySystem(kClearKey)); - EXPECT_TRUE( - IsSupportedKeySystemWithInitDataType(kClearKey, EmeInitDataType::WEBM)); - EXPECT_TRUE( - IsSupportedKeySystemWithInitDataType(kClearKey, EmeInitDataType::KEYIDS)); + EXPECT_TRUE(IsSupportedKeySystem(kClearKeyKeySystem)); + EXPECT_TRUE(IsSupportedKeySystemWithInitDataType(kClearKeyKeySystem, + EmeInitDataType::WEBM)); + EXPECT_TRUE(IsSupportedKeySystemWithInitDataType(kClearKeyKeySystem, + EmeInitDataType::KEYIDS)); // All other InitDataTypes are not supported. - EXPECT_FALSE(IsSupportedKeySystemWithInitDataType(kClearKey, + EXPECT_FALSE(IsSupportedKeySystemWithInitDataType(kClearKeyKeySystem, EmeInitDataType::UNKNOWN)); } @@ -757,9 +755,9 @@ } TEST_F(KeySystemsTest, KeySystemNameForUMA) { - EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKey)); - EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKey, false)); - EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKey, true)); + EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKeyKeySystem)); + EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKeyKeySystem, false)); + EXPECT_EQ("ClearKey", GetKeySystemNameForUMA(kClearKeyKeySystem, true)); EXPECT_EQ("Widevine", GetKeySystemNameForUMA(kWidevineKeySystem)); EXPECT_EQ("Widevine.SoftwareSecure", GetKeySystemNameForUMA(kWidevineKeySystem, false)); @@ -770,9 +768,11 @@ EXPECT_EQ("Unknown", GetKeySystemNameForUMA("Foo", true)); // External Clear Key never has a UMA name. - EXPECT_EQ("Unknown", GetKeySystemNameForUMA(kExternalClearKey)); - EXPECT_EQ("Unknown", GetKeySystemNameForUMA(kExternalClearKey, false)); - EXPECT_EQ("Unknown", GetKeySystemNameForUMA(kExternalClearKey, true)); + EXPECT_EQ("Unknown", GetKeySystemNameForUMA(kExternalClearKeyKeySystem)); + EXPECT_EQ("Unknown", + GetKeySystemNameForUMA(kExternalClearKeyKeySystem, false)); + EXPECT_EQ("Unknown", + GetKeySystemNameForUMA(kExternalClearKeyKeySystem, true)); } TEST_F(KeySystemsTest, KeySystemsUpdate) {
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 167f13b..41315ec 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -533,6 +533,12 @@ "OpenscreenCastStreamingSession", base::FEATURE_DISABLED_BY_DEFAULT); +// Controls whether the Mirroring Service will fetch, analyze, and store +// information on the quality of the session using RTCP logs. +BASE_FEATURE(kEnableRtcpReporting, + "EnableRtcpReporting", + base::FEATURE_DISABLED_BY_DEFAULT); + // Approach original pre-REC MSE object URL autorevoking behavior, though await // actual attempt to use the object URL for attachment to perform revocation. // This will hopefully reduce runtime memory bloat for pages that do not @@ -1078,7 +1084,7 @@ // please use IsMediaFoundationD3D11VideoCaptureEnabled() instead. BASE_FEATURE(kMediaFoundationD3D11VideoCapture, "MediaFoundationD3D11VideoCapture", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables VP8 decode acceleration for Windows. const base::Feature MEDIA_EXPORT kMediaFoundationVP8Decoding{
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index c1411ef..e4ac0b57a 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -243,6 +243,7 @@ MEDIA_EXPORT BASE_DECLARE_FEATURE(kOverlayFullscreenVideo); MEDIA_EXPORT BASE_DECLARE_FEATURE(kPauseBackgroundMutedAudio); MEDIA_EXPORT BASE_DECLARE_FEATURE(kPlatformAudioEncoder); +MEDIA_EXPORT BASE_DECLARE_FEATURE(kEnableRtcpReporting); #if BUILDFLAG(ENABLE_PLATFORM_HEVC) MEDIA_EXPORT BASE_DECLARE_FEATURE(kPlatformHEVCDecoderSupport); #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index 5779a470..bb0436a 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -87,7 +87,9 @@ {"mp4a.A6", MimeUtil::EAC3}, {"vorbis", MimeUtil::VORBIS}, {"opus", MimeUtil::OPUS}, + {"Opus", MimeUtil::OPUS}, {"flac", MimeUtil::FLAC}, + {"fLaC", MimeUtil::FLAC}, {"vp8", MimeUtil::VP8}, {"vp8.0", MimeUtil::VP8}, {"theora", MimeUtil::THEORA},
diff --git a/media/base/svc_scalability_mode.cc b/media/base/svc_scalability_mode.cc index 2f3ccca1..2f00fd0 100644 --- a/media/base/svc_scalability_mode.cc +++ b/media/base/svc_scalability_mode.cc
@@ -58,6 +58,8 @@ return "S3T2h"; case SVCScalabilityMode::kS3T3h: return "S3T3h"; + case SVCScalabilityMode::kL2T1Key: + return "L2T1_KEY"; case SVCScalabilityMode::kL2T2Key: return "L2T2_KEY"; case SVCScalabilityMode::kL2T2KeyShift: @@ -66,6 +68,8 @@ return "L2T3_KEY"; case SVCScalabilityMode::kL2T3KeyShift: return "L2T3_KEY_SHIFT"; + case SVCScalabilityMode::kL3T1Key: + return "L3T1_KEY"; case SVCScalabilityMode::kL3T2Key: return "L3T2_KEY"; case SVCScalabilityMode::kL3T2KeyShift:
diff --git a/media/base/svc_scalability_mode.h b/media/base/svc_scalability_mode.h index 926037cc..f96a560 100644 --- a/media/base/svc_scalability_mode.h +++ b/media/base/svc_scalability_mode.h
@@ -36,10 +36,12 @@ kS3T1h, kS3T2h, kS3T3h, + kL2T1Key, kL2T2Key, kL2T2KeyShift, kL2T3Key, kL2T3KeyShift, + kL3T1Key, kL3T2Key, kL3T2KeyShift, kL3T3Key,
diff --git a/media/capabilities/video_decode_stats_db_unittest.cc b/media/capabilities/video_decode_stats_db_unittest.cc index c792266..b55b353b 100644 --- a/media/capabilities/video_decode_stats_db_unittest.cc +++ b/media/capabilities/video_decode_stats_db_unittest.cc
@@ -6,6 +6,7 @@ #include "media/base/video_codecs.h" #include "media/capabilities/bucket_utility.h" +#include "media/cdm/clear_key_cdm_common.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/rect.h" @@ -32,7 +33,7 @@ // Same as above + KeySystem. Serialize should now show KeySystem name + // mention of hw_secure. auto keyB = MakeKey(H264PROFILE_BASELINE, gfx::Size(1280, 720), 30, - "org.w3.clearkey", false); + kClearKeyKeySystem, false); ASSERT_EQ("0|1280x720|30|org.w3.clearkey|not_hw_secure", keyB.Serialize()); // Different KeySystem, different hw_secure status.
diff --git a/media/capture/mojom/image_capture.mojom b/media/capture/mojom/image_capture.mojom index a1c8698..d4063220 100644 --- a/media/capture/mojom/image_capture.mojom +++ b/media/capture/mojom/image_capture.mojom
@@ -254,8 +254,7 @@ => (PhotoState state); // Sets the |settings| on the associated video capture device. - // https://www.w3.org/TR/image-capture/#dom-imagecapture-setoptions - SetOptions(string source_id, PhotoSettings settings) + SetPhotoOptions(string source_id, PhotoSettings settings) => (bool success); // Takes a Photo from the given |source_id|, returning it encoded in |blob|
diff --git a/media/capture/video/blob_utils.cc b/media/capture/video/blob_utils.cc index b3ec886..1867a4d 100644 --- a/media/capture/video/blob_utils.cc +++ b/media/capture/video/blob_utils.cc
@@ -104,6 +104,8 @@ src_format = libyuv::FOURCC_I420; else if (pixel_format == VideoPixelFormat::PIXEL_FORMAT_RGB24) src_format = libyuv::FOURCC_24BG; + else if (pixel_format == VideoPixelFormat::PIXEL_FORMAT_NV12) + src_format = libyuv::FOURCC_NV12; else return nullptr;
diff --git a/media/cdm/BUILD.gn b/media/cdm/BUILD.gn index 83d5806b..7857a151d 100644 --- a/media/cdm/BUILD.gn +++ b/media/cdm/BUILD.gn
@@ -67,7 +67,10 @@ "supported_audio_codecs.h", ] - public_deps = [ ":cdm_type" ] + public_deps = [ + ":cdm_type", + ":clear_key_cdm_common", + ] deps = [ "//crypto", @@ -158,8 +161,6 @@ sources = [ "cdm_paths.cc" ] - public_deps = [ ":cdm_type" ] - deps = [ "//base", "//media:media_buildflags", @@ -172,6 +173,12 @@ deps = [ "//base" ] } +source_set("clear_key_cdm_common") { + sources = [ "clear_key_cdm_common.h" ] + public_deps = [ ":cdm_type" ] + deps = [ "//media:media_buildflags" ] +} + source_set("unit_tests") { testonly = true sources = [
diff --git a/media/cdm/DEPS b/media/cdm/DEPS index c8585a64..18146e10 100644 --- a/media/cdm/DEPS +++ b/media/cdm/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+components/crash/core/common/crash_key.h", "+crypto", + "+media/cdm/clear_key_cdm_common.h", "+third_party/boringssl/src/include", ]
diff --git a/media/cdm/cdm_host_files.cc b/media/cdm/cdm_host_files.cc index a2cea641..86dc248 100644 --- a/media/cdm/cdm_host_files.cc +++ b/media/cdm/cdm_host_files.cc
@@ -18,7 +18,6 @@ #include "base/scoped_native_library.h" #include "build/build_config.h" #include "media/cdm/api/content_decryption_module_ext.h" -#include "media/cdm/cdm_paths.h" namespace media {
diff --git a/media/cdm/cdm_host_files.h b/media/cdm/cdm_host_files.h index 757a1ea3..b5aa79f 100644 --- a/media/cdm/cdm_host_files.h +++ b/media/cdm/cdm_host_files.h
@@ -18,7 +18,6 @@ #include "media/base/media_export.h" #include "media/cdm/api/content_decryption_module_ext.h" #include "media/cdm/cdm_host_file.h" -#include "media/cdm/cdm_paths.h" namespace base { class FilePath;
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc index 22a9d940d..0aa57b1 100644 --- a/media/cdm/cdm_paths.cc +++ b/media/cdm/cdm_paths.cc
@@ -7,26 +7,10 @@ #include <string> #include "build/build_config.h" -#include "media/cdm/cdm_type.h" #include "media/media_buildflags.h" namespace media { -// Name of the ClearKey CDM library. -const char kClearKeyCdmLibraryName[] = "clearkeycdm"; - -const char kClearKeyCdmBaseDirectory[] = -#if BUILDFLAG(IS_FUCHSIA) - "lib/" -#endif - "ClearKeyCdm"; - -const char kClearKeyCdmDisplayName[] = "Clear Key CDM"; - -const CdmType kClearKeyCdmType{0x3a2e0fadde4bd1b7ull, 0xcb90df3e240d1694ull}; -const CdmType kClearKeyCdmDifferentCdmType{0xc3914773474bdb02ull, - 0x8e8de4d84d3ca030ull}; - base::FilePath GetPlatformSpecificDirectory( const base::FilePath& cdm_base_path) { // CDM_PLATFORM_SPECIFIC_PATH is specified in cdm_paths.gni.
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h index 9766053..f2a0ee4 100644 --- a/media/cdm/cdm_paths.h +++ b/media/cdm/cdm_paths.h
@@ -10,7 +10,6 @@ #include "base/files/file_path.h" #include "base/unguessable_token.h" #include "build/build_config.h" -#include "media/cdm/cdm_type.h" #include "media/media_buildflags.h" #if !BUILDFLAG(ENABLE_LIBRARY_CDMS) @@ -19,21 +18,6 @@ namespace media { -// Name of the ClearKey CDM library. -extern const char kClearKeyCdmLibraryName[]; - -extern const char kClearKeyCdmBaseDirectory[]; - -// Display name for Clear Key CDM. -extern const char kClearKeyCdmDisplayName[]; - -// The default GUID for Clear Key Cdm. -extern const CdmType kClearKeyCdmType; - -// A different GUID for Clear Key Cdm for testing running different types of -// CDMs in the system. -extern const CdmType kClearKeyCdmDifferentCdmType; - // Returns the path of a CDM relative to DIR_COMPONENTS. // On platforms where a platform specific path is used, returns // |cdm_base_path|/_platform_specific/<platform>_<arch>
diff --git a/media/cdm/clear_key_cdm_common.h b/media/cdm/clear_key_cdm_common.h new file mode 100644 index 0000000..b41148a --- /dev/null +++ b/media/cdm/clear_key_cdm_common.h
@@ -0,0 +1,92 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CDM_CLEAR_KEY_CDM_COMMON_H_ +#define MEDIA_CDM_CLEAR_KEY_CDM_COMMON_H_ + +#include "build/build_config.h" +#include "media/cdm/cdm_type.h" +#include "media/media_buildflags.h" + +namespace media { + +// Clear Key key system defined in the EME spec. +inline constexpr char kClearKeyKeySystem[] = "org.w3.clearkey"; + +// External Clear Key key system ("org.chromium.externalclearkey" and variants) +// only for testing. +inline constexpr char kExternalClearKeyKeySystem[] = + "org.chromium.externalclearkey"; + +// Variants of External Clear Key key system to test different scenarios. +// To add a new variant, make sure you also update: +// - media/test/data/eme_player_js/globals.js +// - media/test/data/eme_player_js/player_utils.js +// - CreateCdmInstance() in clear_key_cdm.cc + +// A sub key system that is invalid for testing purpose. +inline constexpr char kExternalClearKeyInvalidKeySystem[] = + "org.chromium.externalclearkey.invalid"; + +// A sub key system that supports decrypt-only mode. +inline constexpr char kExternalClearKeyDecryptOnlyKeySystem[] = + "org.chromium.externalclearkey.decryptonly"; + +// A sub key system that triggers various types of messages. +inline constexpr char kExternalClearKeyMessageTypeTestKeySystem[] = + "org.chromium.externalclearkey.messagetypetest"; + +// A sub key system that triggers the FileIO test. +inline constexpr char kExternalClearKeyFileIOTestKeySystem[] = + "org.chromium.externalclearkey.fileiotest"; + +// A sub key system that triggers the output protection test. +inline constexpr char kExternalClearKeyOutputProtectionTestKeySystem[] = + "org.chromium.externalclearkey.outputprotectiontest"; + +// A sub key system that triggers the platform verification test. +inline constexpr char kExternalClearKeyPlatformVerificationTestKeySystem[] = + "org.chromium.externalclearkey.platformverificationtest"; + +// A sub key system that triggers a crash. +inline constexpr char kExternalClearKeyCrashKeySystem[] = + "org.chromium.externalclearkey.crash"; + +// A sub key system that triggers the verify host files test. +inline constexpr char kExternalClearKeyVerifyCdmHostTestKeySystem[] = + "org.chromium.externalclearkey.verifycdmhosttest"; + +// A sub key system that fetches the Storage ID. +inline constexpr char kExternalClearKeyStorageIdTestKeySystem[] = + "org.chromium.externalclearkey.storageidtest"; + +// A sub key system that is registered with a different CDM type. +inline constexpr char kExternalClearKeyDifferentCdmTypeTestKeySystem[] = + "org.chromium.externalclearkey.differentcdmtype"; + +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +// Name of the ClearKey CDM library. +inline constexpr char kClearKeyCdmLibraryName[] = "clearkeycdm"; + +inline constexpr char kClearKeyCdmBaseDirectory[] = +#if BUILDFLAG(IS_FUCHSIA) + "lib/" +#endif + "ClearKeyCdm"; + +// Display name for Clear Key CDM. +inline constexpr char kClearKeyCdmDisplayName[] = "Clear Key CDM"; +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) + +// The default GUID for Clear Key Cdm. +const CdmType kClearKeyCdmType{0x3a2e0fadde4bd1b7ull, 0xcb90df3e240d1694ull}; + +// A different GUID for Clear Key Cdm for testing running different types of +// CDMs in the system. +const CdmType kClearKeyCdmDifferentCdmType{0xc3914773474bdb02ull, + 0x8e8de4d84d3ca030ull}; + +} // namespace media + +#endif // MEDIA_CDM_CLEAR_KEY_CDM_COMMON_H_
diff --git a/media/cdm/external_clear_key_test_helper.cc b/media/cdm/external_clear_key_test_helper.cc index cd09b2f..68a0b68 100644 --- a/media/cdm/external_clear_key_test_helper.cc +++ b/media/cdm/external_clear_key_test_helper.cc
@@ -12,6 +12,7 @@ #include "build/build_config.h" #include "media/cdm/api/content_decryption_module.h" #include "media/cdm/cdm_paths.h" +#include "media/cdm/clear_key_cdm_common.h" #include "testing/gtest/include/gtest/gtest.h" namespace media {
diff --git a/media/cdm/external_clear_key_test_helper.h b/media/cdm/external_clear_key_test_helper.h index 854580d..771fa17c 100644 --- a/media/cdm/external_clear_key_test_helper.h +++ b/media/cdm/external_clear_key_test_helper.h
@@ -5,11 +5,10 @@ #ifndef MEDIA_CDM_EXTERNAL_CLEAR_KEY_TEST_HELPER_H_ #define MEDIA_CDM_EXTERNAL_CLEAR_KEY_TEST_HELPER_H_ -#include <string> - #include "base/files/file_path.h" #include "base/scoped_native_library.h" #include "media/base/cdm_config.h" +#include "media/cdm/clear_key_cdm_common.h" namespace media { @@ -26,7 +25,7 @@ ~ExternalClearKeyTestHelper(); media::CdmConfig CdmConfig() { - return {"org.chromium.externalclearkey", false, false, false}; + return {kExternalClearKeyKeySystem, false, false, false}; } base::FilePath LibraryPath() { return library_path_; }
diff --git a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc index bdc9878..61f1370 100644 --- a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc +++ b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
@@ -25,6 +25,7 @@ #include "media/base/encryption_pattern.h" #include "media/cdm/api/content_decryption_module_ext.h" #include "media/cdm/cdm_type_conversion.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/json_web_key.h" #include "media/cdm/library_cdm/cdm_host_proxy.h" #include "media/cdm/library_cdm/cdm_host_proxy_impl.h" @@ -45,46 +46,9 @@ #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER const char kClearKeyCdmVersion[] = "0.1.0.1"; -const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; // Variants of External Clear Key key system to test different scenarios. -// A sub key system that supports decrypt-only mode. -const char kExternalClearKeyDecryptOnlyKeySystem[] = - "org.chromium.externalclearkey.decryptonly"; - -// A sub key system that triggers various types of messages. -const char kExternalClearKeyMessageTypeTestKeySystem[] = - "org.chromium.externalclearkey.messagetypetest"; - -// A sub key system that triggers the FileIO test. -const char kExternalClearKeyFileIOTestKeySystem[] = - "org.chromium.externalclearkey.fileiotest"; - -// A sub key system that triggers the output protection test. -const char kExternalClearKeyOutputProtectionTestKeySystem[] = - "org.chromium.externalclearkey.outputprotectiontest"; - -// A sub key system that triggers the platform verification test. -const char kExternalClearKeyPlatformVerificationTestKeySystem[] = - "org.chromium.externalclearkey.platformverificationtest"; - -// A sub key system that triggers a crash. -const char kExternalClearKeyCrashKeySystem[] = - "org.chromium.externalclearkey.crash"; - -// A sub key system that triggers the verify host files test. -const char kExternalClearKeyVerifyCdmHostTestKeySystem[] = - "org.chromium.externalclearkey.verifycdmhosttest"; - -// A sub key system that fetches the Storage ID. -const char kExternalClearKeyStorageIdTestKeySystem[] = - "org.chromium.externalclearkey.storageidtest"; - -// A sub key system that is registered with a different CDM type. -const char kkExternalClearKeyDifferentCdmTypeTestKeySystem[] = - "org.chromium.externalclearkey.differentcdmtype"; - const int64_t kMsPerSecond = 1000; const int64_t kMaxTimerDelayMs = 5 * kMsPerSecond; @@ -186,16 +150,19 @@ } std::string key_system_string(key_system, key_system_size); - if (key_system_string != kExternalClearKeyKeySystem && - key_system_string != kExternalClearKeyDecryptOnlyKeySystem && - key_system_string != kExternalClearKeyMessageTypeTestKeySystem && - key_system_string != kExternalClearKeyFileIOTestKeySystem && - key_system_string != kExternalClearKeyOutputProtectionTestKeySystem && - key_system_string != kExternalClearKeyPlatformVerificationTestKeySystem && - key_system_string != kExternalClearKeyCrashKeySystem && - key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem && - key_system_string != kExternalClearKeyStorageIdTestKeySystem && - key_system_string != kkExternalClearKeyDifferentCdmTypeTestKeySystem) { + if (key_system_string != media::kExternalClearKeyKeySystem && + key_system_string != media::kExternalClearKeyDecryptOnlyKeySystem && + key_system_string != media::kExternalClearKeyMessageTypeTestKeySystem && + key_system_string != media::kExternalClearKeyFileIOTestKeySystem && + key_system_string != + media::kExternalClearKeyOutputProtectionTestKeySystem && + key_system_string != + media::kExternalClearKeyPlatformVerificationTestKeySystem && + key_system_string != media::kExternalClearKeyCrashKeySystem && + key_system_string != media::kExternalClearKeyVerifyCdmHostTestKeySystem && + key_system_string != media::kExternalClearKeyStorageIdTestKeySystem && + key_system_string != + media::kExternalClearKeyDifferentCdmTypeTestKeySystem) { DVLOG(1) << "Unsupported key system:" << key_system_string; return nullptr; } @@ -396,8 +363,8 @@ return; } - std::unique_ptr<media::NewSessionCdmPromise> promise( - new media::CdmCallbackPromise<std::string>( + std::unique_ptr<NewSessionCdmPromise> promise( + new CdmCallbackPromise<std::string>( base::BindOnce(&ClearKeyCdm::OnSessionCreated, base::Unretained(this), promise_id), base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), @@ -432,8 +399,8 @@ DCHECK(allow_persistent_state_); std::string web_session_str(session_id, session_id_length); - std::unique_ptr<media::NewSessionCdmPromise> promise( - new media::CdmCallbackPromise<std::string>( + std::unique_ptr<NewSessionCdmPromise> promise( + new CdmCallbackPromise<std::string>( base::BindOnce(&ClearKeyCdm::OnSessionCreated, base::Unretained(this), promise_id), base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), @@ -451,12 +418,11 @@ std::string web_session_str(session_id, session_id_length); std::vector<uint8_t> response_vector(response, response + response_size); - std::unique_ptr<media::SimpleCdmPromise> promise( - new media::CdmCallbackPromise<>( - base::BindOnce(&ClearKeyCdm::OnUpdateSuccess, base::Unretained(this), - promise_id, web_session_str), - base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), - promise_id))); + std::unique_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( + base::BindOnce(&ClearKeyCdm::OnUpdateSuccess, base::Unretained(this), + promise_id, web_session_str), + base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), + promise_id))); cdm_->UpdateSession(session_id, response_vector, std::move(promise)); } @@ -507,12 +473,11 @@ DVLOG(1) << __func__; std::string web_session_str(session_id, session_id_length); - std::unique_ptr<media::SimpleCdmPromise> promise( - new media::CdmCallbackPromise<>( - base::BindOnce(&ClearKeyCdm::OnPromiseResolved, - base::Unretained(this), promise_id), - base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), - promise_id))); + std::unique_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( + base::BindOnce(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), + promise_id), + base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), + promise_id))); cdm_->CloseSession(std::move(web_session_str), std::move(promise)); } @@ -522,12 +487,11 @@ DVLOG(1) << __func__; std::string web_session_str(session_id, session_id_length); - std::unique_ptr<media::SimpleCdmPromise> promise( - new media::CdmCallbackPromise<>( - base::BindOnce(&ClearKeyCdm::OnPromiseResolved, - base::Unretained(this), promise_id), - base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), - promise_id))); + std::unique_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( + base::BindOnce(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), + promise_id), + base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), + promise_id))); cdm_->RemoveSession(std::move(web_session_str), std::move(promise)); } @@ -535,12 +499,11 @@ const uint8_t* server_certificate_data, uint32_t server_certificate_data_size) { DVLOG(1) << __func__; - std::unique_ptr<media::SimpleCdmPromise> promise( - new media::CdmCallbackPromise<>( - base::BindOnce(&ClearKeyCdm::OnPromiseResolved, - base::Unretained(this), promise_id), - base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), - promise_id))); + std::unique_ptr<SimpleCdmPromise> promise(new CdmCallbackPromise<>( + base::BindOnce(&ClearKeyCdm::OnPromiseResolved, base::Unretained(this), + promise_id), + base::BindOnce(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), + promise_id))); cdm_->SetServerCertificate( std::vector<uint8_t>( server_certificate_data, @@ -573,9 +536,9 @@ ScheduleNextTimer(); } -static void CopyDecryptResults(media::Decryptor::Status* status_copy, +static void CopyDecryptResults(Decryptor::Status* status_copy, scoped_refptr<DecoderBuffer>* buffer_copy, - media::Decryptor::Status status, + Decryptor::Status status, scoped_refptr<DecoderBuffer> buffer) { *status_copy = status; *buffer_copy = std::move(buffer); @@ -605,13 +568,14 @@ cdm::Status ClearKeyCdm::InitializeAudioDecoder( const cdm::AudioDecoderConfig_2& audio_decoder_config) { - if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) + if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) { return cdm::kInitializationError; + } #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) if (!audio_decoder_) { audio_decoder_ = - std::make_unique<media::FFmpegCdmAudioDecoder>(cdm_host_proxy_.get()); + std::make_unique<FFmpegCdmAudioDecoder>(cdm_host_proxy_.get()); } if (!audio_decoder_->Initialize(audio_decoder_config)) @@ -630,8 +594,9 @@ cdm::Status ClearKeyCdm::InitializeVideoDecoder( const cdm::VideoDecoderConfig_3& video_decoder_config) { - if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) + if (key_system_ == kExternalClearKeyDecryptOnlyKeySystem) { return cdm::kInitializationError; + } if (!video_decoder_) { video_decoder_ = @@ -772,20 +737,22 @@ } // Callback is called synchronously, so we can use variables on the stack. - media::Decryptor::Status status = media::Decryptor::kError; + Decryptor::Status status = Decryptor::kError; // The CDM does not care what the stream type is. Pass kVideo // for both audio and video decryption. cdm_->GetCdmContext()->GetDecryptor()->Decrypt( - media::Decryptor::kVideo, std::move(buffer), + Decryptor::kVideo, std::move(buffer), base::BindOnce(&CopyDecryptResults, &status, decrypted_buffer)); - if (status == media::Decryptor::kError) + if (status == Decryptor::kError) { return cdm::kDecryptError; + } - if (status == media::Decryptor::kNoKey) + if (status == Decryptor::kNoKey) { return cdm::kNoKey; + } - DCHECK_EQ(status, media::Decryptor::kSuccess); + DCHECK_EQ(status, Decryptor::kSuccess); return cdm::kSuccess; }
diff --git a/media/cdm/win/media_foundation_cdm_factory_unittest.cc b/media/cdm/win/media_foundation_cdm_factory_unittest.cc index 9d3dbdc..1429ee2c 100644 --- a/media/cdm/win/media_foundation_cdm_factory_unittest.cc +++ b/media/cdm/win/media_foundation_cdm_factory_unittest.cc
@@ -15,6 +15,7 @@ #include "media/base/test_helpers.h" #include "media/base/win/mf_helpers.h" #include "media/base/win/mf_mocks.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/mock_helpers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -31,7 +32,6 @@ namespace media { -const char kClearKeyKeySystem[] = "org.w3.clearkey"; const CdmConfig kClearKeyHardwareSecureCdmConfig = {kClearKeyKeySystem, true, true, true};
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index db794bf..86af44e 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -100,6 +100,8 @@ CodecInfo::HISTOGRAM_VORBIS}; static const CodecInfo kOpusCodecInfo = {"opus", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_OPUS}; +static const CodecInfo kOpusCodecInfo2 = {"Opus", CodecInfo::AUDIO, nullptr, + CodecInfo::HISTOGRAM_OPUS}; #if BUILDFLAG(ENABLE_AV1_DECODER) // Note: Validation of the codec string is handled by the caller. @@ -109,14 +111,14 @@ static const CodecInfo* const kVideoWebMCodecs[] = { &kVP8CodecInfo, &kLegacyVP9CodecInfo, &kVP9CodecInfo, &kVorbisCodecInfo, - &kOpusCodecInfo, + &kOpusCodecInfo, &kOpusCodecInfo2, #if BUILDFLAG(ENABLE_AV1_DECODER) &kAV1CodecInfo, #endif nullptr}; -static const CodecInfo* const kAudioWebMCodecs[] = {&kVorbisCodecInfo, - &kOpusCodecInfo, nullptr}; +static const CodecInfo* const kAudioWebMCodecs[] = { + &kVorbisCodecInfo, &kOpusCodecInfo, &kOpusCodecInfo2, nullptr}; static StreamParser* BuildWebMParser(base::span<const std::string> codecs, MediaLog* media_log) { @@ -262,9 +264,13 @@ "vp09.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_VP9}; static const CodecInfo kMPEG4FLACCodecInfo = {"flac", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_FLAC}; +static const CodecInfo kMPEG4FLACCodecInfo2 = { + "fLaC", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_FLAC}; static const CodecInfo* const kVideoMP4Codecs[] = {&kMPEG4FLACCodecInfo, + &kMPEG4FLACCodecInfo2, &kOpusCodecInfo, + &kOpusCodecInfo2, &kMPEG4VP09CodecInfo, #if BUILDFLAG(USE_PROPRIETARY_CODECS) &kH264AVC1CodecInfo, @@ -294,7 +300,9 @@ nullptr}; static const CodecInfo* const kAudioMP4Codecs[] = {&kMPEG4FLACCodecInfo, + &kMPEG4FLACCodecInfo2, &kOpusCodecInfo, + &kOpusCodecInfo2, #if BUILDFLAG(USE_PROPRIETARY_CODECS) &kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, @@ -335,7 +343,8 @@ bool has_flac = false; for (const auto& codec_id : codecs) { - if (base::MatchPattern(codec_id, kMPEG4FLACCodecInfo.pattern)) { + if (base::MatchPattern(codec_id, kMPEG4FLACCodecInfo.pattern) || + base::MatchPattern(codec_id, kMPEG4FLACCodecInfo2.pattern)) { has_flac = true; #if BUILDFLAG(USE_PROPRIETARY_CODECS) } else if (base::MatchPattern(codec_id, kMPEG2AACLCCodecInfo.pattern)) {
diff --git a/media/gpu/chromeos/image_processor_test.cc b/media/gpu/chromeos/image_processor_test.cc index 814ceb7..73d8555 100644 --- a/media/gpu/chromeos/image_processor_test.cc +++ b/media/gpu/chromeos/image_processor_test.cc
@@ -39,6 +39,11 @@ #include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_surface.h" +#include "ui/gl/gl_utils.h" +#include "ui/gl/init/gl_factory.h" #include "ui/gl/test/gl_surface_test_support.h" #define MM21_TILE_WIDTH 32 @@ -148,6 +153,31 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(USE_V4L2_CODEC) +bool SupportsNecessaryGLExtension() { + bool ret; + + scoped_refptr<gl::GLSurface> gl_surface = + gl::init::CreateOffscreenGLSurface(gl::GetDefaultDisplay(), gfx::Size()); + if (!gl_surface) { + LOG(ERROR) << "Error creating GL surface"; + return false; + } + scoped_refptr<gl::GLContext> gl_context = gl::init::CreateGLContext( + nullptr, gl_surface.get(), gl::GLContextAttribs()); + if (!gl_context) { + LOG(ERROR) << "Error creating GL context"; + return false; + } + if (!gl_context->MakeCurrent(gl_surface.get())) { + LOG(ERROR) << "Error making GL context current"; + return false; + } + ret = gl_context->HasExtension("GL_EXT_YUV_target"); + gl_context->ReleaseCurrent(gl_surface.get()); + + return ret; +} + scoped_refptr<VideoFrame> CreateNV12Frame(const gfx::Size& size, VideoFrame::StorageType type) { const gfx::Rect visible_rect(size); @@ -562,6 +592,10 @@ gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), /*fallback_to_software_gl=*/false); + if (!SupportsNecessaryGLExtension()) { + GTEST_SKIP() << "Skipping GL Backend test, unsupported platform."; + } + constexpr gfx::Size kTestImageSize(1920, 1088); constexpr gfx::Rect kTestImageVisibleRect(kTestImageSize); const ImageProcessor::PixelLayoutCandidate candidate = {Fourcc(Fourcc::MM21),
diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc index e69a35d..e57c004 100644 --- a/media/gpu/v4l2/v4l2_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_video_decoder.cc
@@ -113,8 +113,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); VLOGF(2); - base::PlatformThread::SetName("V4L2VideoDecoderThread"); - weak_this_for_polling_ = weak_this_for_polling_factory_.GetWeakPtr(); }
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc index 1989c66..a456462 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -289,6 +289,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_); TRACE_EVENT0("media,gpu", "V4L2VEA::InitializeTask"); + // Set kInitialized here so that NotifyError() is invoked from here. + encoder_state_ = kInitialized; + native_input_mode_ = config.storage_type.value_or(Config::StorageType::kShmem) == Config::StorageType::kGpuMemoryBuffer; @@ -350,7 +353,6 @@ return; } - encoder_state_ = kInitialized; uint32_t bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; switch (config.bitrate.mode()) { case Bitrate::Mode::kConstant:
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h index 1e9235a0..cf551529 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -106,7 +106,8 @@ // Internal state of the encoder. enum State { kUninitialized, // Initialize() not yet called. - kInitialized, // Initialize() returned true; ready to start encoding. + kInitialized, // Initialize() returned true. The encoding is ready after + // InitializeTask() completes successfully. kEncoding, // Encoding frames. kFlushing, // Flushing frames. kError, // Error in encoder state.
diff --git a/media/gpu/vaapi/test/av1_decoder.cc b/media/gpu/vaapi/test/av1_decoder.cc index a4d87fa..1258346 100644 --- a/media/gpu/vaapi/test/av1_decoder.cc +++ b/media/gpu/vaapi/test/av1_decoder.cc
@@ -663,8 +663,11 @@ *va_device_, new_profile, GetFormatForColorConfig(color_config)); } - ref_frames_.clear(); - display_surfaces_.clear(); + for (auto& frame : ref_frames_) + frame.reset(); + + for (auto& display_surface : display_surfaces_) + display_surface.reset(); const gfx::Size new_frame_size( base::strict_cast<int>(current_sequence_header_->max_frame_width),
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc index f7f6ded..5ad5399 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
@@ -120,10 +120,11 @@ VideoBitrateAllocation CreateBitrateAllocationWithActiveLayers( const VideoBitrateAllocation& bitrate_allocation, - const std::vector<size_t>& active_layers) { + const std::vector<size_t>& active_layers, + size_t num_temporal_layers) { VideoBitrateAllocation new_bitrate_allocation; for (size_t si : active_layers) { - for (size_t ti = 0; ti < VideoBitrateAllocation::kMaxTemporalLayers; ++ti) { + for (size_t ti = 0; ti < num_temporal_layers; ++ti) { const uint32_t bps = bitrate_allocation.GetBitrateBps(si, ti); new_bitrate_allocation.SetBitrate(si, ti, bps); } @@ -603,40 +604,60 @@ InitializeVP9VaapiVideoEncoderDelegate(num_spatial_layers, num_temporal_layers); - const std::vector<std::vector<size_t>> kActivateExercise[2] = { + struct ActivationQuery { + size_t num_temporal_layers; + std::vector<size_t> active_layers; + }; + std::vector<ActivationQuery> kQueries[2] = { { // Two spatial layers. - {0}, // Deactivate the top layer. - {0, 1}, // Activate the top layer. - {1}, // Deactivate the bottom layer. - {0, 1}, // Activate the bottom layer. + {num_temporal_layers, {0}}, // Deactivate the top layer. + {num_temporal_layers, {0, 1}}, // Activate the top layer. + {num_temporal_layers, {1}}, // Deactivate the bottom layer. + {num_temporal_layers, {0, 1}}, // Activate the bottom layer. + {1, {0}}, // L1T1 + {3, {0, 1}}, // L2T3 + {1, {1}}, // L1T1 + {3, {0}}, // L1T3 + {2, {0, 1}}, // L2T2 }, { // Three spatial layers. - {0, 1}, // Deactivate the top layer. - {1}, // Deactivate the bottom layer. - {0}, // Activate the bottom layer and deactivate the top two layers. - {1, - 2}, // Activate the top two layers and deactivate the bottom layer. - {0, 1, 2}, // Activate the bottom layer. - {2}, // Deactivate the bottom two layers. - {0, 1, 2}, // Activate the bottom two layers. + {num_temporal_layers, {0, 1}}, // Deactivate the top layer. + {num_temporal_layers, {1}}, // Deactivate the bottom layer. + {num_temporal_layers, {0}}, // Activate the bottom layer and + // deactivate the top two layers. + {num_temporal_layers, {1, 2}}, // Activate the top two layers and + // deactivate the bottom layer. + {num_temporal_layers, {0, 1, 2}}, // Activate the bottom layer. + {num_temporal_layers, {2}}, // Deactivate the bottom two layers. + {num_temporal_layers, {0, 1, 2}}, // Activate the bottom two layers. + {3, {1}}, // L1T3 + {3, {0, 1, 2}}, // L3T3 + {2, {0, 1}}, // L2T2 + {1, {0, 1}}, // L2T1 + {1, {0}}, // L1T1 + {1, {0, 1, 2}}, // L3T1 }, }; + // Allocate a default bitrate allocation with the maximum temporal layers so + // that it has non-zero bitrate up to the maximum supported temporal layers. const VideoBitrateAllocation kDefaultBitrateAllocation = AllocateDefaultBitrateForTesting( - num_spatial_layers, num_temporal_layers, + num_spatial_layers, VP9SVCLayers::kMaxSupportedTemporalLayers, kDefaultVideoEncodeAcceleratorConfig.bitrate); const std::vector<gfx::Size> kDefaultSpatialLayers = GetDefaultSpatialLayerResolutions(num_spatial_layers); const uint32_t kFramerate = *kDefaultVideoEncodeAcceleratorConfig.initial_framerate; - for (auto& active_layers : kActivateExercise[num_spatial_layers - 2]) { + for (const auto& query : kQueries[num_spatial_layers - 2]) { + const auto& active_layers = query.active_layers; const VideoBitrateAllocation bitrate_allocation = CreateBitrateAllocationWithActiveLayers(kDefaultBitrateAllocation, - active_layers); + query.active_layers, + query.num_temporal_layers); std::vector<gfx::Size> spatial_layer_resolutions; for (size_t active_sid : active_layers) spatial_layer_resolutions.emplace_back(kDefaultSpatialLayers[active_sid]); @@ -646,7 +667,7 @@ UpdateRatesAndEncode(bitrate_allocation, kFramerate, /*valid_rates_request=*/true, /*is_key_pic=*/true, spatial_layer_resolutions, - num_temporal_layers, + query.num_temporal_layers, /*expected_temporal_layer_id=*/0u); } } @@ -675,22 +696,6 @@ invalid_bitrate_allocations.push_back(bitrate_allocation); } - // Increase the number of temporal layers. - bitrate_allocation = kDefaultBitrateAllocation; - ASSERT_LE(num_temporal_layers + 1, - VideoBitrateAllocation::kMaxTemporalLayers); - for (size_t si = 0; si < num_spatial_layers; ++si) - bitrate_allocation.SetBitrate(si, num_temporal_layers, kBitrate); - invalid_bitrate_allocations.push_back(bitrate_allocation); - - // Decrease the number of temporal layers. - if (num_temporal_layers > 1) { - bitrate_allocation = kDefaultBitrateAllocation; - for (size_t si = 0; si < num_spatial_layers; ++si) - bitrate_allocation.SetBitrate(si, num_temporal_layers - 1, 0u); - invalid_bitrate_allocations.push_back(bitrate_allocation); - } - // Set 0 in the bottom temporal layer. if (num_temporal_layers > 1) { bitrate_allocation = kDefaultBitrateAllocation;
diff --git a/media/gpu/vp9_svc_layers.cc b/media/gpu/vp9_svc_layers.cc index 6b2774c..5f5b3e7 100644 --- a/media/gpu/vp9_svc_layers.cc +++ b/media/gpu/vp9_svc_layers.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "media/gpu/macros.h" #include "media/gpu/vp9_picture.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace media { namespace { @@ -27,6 +28,63 @@ kUpdate = 2, kReferenceAndUpdate = kReference | kUpdate, }; + +const char* GetSVCName(size_t begin_active_layer, + size_t end_active_layer, + size_t num_temporal_layers) { + DCHECK_LT(begin_active_layer, end_active_layer); + size_t num_spatial_layers = end_active_layer - begin_active_layer; + absl::optional<SVCScalabilityMode> svc_mode; + switch (num_spatial_layers) { + case 1: + switch (num_temporal_layers) { + case 1: + return "L1T1"; + case 2: + svc_mode = SVCScalabilityMode::kL1T2; + break; + case 3: + svc_mode = SVCScalabilityMode::kL1T3; + break; + } + break; + case 2: + switch (num_temporal_layers) { + case 1: + svc_mode = SVCScalabilityMode::kL2T1Key; + break; + case 2: + svc_mode = SVCScalabilityMode::kL2T2Key; + break; + case 3: + svc_mode = SVCScalabilityMode::kL2T3Key; + break; + } + break; + case 3: + switch (num_temporal_layers) { + case 1: + svc_mode = SVCScalabilityMode::kL3T1Key; + break; + case 2: + svc_mode = SVCScalabilityMode::kL3T2Key; + break; + case 3: + svc_mode = SVCScalabilityMode::kL3T3Key; + break; + } + break; + } + + if (!svc_mode) { + DVLOGF(1) << "Unexpected SVC config: " + << "begin_active_layer=" << begin_active_layer + << ", end_active_layer=" << end_active_layer + << ", num_temporal_layers=" << num_temporal_layers; + return "INVALID SVC"; + } + return GetScalabilityModeName(*svc_mode); +} } // namespace struct VP9SVCLayers::FrameConfig { @@ -126,7 +184,6 @@ : num_temporal_layers_(spatial_layers[0].num_of_temporal_layers), temporal_layers_reference_pattern_( GetTemporalLayersReferencePattern(num_temporal_layers_)), - pattern_index_(0u), temporal_pattern_size_(temporal_layers_reference_pattern_.size()) { for (const auto spatial_layer : spatial_layers) { spatial_layer_resolutions_.emplace_back( @@ -168,35 +225,49 @@ // encoding. if (spatial_idx_ != 0 && spatial_idx_ != active_spatial_layer_resolutions_.size()) { + DVLOGF(1) + << "MaybeUpdateActiveLayer() is called in non bottom spatial layer"; return false; } size_t begin_active_layer = kMaxSpatialLayers; size_t end_active_layer = spatial_layer_resolutions_.size(); + size_t new_num_temporal_layers = 0; for (size_t sid = 0; sid < spatial_layer_resolutions_.size(); ++sid) { - size_t sum = 0; - for (size_t tid = 0; tid < num_temporal_layers_; ++tid) { + size_t num_active_temporal_layers_of_current_layer = 0; + for (int tid = kMaxSupportedTemporalLayers - 1; tid >= 0; tid--) { const uint32_t tl_bitrate = bitrate_allocation->GetBitrateBps(sid, tid); - // A bitrate of a temporal layer must be zero if the bitrates of lower - // temporal layers are zero, e.g. {0, 0, 100}. - if (tid > 0 && tl_bitrate > 0 && sum == 0) - return false; - // A bitrate of a temporal layer must not be zero if the bitrates of lower - // temporal layers are not zero, e.g. {100, 0, 0}. - if (tid > 0 && tl_bitrate == 0 && sum != 0) - return false; - - sum += static_cast<size_t>(tl_bitrate); + if (tl_bitrate != 0) { + num_active_temporal_layers_of_current_layer = tid + 1; + break; + } } - // Check if the temporal layers larger than |num_temporal_layers_| are zero. - for (size_t tid = num_temporal_layers_; + // Now, |active_num_temporal_layers_| is zero if the current spatial layer + // is deactivated, or the bitrates of the current spatial layer is [X_i] + for (size_t tid = 0; tid < num_active_temporal_layers_of_current_layer; + ++tid) { + const uint32_t tl_bitrate = bitrate_allocation->GetBitrateBps(sid, tid); + // A bitrate of a lower temporal layer than |active_num_temporal_layers| + // must not be zero, e.g. {0, 0, 100}. + if (tl_bitrate == 0) { + DVLOGF(1) << "The bitrate of a lower temporal layer is zero while the " + << "bitrate of an upper temporal layer is non zero"; + return false; + } + } + + // Check if the temporal layers higher than |kMaxSupportedTemporalLayers| + // are zero. + for (size_t tid = kMaxSupportedTemporalLayers; tid < VideoBitrateAllocation::kMaxTemporalLayers; ++tid) { - if (bitrate_allocation->GetBitrateBps(sid, tid) != 0u) + if (bitrate_allocation->GetBitrateBps(sid, tid) != 0u) { + DVLOGF(1) << "Unsupported temporal layers"; return false; + } } - if (sum == 0) { + if (num_active_temporal_layers_of_current_layer == 0) { // This is the first non-active spatial layer in the end side. if (begin_active_layer != kMaxSpatialLayers) { end_active_layer = sid; @@ -205,9 +276,24 @@ // No active spatial layer is found yet. Try the upper spatial layer. continue; } + + // Check if the number of active temporal layers is same among spatial + // layers. + if (new_num_temporal_layers != 0 && + num_active_temporal_layers_of_current_layer != + new_num_temporal_layers) { + DVLOGF(1) << "The invalid active temporal layers: " + << "num_active_temporal_layers_of_current_layer=" + << num_active_temporal_layers_of_current_layer + << ", new_num_temporal_layers=" << new_num_temporal_layers; + return false; + } + // This is the lowest active layer. - if (begin_active_layer == kMaxSpatialLayers) + if (begin_active_layer == kMaxSpatialLayers) { begin_active_layer = sid; + new_num_temporal_layers = num_active_temporal_layers_of_current_layer; + } } // Check if all the bitrates of unsupported temporal and spatial layers are // zero. @@ -220,17 +306,20 @@ } } // No active layer is found. - if (begin_active_layer == kMaxSpatialLayers) + if (begin_active_layer == kMaxSpatialLayers) { + DVLOGF(1) << "No active spatial layers"; return false; + } - DCHECK_LT(begin_active_layer_, end_active_layer_); - DCHECK_LE(end_active_layer_ - begin_active_layer_, + DCHECK_NE(new_num_temporal_layers, 0u); + DCHECK_LT(begin_active_layer, end_active_layer); + DCHECK_LE(end_active_layer - begin_active_layer, spatial_layer_resolutions_.size()); // Remove non active spatial layer bitrate if |begin_active_layer| > 0. if (begin_active_layer > 0) { for (size_t sid = begin_active_layer; sid < end_active_layer; ++sid) { - for (size_t tid = 0; tid < num_temporal_layers_; ++tid) { + for (size_t tid = 0; tid < new_num_temporal_layers; ++tid) { uint32_t bitrate = bitrate_allocation->GetBitrateBps(sid, tid); bitrate_allocation->SetBitrate(sid - begin_active_layer, tid, bitrate); bitrate_allocation->SetBitrate(sid, tid, 0u); @@ -241,7 +330,15 @@ // Reset SVC parameters and force to produce key frame if active layer // changed. if (begin_active_layer != begin_active_layer_ || - end_active_layer != end_active_layer_) { + end_active_layer != end_active_layer_ || + new_num_temporal_layers != num_temporal_layers_) { + DVLOGF(2) << "SVC structure is changed from " + << GetSVCName(begin_active_layer_, end_active_layer_, + num_temporal_layers_) + << " to " + << GetSVCName(begin_active_layer, end_active_layer, + new_num_temporal_layers); + // Update the stored active layer range. begin_active_layer_ = begin_active_layer; end_active_layer_ = end_active_layer; @@ -249,8 +346,17 @@ spatial_layer_resolutions_.begin() + begin_active_layer, spatial_layer_resolutions_.begin() + end_active_layer}; force_key_frame_ = true; - } + // Only updating the number of temporal layers don't have to force keyframe. + // But we produce keyframe in the case to not complex the code, assuming + // updating the number of temporal layers don't often happen. + // If this is not true, we should avoid producing keyframe in this case. + num_temporal_layers_ = new_num_temporal_layers; + temporal_layers_reference_pattern_ = + GetTemporalLayersReferencePattern(num_temporal_layers_); + temporal_pattern_size_ = temporal_layers_reference_pattern_.size(); + // |pattern_index_| is updated to zero in FillUsedRefFramesAndMetadata(). + } return true; }
diff --git a/media/gpu/vp9_svc_layers.h b/media/gpu/vp9_svc_layers.h index a5709c1..350f19a6 100644 --- a/media/gpu/vp9_svc_layers.h +++ b/media/gpu/vp9_svc_layers.h
@@ -19,10 +19,10 @@ struct Vp9Metadata; // This class manages a state of K-SVC encoding up to three spatial and temporal -// layers. This supports activating/deactivating spatial layers while the -// temporal layer sizes must be unchanged. The temporal layer sizes among -// spatial layers must be identical. Temporal layers and spatial layers are -// described in https://tools.ietf.org/html/draft-ietf-payload-vp9-10#section-3. +// layers. This supports activating/deactivating spatial layers and changing the +// number of temporal layers. The temporal layer sizes among spatial layers must +// be identical. Temporal layers and spatial layers are described in +// https://tools.ietf.org/html/draft-ietf-payload-vp9-10#section-3. class MEDIA_GPU_EXPORT VP9SVCLayers { public: struct FrameConfig; @@ -71,16 +71,12 @@ void UpdateRefFramesPatternIndex( const std::vector<uint8_t>& refresh_frame_indices); - // Following variables are configured upon construction, containing the amount - // of temporal layers/spatial layers, the associated temporal layers indices - // and the nature (reference, update, both, none) of each frame in the - // temporal group, respectively. - const size_t num_temporal_layers_; - const std::vector<FrameConfig> temporal_layers_reference_pattern_; + // The variables of handling temporal layers structure. + size_t num_temporal_layers_; + std::vector<FrameConfig> temporal_layers_reference_pattern_; + size_t temporal_pattern_size_; + uint8_t pattern_index_ = 0; - // The current index into the |temporal_layers_reference_pattern_|. - uint8_t pattern_index_; - const size_t temporal_pattern_size_; size_t spatial_idx_ = 0; size_t frame_num_ = 0; bool force_key_frame_ = false;
diff --git a/media/gpu/vp9_svc_layers_unittest.cc b/media/gpu/vp9_svc_layers_unittest.cc index 254d658..86f5c822 100644 --- a/media/gpu/vp9_svc_layers_unittest.cc +++ b/media/gpu/vp9_svc_layers_unittest.cc
@@ -14,6 +14,7 @@ #include "media/gpu/vp9_picture.h" #include "media/gpu/vp9_reference_frame_vector.h" #include "media/video/video_encode_accelerator.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -183,13 +184,15 @@ // This test verifies the bitrate check in MaybeUpdateActiveLayer(). TEST_F(VP9SVCLayersTest, MaybeUpdateActiveLayer) { - constexpr size_t kNumSpatialLayers = 3; - constexpr size_t kNumTemporalLayers = 3; + constexpr size_t kNumSpatialLayers = VP9SVCLayers::kMaxSpatialLayers; + constexpr static size_t kNumTemporalLayers = + VP9SVCLayers::kMaxSupportedTemporalLayers; const std::vector<VP9SVCLayers::SpatialLayer> spatial_layers = GetDefaultSVCLayers(kNumSpatialLayers, kNumTemporalLayers); VP9SVCLayers svc_layers(spatial_layers); + const std::vector<gfx::Size> kSpatialLayerResolutions = + svc_layers.active_spatial_layer_resolutions(); - // Set Default bitrate allocation. uint32_t layer_rate = 1u; VideoBitrateAllocation allocation; for (size_t sid = 0; sid < VideoBitrateAllocation::kMaxSpatialLayers; ++sid) { @@ -198,6 +201,9 @@ allocation.SetBitrate(sid, tid, layer_rate++); } } + // MaybeUpdateActiveLayer() returns false because the given allocation has + // non-zero bitrate at higher layers than |kNumSpatialLayers| and + // |kNumTemporalLayers|. DCHECK_LT(kNumSpatialLayers, VideoBitrateAllocation::kMaxSpatialLayers); DCHECK_LT(kNumTemporalLayers, VideoBitrateAllocation::kMaxTemporalLayers); EXPECT_FALSE(svc_layers.MaybeUpdateActiveLayer(&allocation)); @@ -209,6 +215,8 @@ allocation.SetBitrate(sid, tid, 0u); } } + // MaybeUpdateActiveLayer() returns false because the given allocation has + // non-zero bitrate at higher spatial layers than |kNumSpatialLayers|. EXPECT_FALSE(svc_layers.MaybeUpdateActiveLayer(&allocation)); // Set unsupported spatial layer bitrate to 0. @@ -219,18 +227,24 @@ allocation.SetBitrate(sid, tid, 0u); } } + // L3T3 encoding. EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&allocation)); + EXPECT_EQ(svc_layers.active_spatial_layer_resolutions(), + kSpatialLayerResolutions); + EXPECT_EQ(svc_layers.num_temporal_layers(), kNumTemporalLayers); // Set lower temporal layer bitrate to zero, e.g. {0, 2, 3}. allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/0, 0u); EXPECT_FALSE(svc_layers.MaybeUpdateActiveLayer(&allocation)); - allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/0, 1u); - // Set upper temporal layer bitrate to 0, e.g. {1, 2, 0}. + + // Set the bitrate of top temporal layer in SL2 to 0, e.g. {1, 2, 0}. + // This is invalid because the bitrates of other SL0 and SL1 is not zero. This + // means the number of temporal layers are different among spatial layers. allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/2, 0u); EXPECT_FALSE(svc_layers.MaybeUpdateActiveLayer(&allocation)); - allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/2, 3u); + // Deactivate SL0 and SL1 and verify the new bitrate allocation. constexpr int kNumDeactivatedLowerSpatialLayer = 2; VideoBitrateAllocation new_allocation = allocation; @@ -239,6 +253,9 @@ new_allocation.SetBitrate(sid, tid, 0u); } EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_THAT(svc_layers.active_spatial_layer_resolutions(), + ::testing::ElementsAre(kSpatialLayerResolutions[2])); + EXPECT_EQ(svc_layers.num_temporal_layers(), kNumTemporalLayers); for (size_t sid = 0; sid < kNumSpatialLayers; ++sid) { for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) { if (sid + kNumDeactivatedLowerSpatialLayer < @@ -253,17 +270,89 @@ // Deactivate SL2 and verify the new bitrate allocation. new_allocation = allocation; - constexpr int kNumActiveSpatialLayer = 2; for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) new_allocation.SetBitrate(/*spatial_index=*/2, tid, 0u); EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_THAT(svc_layers.active_spatial_layer_resolutions(), + ::testing::ElementsAre(kSpatialLayerResolutions[0], + kSpatialLayerResolutions[1])); + EXPECT_EQ(svc_layers.num_temporal_layers(), kNumTemporalLayers); for (size_t sid = 0; sid < kNumSpatialLayers; ++sid) { for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) { - if (sid < kNumActiveSpatialLayer) + if (sid < 2) { EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), allocation.GetBitrateBps(sid, tid)); - else + } else { EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), 0u); + } + } + } + // L3T3 encoding. + new_allocation = allocation; + EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_EQ(svc_layers.active_spatial_layer_resolutions(), + kSpatialLayerResolutions); + EXPECT_EQ(svc_layers.num_temporal_layers(), kNumTemporalLayers); + + // L3T3 -> L1T1 by deactivating SL1 and SL2. + new_allocation = VideoBitrateAllocation(); + new_allocation.SetBitrate(/*spatial_index=*/0, /*temporal_index=*/0, 1u); + EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_THAT(svc_layers.active_spatial_layer_resolutions(), + ::testing::ElementsAre(kSpatialLayerResolutions[0])); + EXPECT_EQ(svc_layers.num_temporal_layers(), 1u); + for (size_t sid = 0; sid < kNumSpatialLayers; ++sid) { + for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) { + if (sid == 0 && tid == 0) { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), 1u); + } else { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), 0u); + } + } + } + // L1T1 -> L2T3 by deactivating SL0. + new_allocation = VideoBitrateAllocation(); + for (size_t sid = 1; sid < 3; sid++) { + for (size_t tid = 0; tid < 3; tid++) { + new_allocation.SetBitrate(/*spatial_index=*/sid, /*temporal_index=*/tid, + allocation.GetBitrateBps(sid, tid)); + } + } + EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_THAT(svc_layers.active_spatial_layer_resolutions(), + ::testing::ElementsAre(kSpatialLayerResolutions[1], + kSpatialLayerResolutions[2])); + EXPECT_EQ(svc_layers.num_temporal_layers(), 3u); + for (size_t sid = 0; sid < kNumSpatialLayers; ++sid) { + for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) { + if (sid < 2 && tid < 3) { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), + allocation.GetBitrateBps(sid + 1, tid)); + } else { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), 0u); + } + } + } + // L2T3 -> L3T2 + new_allocation = VideoBitrateAllocation(); + for (size_t sid = 0; sid < 3; sid++) { + for (size_t tid = 0; tid < 2; tid++) { + new_allocation.SetBitrate(/*spatial_index=*/sid, /*temporal_index=*/tid, + allocation.GetBitrateBps(sid, tid)); + } + } + EXPECT_TRUE(svc_layers.MaybeUpdateActiveLayer(&new_allocation)); + EXPECT_EQ(svc_layers.active_spatial_layer_resolutions(), + kSpatialLayerResolutions); + EXPECT_EQ(svc_layers.num_temporal_layers(), 2u); + for (size_t sid = 0; sid < kNumSpatialLayers; ++sid) { + for (size_t tid = 0; tid < kNumTemporalLayers; ++tid) { + if (sid < 3 && tid < 2) { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), + allocation.GetBitrateBps(sid, tid)); + } else { + EXPECT_EQ(new_allocation.GetBitrateBps(sid, tid), 0u); + } } } }
diff --git a/media/mojo/clients/mojo_cdm_unittest.cc b/media/mojo/clients/mojo_cdm_unittest.cc index 5d922db..1ed01d9 100644 --- a/media/mojo/clients/mojo_cdm_unittest.cc +++ b/media/mojo/clients/mojo_cdm_unittest.cc
@@ -17,6 +17,7 @@ #include "media/base/cdm_config.h" #include "media/base/content_decryption_module.h" #include "media/base/mock_filters.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/default_cdm_factory.h" #include "media/mojo/mojom/content_decryption_module.mojom.h" #include "media/mojo/services/mojo_cdm_service.h" @@ -49,8 +50,6 @@ namespace { -const char kClearKeyKeySystem[] = "org.w3.clearkey"; - // Random key ID used to create a session. const uint8_t kKeyId[] = { // base64 equivalent is AQIDBAUGBwgJCgsMDQ4PEA @@ -116,7 +115,7 @@ mojo::Remote<mojom::ContentDecryptionModule> cdm_remote( cdm_receiver_->BindNewPipeAndPassRemote()); - media::CdmConfig cdm_config = {"com.foo.bar", false, false, false}; + CdmConfig cdm_config = {"com.foo.bar", false, false, false}; mojo_cdm_ = base::MakeRefCounted<MojoCdm>( std::move(cdm_remote), std::move(cdm_context), cdm_config, @@ -299,7 +298,7 @@ break; case FAILURE: - promise->reject(media::CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0, + promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0, "Promise rejected"); break; @@ -335,7 +334,7 @@ break; case FAILURE: - promise->reject(media::CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0, + promise->reject(CdmPromise::Exception::NOT_SUPPORTED_ERROR, 0, "Promise rejected"); break;
diff --git a/media/mojo/clients/mojo_renderer_unittest.cc b/media/mojo/clients/mojo_renderer_unittest.cc index fd414876..afb2169 100644 --- a/media/mojo/clients/mojo_renderer_unittest.cc +++ b/media/mojo/clients/mojo_renderer_unittest.cc
@@ -20,6 +20,7 @@ #include "media/base/cdm_context.h" #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/default_cdm_factory.h" #include "media/mojo/clients/mojo_renderer.h" #include "media/mojo/common/media_type_converters.h" @@ -50,7 +51,6 @@ namespace { const int64_t kStartPlayingTimeInMs = 100; -const char kClearKeyKeySystem[] = "org.w3.clearkey"; ACTION_P2(GetMediaTime, start_time, elapsed_timer) { return start_time + elapsed_timer->Elapsed();
diff --git a/media/mojo/mojom/media_types.mojom b/media/mojo/mojom/media_types.mojom index 07524ed..66cfd71 100644 --- a/media/mojo/mojom/media_types.mojom +++ b/media/mojo/mojom/media_types.mojom
@@ -125,8 +125,10 @@ kL1T1, kL1T2, kL1T3, + kL2T1Key, kL2T2Key, kL2T3Key, + kL3T1Key, kL3T2Key, kL3T3Key, };
diff --git a/media/mojo/mojom/media_types_enum_mojom_traits.h b/media/mojo/mojom/media_types_enum_mojom_traits.h index abe632fc..0bed899e 100644 --- a/media/mojo/mojom/media_types_enum_mojom_traits.h +++ b/media/mojo/mojom/media_types_enum_mojom_traits.h
@@ -160,10 +160,14 @@ return media::mojom::SVCScalabilityMode::kL1T2; case media::SVCScalabilityMode::kL1T3: return media::mojom::SVCScalabilityMode::kL1T3; + case media::SVCScalabilityMode::kL2T1Key: + return media::mojom::SVCScalabilityMode::kL2T1Key; case media::SVCScalabilityMode::kL2T2Key: return media::mojom::SVCScalabilityMode::kL2T2Key; case media::SVCScalabilityMode::kL2T3Key: return media::mojom::SVCScalabilityMode::kL2T3Key; + case media::SVCScalabilityMode::kL3T1Key: + return media::mojom::SVCScalabilityMode::kL3T1Key; case media::SVCScalabilityMode::kL3T2Key: return media::mojom::SVCScalabilityMode::kL3T2Key; case media::SVCScalabilityMode::kL3T3Key: @@ -213,12 +217,18 @@ case media::mojom::SVCScalabilityMode::kL1T3: *output = media::SVCScalabilityMode::kL1T3; return true; + case media::mojom::SVCScalabilityMode::kL2T1Key: + *output = media::SVCScalabilityMode::kL2T1Key; + return true; case media::mojom::SVCScalabilityMode::kL2T2Key: *output = media::SVCScalabilityMode::kL2T2Key; return true; case media::mojom::SVCScalabilityMode::kL2T3Key: *output = media::SVCScalabilityMode::kL2T3Key; return true; + case media::mojom::SVCScalabilityMode::kL3T1Key: + *output = media::SVCScalabilityMode::kL3T1Key; + return true; case media::mojom::SVCScalabilityMode::kL3T2Key: *output = media::SVCScalabilityMode::kL3T2Key; return true;
diff --git a/media/mojo/services/cdm_service_unittest.cc b/media/mojo/services/cdm_service_unittest.cc index cb8e83c..8228a64 100644 --- a/media/mojo/services/cdm_service_unittest.cc +++ b/media/mojo/services/cdm_service_unittest.cc
@@ -15,6 +15,7 @@ #include "base/unguessable_token.h" #include "build/build_config.h" #include "media/base/mock_filters.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/cdm/default_cdm_factory.h" #include "media/media_buildflags.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -39,7 +40,6 @@ // MockCdmFactory treats any non-empty key system as valid and the empty key // system as invalid. -const char kValidKeySystem[] = "org.w3.clearkey"; const char kInvalidKeySystem[] = ""; // Needed since MockCdmServiceClient needs to return unique_ptr of CdmFactory. @@ -64,22 +64,22 @@ const raw_ptr<CdmFactory> cdm_factory_; }; -class MockCdmServiceClient : public media::CdmService::Client { +class MockCdmServiceClient : public CdmService::Client { public: explicit MockCdmServiceClient(CdmFactory* cdm_factory) : cdm_factory_(cdm_factory) {} ~MockCdmServiceClient() override = default; - // media::CdmService::Client implementation. + // CdmService::Client implementation. MOCK_METHOD0(EnsureSandboxed, void()); - std::unique_ptr<media::CdmFactory> CreateCdmFactory( + std::unique_ptr<CdmFactory> CreateCdmFactory( mojom::FrameInterfaceFactory* frame_interfaces) override { return std::make_unique<CdmFactoryWrapper>(cdm_factory_); } #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) - void AddCdmHostFilePaths(std::vector<media::CdmHostFilePath>*) override {} + void AddCdmHostFilePaths(std::vector<CdmHostFilePath>*) override {} #endif // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION) private: @@ -157,7 +157,7 @@ private: void OnCdmCreated(bool expected_result, mojo::PendingRemote<mojom::ContentDecryptionModule> remote, - media::mojom::CdmContextPtr cdm_context, + mojom::CdmContextPtr cdm_context, const std::string& error_message) { if (!expected_result) { EXPECT_FALSE(remote); @@ -179,7 +179,7 @@ TEST_F(CdmServiceTest, InitializeCdm_Success) { Initialize(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); } TEST_F(CdmServiceTest, InitializeCdm_InvalidKeySystem) { @@ -189,9 +189,9 @@ TEST_F(CdmServiceTest, DestroyAndRecreateCdm) { Initialize(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); cdm_remote_.reset(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); } // CdmFactory disconnection will cause the service to idle. @@ -199,7 +199,7 @@ Initialize(); auto* service = cdm_service(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); EXPECT_EQ(service->BoundCdmFactorySizeForTesting(), 1u); EXPECT_EQ(service->UnboundCdmFactorySizeForTesting(), 0u); @@ -213,7 +213,7 @@ // Destroy service will destroy the CdmFactory and all CDMs. TEST_F(CdmServiceTest, DestroyCdmService_AfterCdmCreation) { Initialize(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); base::RunLoop run_loop; // Ideally we should not care about order, and should only quit the loop when @@ -234,7 +234,7 @@ mock_cdm_factory_.SetBeforeCreationCB(base::BindRepeating( &CdmServiceTest::DestroyService, base::Unretained(this))); Initialize(); - InitializeCdm(kValidKeySystem, true); + InitializeCdm(kClearKeyKeySystem, true); run_loop.Run(); }
diff --git a/media/mojo/services/media_metrics_provider_unittest.cc b/media/mojo/services/media_metrics_provider_unittest.cc index 9c77c49..3b3fd7d 100644 --- a/media/mojo/services/media_metrics_provider_unittest.cc +++ b/media/mojo/services/media_metrics_provider_unittest.cc
@@ -11,6 +11,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/test_message_loop.h" #include "components/ukm/test_ukm_recorder.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/mojo/services/media_metrics_provider.h" #include "media/mojo/services/watch_time_recorder.h" #include "mojo/public/cpp/bindings/remote.h" @@ -123,7 +124,6 @@ // Now try one with different values and optional parameters set. const std::string kTestOrigin2 = "https://test2.google.com/"; - const std::string kClearKeyKeySystem = "org.w3.clearkey"; const base::TimeDelta kMetadataTime = base::Seconds(1); const base::TimeDelta kFirstFrameTime = base::Seconds(2); const base::TimeDelta kPlayReadyTime = base::Seconds(3);
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc index 8e8901a0..9ec1933 100644 --- a/media/mojo/services/media_service_unittest.cc +++ b/media/mojo/services/media_service_unittest.cc
@@ -17,6 +17,7 @@ #include "media/base/cdm_config.h" #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/media_buildflags.h" #include "media/mojo/buildflags.h" #include "media/mojo/clients/mojo_decryptor.h" @@ -54,7 +55,6 @@ } #if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID) -const char kClearKeyKeySystem[] = "org.w3.clearkey"; const char kInvalidKeySystem[] = "invalid.key.system"; #endif @@ -80,8 +80,7 @@ MOCK_METHOD1(OnAudioConfigChange, void(const AudioDecoderConfig&)); MOCK_METHOD1(OnVideoConfigChange, void(const VideoDecoderConfig&)); MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size& size)); - MOCK_METHOD1(OnStatisticsUpdate, - void(const media::PipelineStatistics& stats)); + MOCK_METHOD1(OnStatisticsUpdate, void(const PipelineStatistics& stats)); MOCK_METHOD1(OnWaiting, void(WaitingReason)); MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration)); MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state)); @@ -94,7 +93,7 @@ // Tests MediaService using TestMojoMediaClient, which supports CDM creation // using DefaultCdmFactory (only supports Clear Key key system), and Renderer -// creation using RendererImplFactory that always create media::RendererImpl. +// creation using RendererImplFactory that always create RendererImpl. class MediaServiceTest : public testing::Test { public: MediaServiceTest() @@ -167,7 +166,7 @@ protected: void OnCdmCreated(bool expected_result, mojo::PendingRemote<mojom::ContentDecryptionModule> remote, - media::mojom::CdmContextPtr cdm_context, + mojom::CdmContextPtr cdm_context, const std::string& error_message) { if (!expected_result) { EXPECT_FALSE(remote);
diff --git a/media/renderers/video_frame_rgba_to_yuva_converter.cc b/media/renderers/video_frame_rgba_to_yuva_converter.cc index c9805bcd..3215cb80 100644 --- a/media/renderers/video_frame_rgba_to_yuva_converter.cc +++ b/media/renderers/video_frame_rgba_to_yuva_converter.cc
@@ -139,7 +139,8 @@ } #endif // BUILDFLAG(IS_WIN) - if (!provider->GrContext()) { + if (!provider->GrContext() || + provider->ContextCapabilities().supports_yuv_rgb_conversion) { SkYUVAInfo yuva_info = VideoFrameYUVMailboxesHolder::VideoFrameGetSkYUVAInfo(dst_video_frame); gpu::Mailbox yuva_mailboxes[SkYUVAInfo::kMaxPlanes];
diff --git a/media/renderers/video_frame_yuv_converter.cc b/media/renderers/video_frame_yuv_converter.cc index 177ecfff..59ab620 100644 --- a/media/renderers/video_frame_yuv_converter.cc +++ b/media/renderers/video_frame_yuv_converter.cc
@@ -127,7 +127,9 @@ if (!holder_) holder_ = std::make_unique<VideoFrameYUVMailboxesHolder>(); - if (raster_context_provider->GrContext()) { + if (raster_context_provider->GrContext() && + !raster_context_provider->ContextCapabilities() + .supports_yuv_rgb_conversion) { return ConvertFromVideoFrameYUVWithGrContext( video_frame, raster_context_provider, dest_mailbox_holder, gr_params.value_or(GrParams()));
diff --git a/mojo/core/broker_posix.cc b/mojo/core/broker_posix.cc index 0699706..96cdf72 100644 --- a/mojo/core/broker_posix.cc +++ b/mojo/core/broker_posix.cc
@@ -132,7 +132,7 @@ if (!GetBrokerMessageData(message.get(), &data)) return base::WritableSharedMemoryRegion(); absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(data->guid_high, data->guid_low); + base::UnguessableToken::Deserialize(data->guid_high, data->guid_low); if (!guid.has_value()) { return base::WritableSharedMemoryRegion(); }
diff --git a/mojo/core/broker_win.cc b/mojo/core/broker_win.cc index ffb07bd..f9e95020 100644 --- a/mojo/core/broker_win.cc +++ b/mojo/core/broker_win.cc
@@ -151,7 +151,7 @@ if (!GetBrokerMessageData(response.get(), &data)) return base::WritableSharedMemoryRegion(); absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(data->guid_high, data->guid_low); + base::UnguessableToken::Deserialize(data->guid_high, data->guid_low); if (!guid.has_value()) { return base::WritableSharedMemoryRegion(); }
diff --git a/mojo/core/data_pipe_consumer_dispatcher.cc b/mojo/core/data_pipe_consumer_dispatcher.cc index d035540..ba0e8eed 100644 --- a/mojo/core/data_pipe_consumer_dispatcher.cc +++ b/mojo/core/data_pipe_consumer_dispatcher.cc
@@ -391,8 +391,8 @@ } absl::optional<base::UnguessableToken> buffer_guid = - base::UnguessableToken::Deserialize2(state->buffer_guid_high, - state->buffer_guid_low); + base::UnguessableToken::Deserialize(state->buffer_guid_high, + state->buffer_guid_low); if (!buffer_guid.has_value()) { AssertNotExtractingHandlesFromMessage(); return nullptr;
diff --git a/mojo/core/data_pipe_producer_dispatcher.cc b/mojo/core/data_pipe_producer_dispatcher.cc index 2e8abc1..1a54b1a 100644 --- a/mojo/core/data_pipe_producer_dispatcher.cc +++ b/mojo/core/data_pipe_producer_dispatcher.cc
@@ -352,8 +352,8 @@ } absl::optional<base::UnguessableToken> buffer_guid = - base::UnguessableToken::Deserialize2(state->buffer_guid_high, - state->buffer_guid_low); + base::UnguessableToken::Deserialize(state->buffer_guid_high, + state->buffer_guid_low); if (!buffer_guid.has_value()) { AssertNotExtractingHandlesFromMessage(); return nullptr;
diff --git a/mojo/core/ipcz_driver/shared_buffer.cc b/mojo/core/ipcz_driver/shared_buffer.cc index 24267ce6..1515564 100644 --- a/mojo/core/ipcz_driver/shared_buffer.cc +++ b/mojo/core/ipcz_driver/shared_buffer.cc
@@ -133,7 +133,7 @@ } absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(mojo_guid.high, mojo_guid.low); + base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low); if (!guid.has_value()) { return nullptr; } @@ -251,7 +251,7 @@ } absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(header.guid_high, header.guid_low); + base::UnguessableToken::Deserialize(header.guid_high, header.guid_low); if (!guid.has_value()) { return nullptr; }
diff --git a/mojo/core/platform_wrapper_unittest.cc b/mojo/core/platform_wrapper_unittest.cc index 607814a..72ee50c 100644 --- a/mojo/core/platform_wrapper_unittest.cc +++ b/mojo/core/platform_wrapper_unittest.cc
@@ -192,7 +192,7 @@ auto mode = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe; absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(mojo_guid.high, mojo_guid.low); + base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low); ASSERT_TRUE(guid.has_value()); #if BUILDFLAG(IS_WIN) ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type);
diff --git a/mojo/core/shared_buffer_dispatcher.cc b/mojo/core/shared_buffer_dispatcher.cc index d13da6916..575a992a 100644 --- a/mojo/core/shared_buffer_dispatcher.cc +++ b/mojo/core/shared_buffer_dispatcher.cc
@@ -164,8 +164,8 @@ handles[0] = std::move(platform_handles[0]); absl::optional<base::UnguessableToken> guid = - base::UnguessableToken::Deserialize2(serialized_state->guid_high, - serialized_state->guid_low); + base::UnguessableToken::Deserialize(serialized_state->guid_high, + serialized_state->guid_low); if (!guid.has_value()) { AssertNotExtractingHandlesFromMessage(); return nullptr;
diff --git a/mojo/public/cpp/base/unguessable_token_mojom_traits.cc b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc index d4e9b6f..ba96eeac 100644 --- a/mojo/public/cpp/base/unguessable_token_mojom_traits.cc +++ b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
@@ -18,7 +18,7 @@ // deserialized by the traits should always yield a non-empty token. // If deserialization results in an empty token, the data is malformed. absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return false; }
diff --git a/mojo/public/cpp/platform/platform_handle_internal.h b/mojo/public/cpp/platform/platform_handle_internal.h index 89dc0c8d..5cc7b44 100644 --- a/mojo/public/cpp/platform/platform_handle_internal.h +++ b/mojo/public/cpp/platform/platform_handle_internal.h
@@ -24,7 +24,7 @@ } static absl::optional<base::UnguessableToken> UnmarshalUnguessableToken( const MojoSharedBufferGuid* guid) { - return base::UnguessableToken::Deserialize2(guid->high, guid->low); + return base::UnguessableToken::Deserialize(guid->high, guid->low); } };
diff --git a/mojo/public/js/BUILD.gn b/mojo/public/js/BUILD.gn index fc22638..fcb7779 100644 --- a/mojo/public/js/BUILD.gn +++ b/mojo/public/js/BUILD.gn
@@ -6,7 +6,9 @@ import("//mojo/public/tools/bindings/mojom.gni") import("//third_party/closure_compiler/closure_args.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//third_party/node/node.gni") import("//tools/grit/grit_rule.gni") +import("//ui/webui/webui_features.gni") interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings" @@ -64,6 +66,25 @@ } } +template("minify_file") { + node(target_name) { + script = "//mojo/public/tools/bindings/minify_with_terser.py" + inputs = [ invoker.input ] + outputs = [ invoker.output ] + + args = [ + "--input", + rebase_path(invoker.input, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + ] + + if (defined(invoker.deps)) { + deps = invoker.deps + } + } +} + concatenate_files("generate_mojo_internal_js") { inputs = [ "mojo_internal_preamble.js.part", @@ -80,17 +101,20 @@ output = "interface_support.js" } -js_library("bindings_lite_sources") { - sources = [ - "$target_gen_dir/interface_support.js", - "$target_gen_dir/mojo_internal.js", - "compile_preamble.js", - ] - deps = [ "//mojo/public/interfaces/bindings:bindings_js_library_for_compile" ] - extra_deps = [ - ":generate_interface_support_js", - ":generate_mojo_internal_js", - ] +if (enable_mojom_closure_compile || (is_chromeos_ash && enable_js_type_check)) { + js_library("bindings_lite_sources") { + sources = [ + "$target_gen_dir/interface_support.js", + "$target_gen_dir/mojo_internal.js", + "compile_preamble.js", + ] + deps = + [ "//mojo/public/interfaces/bindings:bindings_js_library_for_compile" ] + extra_deps = [ + ":generate_interface_support_js", + ":generate_mojo_internal_js", + ] + } } # All generated mojom JS modules consume the API defined by this module. The @@ -106,10 +130,10 @@ "bindings_uncompiled_module_export.js.part", ] output = "bindings_uncompiled.js" - deps = [ "//mojo/public/interfaces/bindings:bindings_js_library" ] + deps = [ "//mojo/public/interfaces/bindings:bindings_js__generator" ] } -if (enable_mojom_closure_compile || enable_js_type_check) { +if (enable_mojom_closure_compile || (enable_js_type_check && is_chromeos_ash)) { js_binary("bindings_lite") { outputs = [ "$target_gen_dir/mojo_bindings_lite.js" ] sources = [] @@ -161,10 +185,18 @@ ] } - copy("bindings_module") { - sources = [ "$target_gen_dir/bindings_uncompiled.js" ] - outputs = [ "$target_gen_dir/bindings.js" ] - deps = [ ":bindings_uncompiled_module" ] + if (optimize_webui) { + minify_file("bindings_module") { + input = "$target_gen_dir/bindings_uncompiled.js" + output = "$target_gen_dir/bindings.js" + deps = [ ":bindings_uncompiled_module" ] + } + } else { + copy("bindings_module") { + sources = [ "$target_gen_dir/bindings_uncompiled.js" ] + outputs = [ "$target_gen_dir/bindings.js" ] + deps = [ ":bindings_uncompiled_module" ] + } } }
diff --git a/mojo/public/tools/bindings/minify_with_terser.py b/mojo/public/tools/bindings/minify_with_terser.py new file mode 100755 index 0000000..cefee7a4 --- /dev/null +++ b/mojo/public/tools/bindings/minify_with_terser.py
@@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This utility minifies JS files with terser. +# +# Instance of 'node' has no 'RunNode' member (no-member) +# pylint: disable=no-member + +import argparse +import os +import sys + +_HERE_PATH = os.path.dirname(__file__) +_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..', '..')) +_CWD = os.getcwd() +sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node')) +import node +import node_modules + + +def MinifyFile(input_file, output_file): + node.RunNode([ + node_modules.PathToTerser(), input_file, '--mangle', '--compress', + '--comments', 'false', '--output', output_file + ]) + + +def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('--input', required=True) + parser.add_argument('--output', required=True) + args = parser.parse_args(argv) + + # Delete the output file if it already exists. It may be a sym link to the + # input, because in non-optimized/pre-Terser builds the input file is copied + # to the output location with gn copy(). + out_path = os.path.join(_CWD, args.output) + if (os.path.exists(out_path)): + os.remove(out_path) + + MinifyFile(os.path.join(_CWD, args.input), out_path) + + +if __name__ == '__main__': + main(sys.argv[1:])
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index c2344a41..496934e 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni
@@ -42,7 +42,8 @@ # Enables Closure compilation of generated JS lite bindings. In environments # where compilation is supported, any mojom target "foo" will also have a # corresponding "foo_js_library_for_compile" target generated. - enable_mojom_closure_compile = enable_js_type_check && optimize_webui + enable_mojom_closure_compile = + is_chromeos_ash && enable_js_type_check && optimize_webui # Enables generating javascript fuzzing-related code and the bindings for the # MojoLPM fuzzer targets. Off by default. @@ -1921,10 +1922,16 @@ } } + # Closure libraries are needed for mojom_closure_compile, and when + # js_type_check is enabled on Ash. + generate_closure_libraries = + enable_mojom_closure_compile || (is_chromeos_ash && enable_js_type_check) + # js_library() closure compiler targets, primarily used on ChromeOS. Only # generate these targets if the mojom target is not C++ only and is not using # TypeScript. - if ((!defined(invoker.cpp_only) || !invoker.cpp_only) && + if (generate_closure_libraries && + (!defined(invoker.cpp_only) || !invoker.cpp_only) && !use_typescript_for_target) { js_library_target_name = "${target_name}_js_library" if (sources_list != []) {
diff --git a/net/cert/pki/string_util.cc b/net/cert/pki/string_util.cc index b538766..a7e4687c 100644 --- a/net/cert/pki/string_util.cc +++ b/net/cert/pki/string_util.cc
@@ -88,4 +88,30 @@ return out.str(); } +std::vector<std::string_view> SplitString(std::string_view str, + char split_char) { + std::vector<std::string_view> out; + + if (str.empty()) { + return out; + } + + while (true) { + // Find end of current token + size_t i = str.find(split_char); + + // Add current token + out.push_back(str.substr(0, i)); + + if (i == str.npos) { + // That was the last token + break; + } + // Continue to next + str = str.substr(i + 1); + } + + return out; +} + } // namespace net::string_util
diff --git a/net/cert/pki/string_util.h b/net/cert/pki/string_util.h index 46550f5..1687b088 100644 --- a/net/cert/pki/string_util.h +++ b/net/cert/pki/string_util.h
@@ -8,6 +8,7 @@ #include "net/base/net_export.h" #include <string_view> +#include <vector> namespace net::string_util { @@ -50,6 +51,11 @@ // Returns a decimal string representation of |i|. NET_EXPORT_PRIVATE std::string NumberToDecimalString(int i); +// Splits |str| on |split_char| returning the list of resulting strings. +NET_EXPORT_PRIVATE std::vector<std::string_view> SplitString( + std::string_view str, + char split_char); + } // namespace net::string_util #endif // NET_CERT_PKI_STRING_UTIL_H_
diff --git a/net/cert/pki/string_util_unittest.cc b/net/cert/pki/string_util_unittest.cc index a54b707e3..88b5191d 100644 --- a/net/cert/pki/string_util_unittest.cc +++ b/net/cert/pki/string_util_unittest.cc
@@ -117,6 +117,39 @@ EXPECT_EQ(number, "255"); } +TEST(StringUtilTest, SplitString) { + EXPECT_EQ(net::string_util::SplitString("", ','), + std::vector<std::string_view>()); + + EXPECT_EQ(net::string_util::SplitString("a", ','), + std::vector<std::string_view>({"a"})); + EXPECT_EQ(net::string_util::SplitString("abc", ','), + std::vector<std::string_view>({"abc"})); + + EXPECT_EQ(net::string_util::SplitString(",", ','), + std::vector<std::string_view>({"", ""})); + + EXPECT_EQ(net::string_util::SplitString("a,", ','), + std::vector<std::string_view>({"a", ""})); + EXPECT_EQ(net::string_util::SplitString("abc,", ','), + std::vector<std::string_view>({"abc", ""})); + + EXPECT_EQ(net::string_util::SplitString(",a", ','), + std::vector<std::string_view>({"", "a"})); + EXPECT_EQ(net::string_util::SplitString(",abc", ','), + std::vector<std::string_view>({"", "abc"})); + + EXPECT_EQ(net::string_util::SplitString("a,b", ','), + std::vector<std::string_view>({"a", "b"})); + EXPECT_EQ(net::string_util::SplitString("abc,def", ','), + std::vector<std::string_view>({"abc", "def"})); + + EXPECT_EQ(net::string_util::SplitString("a,,b", ','), + std::vector<std::string_view>({"a", "", "b"})); + EXPECT_EQ(net::string_util::SplitString("abc,,def", ','), + std::vector<std::string_view>({"abc", "", "def"})); +} + } // namespace } // namespace net
diff --git a/net/cert/pki/test_helpers.cc b/net/cert/pki/test_helpers.cc index 8dfa889..cf59748 100644 --- a/net/cert/pki/test_helpers.cc +++ b/net/cert/pki/test_helpers.cc
@@ -81,24 +81,12 @@ } std::vector<std::string_view> SplitString(std::string_view str) { + std::vector<std::string_view> split = string_util::SplitString(str, ','); + std::vector<std::string_view> out; - - while (!str.empty()) { - // Find end of current token - size_t i = str.find(','); - - // Add current token - std::string_view token = str.substr(0, i); - out.push_back(StripString(token)); - - if (i == str.npos) { - // That was the last token - break; - } - // Continue to next - str = str.substr(i + 1); + for (const auto& s : split) { + out.push_back(StripString(s)); } - return out; } @@ -316,6 +304,8 @@ return false; } } else if (GetValue("last_cert_trust: ", line_piece, &value, &has_trust)) { + // TODO(mattm): convert test files to use + // CertificateTrust::FromDebugString strings. if (value == "TRUSTED_ANCHOR") { test->last_cert_trust = CertificateTrust::ForTrustAnchor(); } else if (value == "TRUSTED_ANCHOR_WITH_EXPIRATION") {
diff --git a/net/cert/pki/trust_store.cc b/net/cert/pki/trust_store.cc index cb4b3c9..8d549922 100644 --- a/net/cert/pki/trust_store.cc +++ b/net/cert/pki/trust_store.cc
@@ -4,8 +4,26 @@ #include "net/cert/pki/trust_store.h" +#include "net/cert/pki/string_util.h" + namespace net { +namespace { + +constexpr char kUnspecifiedStr[] = "UNSPECIFIED"; +constexpr char kDistrustedStr[] = "DISTRUSTED"; +constexpr char kTrustedAnchorStr[] = "TRUSTED_ANCHOR"; +constexpr char kTrustedAnchorOrLeafStr[] = "TRUSTED_ANCHOR_OR_LEAF"; +constexpr char kTrustedLeafStr[] = "TRUSTED_LEAF"; + +constexpr char kEnforceAnchorExpiry[] = "enforce_anchor_expiry"; +constexpr char kEnforceAnchorConstraints[] = "enforce_anchor_constraints"; +constexpr char kRequireAnchorBasicConstraints[] = + "require_anchor_basic_constraints"; +constexpr char kRequireLeafSelfsigned[] = "require_leaf_selfsigned"; + +} // namespace + bool CertificateTrust::IsTrustAnchor() const { switch (type) { case CertificateTrustType::DISTRUSTED: @@ -70,36 +88,83 @@ std::string result; switch (type) { case CertificateTrustType::UNSPECIFIED: - result = "UNSPECIFIED"; + result = kUnspecifiedStr; break; case CertificateTrustType::DISTRUSTED: - result = "DISTRUSTED"; + result = kDistrustedStr; break; case CertificateTrustType::TRUSTED_ANCHOR: - result = "TRUSTED_ANCHOR"; + result = kTrustedAnchorStr; break; case CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF: - result = "TRUSTED_ANCHOR_OR_LEAF"; + result = kTrustedAnchorOrLeafStr; break; case CertificateTrustType::TRUSTED_LEAF: - result = "TRUSTED_LEAF"; + result = kTrustedLeafStr; break; } if (enforce_anchor_expiry) { - result += "+enforce_anchor_expiry"; + result += '+'; + result += kEnforceAnchorExpiry; } if (enforce_anchor_constraints) { - result += "+enforce_anchor_constraints"; + result += '+'; + result += kEnforceAnchorConstraints; } if (require_anchor_basic_constraints) { - result += "+require_anchor_basic_constraints"; + result += '+'; + result += kRequireAnchorBasicConstraints; } if (require_leaf_selfsigned) { - result += "+require_leaf_selfsigned"; + result += '+'; + result += kRequireLeafSelfsigned; } return result; } +// static +absl::optional<CertificateTrust> CertificateTrust::FromDebugString( + const std::string& trust_string) { + std::vector<std::string_view> split = + string_util::SplitString(trust_string, '+'); + + if (split.empty()) { + return absl::nullopt; + } + + CertificateTrust trust; + + if (string_util::IsEqualNoCase(split[0], kUnspecifiedStr)) { + trust = CertificateTrust::ForUnspecified(); + } else if (string_util::IsEqualNoCase(split[0], kDistrustedStr)) { + trust = CertificateTrust::ForDistrusted(); + } else if (string_util::IsEqualNoCase(split[0], kTrustedAnchorStr)) { + trust = CertificateTrust::ForTrustAnchor(); + } else if (string_util::IsEqualNoCase(split[0], kTrustedAnchorOrLeafStr)) { + trust = CertificateTrust::ForTrustAnchorOrLeaf(); + } else if (string_util::IsEqualNoCase(split[0], kTrustedLeafStr)) { + trust = CertificateTrust::ForTrustedLeaf(); + } else { + return absl::nullopt; + } + + for (auto i = ++split.begin(); i != split.end(); ++i) { + if (string_util::IsEqualNoCase(*i, kEnforceAnchorExpiry)) { + trust = trust.WithEnforceAnchorExpiry(); + } else if (string_util::IsEqualNoCase(*i, kEnforceAnchorConstraints)) { + trust = trust.WithEnforceAnchorConstraints(); + } else if (string_util::IsEqualNoCase(*i, kRequireAnchorBasicConstraints)) { + trust = trust.WithRequireAnchorBasicConstraints(); + } else if (string_util::IsEqualNoCase(*i, kRequireLeafSelfsigned)) { + trust = trust.WithRequireLeafSelfSigned(); + } else { + return absl::nullopt; + } + } + + return trust; +} + TrustStore::TrustStore() = default; void TrustStore::AsyncGetIssuersOf(const ParsedCertificate* cert,
diff --git a/net/cert/pki/trust_store.h b/net/cert/pki/trust_store.h index caa5d3a4..441f0a0 100644 --- a/net/cert/pki/trust_store.h +++ b/net/cert/pki/trust_store.h
@@ -9,6 +9,7 @@ #include "net/base/net_export.h" #include "net/cert/pki/cert_issuer_source.h" #include "net/cert/pki/parsed_certificate.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -98,6 +99,9 @@ std::string ToDebugString() const; + static absl::optional<CertificateTrust> FromDebugString( + const std::string& trust_string); + // The overall type of trust. CertificateTrustType type = CertificateTrustType::UNSPECIFIED;
diff --git a/net/cert/pki/trust_store_unittest.cc b/net/cert/pki/trust_store_unittest.cc index d81b1f59..d360c28 100644 --- a/net/cert/pki/trust_store_unittest.cc +++ b/net/cert/pki/trust_store_unittest.cc
@@ -67,6 +67,11 @@ std::set<std::string> strings; for (const auto& trust : trust_settings) { strings.insert(trust.ToDebugString()); + + absl::optional<CertificateTrust> round_tripped_trust = + CertificateTrust::FromDebugString(trust.ToDebugString()); + ASSERT_TRUE(round_tripped_trust) << " for " << trust.ToDebugString(); + EXPECT_EQ(trust.ToDebugString(), round_tripped_trust->ToDebugString()); } EXPECT_EQ(strings.size(), trust_settings.size()); }
diff --git a/net/cookies/cookie_partition_key.cc b/net/cookies/cookie_partition_key.cc index 8a1b10027..34707a22 100644 --- a/net/cookies/cookie_partition_key.cc +++ b/net/cookies/cookie_partition_key.cc
@@ -54,7 +54,8 @@ CookiePartitionKey::~CookiePartitionKey() = default; bool CookiePartitionKey::operator==(const CookiePartitionKey& other) const { - return site_ == other.site_ && nonce_ == other.nonce_; + return site_ == other.site_ && nonce_ == other.nonce_ && + from_script_ == other.from_script_; } bool CookiePartitionKey::operator!=(const CookiePartitionKey& other) const {
diff --git a/net/cookies/cookie_partition_key_collection_unittest.cc b/net/cookies/cookie_partition_key_collection_unittest.cc index 29e00470..8c9cd9b1 100644 --- a/net/cookies/cookie_partition_key_collection_unittest.cc +++ b/net/cookies/cookie_partition_key_collection_unittest.cc
@@ -76,6 +76,8 @@ CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com")); const CookiePartitionKey kOtherPartitionKey = CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com")); + const CookiePartitionKey kPartitionKeyNotInCollection = + CookiePartitionKey::FromURLForTesting(GURL("https://foobar.com")); struct TestCase { const CookiePartitionKeyCollection keychain; @@ -91,6 +93,8 @@ // Multiple keys {CookiePartitionKeyCollection({kPartitionKey, kOtherPartitionKey}), kPartitionKey, true}, + {CookiePartitionKeyCollection({kPartitionKey, kOtherPartitionKey}), + kPartitionKeyNotInCollection, false}, // Contains all keys {CookiePartitionKeyCollection::ContainsAll(), kPartitionKey, true}, };
diff --git a/net/cookies/cookie_partition_key_unittest.cc b/net/cookies/cookie_partition_key_unittest.cc index 779a705..8e366f9 100644 --- a/net/cookies/cookie_partition_key_unittest.cc +++ b/net/cookies/cookie_partition_key_unittest.cc
@@ -182,9 +182,6 @@ CookiePartitionKey::FromNetworkIsolationKey( test_case.network_isolation_key); - if (got) - EXPECT_FALSE(got->from_script()); - if (PartitionedCookiesEnabled()) { EXPECT_EQ(test_case.expected, got); } else if (test_case.allow_nonced_partition_keys) { @@ -218,6 +215,30 @@ } } +TEST_P(CookiePartitionKeyTest, FromStorageKeyComponents) { + struct TestCase { + const GURL url; + const absl::optional<base::UnguessableToken> nonce = absl::nullopt; + } test_cases[] = { + {GURL("https://foo.com")}, + {GURL()}, + {GURL("https://foo.com"), base::UnguessableToken::Create()}, + }; + + for (const auto& test_case : test_cases) { + auto want = + CookiePartitionKey::FromURLForTesting(test_case.url, test_case.nonce); + absl::optional<CookiePartitionKey> got = + CookiePartitionKey::FromStorageKeyComponents(want.site(), want.nonce()); + if (PartitionedCookiesEnabled() || + (NoncedPartitionedCookiesEnabled() && test_case.nonce)) { + EXPECT_EQ(got, want); + } else { + EXPECT_FALSE(got); + } + } +} + TEST_P(CookiePartitionKeyTest, FromScript) { auto key = CookiePartitionKey::FromScript(); EXPECT_TRUE(key);
diff --git a/net/cookies/cookie_setting_override.h b/net/cookies/cookie_setting_override.h index a475727f5..24bba57 100644 --- a/net/cookies/cookie_setting_override.h +++ b/net/cookies/cookie_setting_override.h
@@ -17,12 +17,15 @@ // When specified, the user has indicated to force allowing third-party // cookies. kForceThirdPartyByUser = 1, + // When specified, third-party cookies may be allowed based on existence of + // TopLevelStorageAccess grants. + kTopLevelStorageAccessGrantEligible = 2, + kMaxValue = kTopLevelStorageAccessGrantEligible, }; -using CookieSettingOverrides = - base::EnumSet<CookieSettingOverride, - CookieSettingOverride::kNone, - CookieSettingOverride::kForceThirdPartyByUser>; +using CookieSettingOverrides = base::EnumSet<CookieSettingOverride, + CookieSettingOverride::kNone, + CookieSettingOverride::kMaxValue>; } // namespace net
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 1eeb99a..b2608ee 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc
@@ -927,7 +927,7 @@ int rv = GeneratePendingIO(&cb); // The cache destructor will see one pending operation here. - cache_.reset(); + ResetCaches(); if (rv == net::ERR_IO_PENDING) { if (fast || simple_cache_mode_) @@ -1023,7 +1023,7 @@ result.ReleaseEntry()->Close(); // The cache destructor will see one pending operation here. - cache_.reset(); + ResetCaches(); } base::RunLoop().RunUntilIdle(); @@ -1059,7 +1059,7 @@ cache_->CreateEntry("some key", net::HIGHEST, cb.callback()); ASSERT_THAT(result.net_error(), IsError(net::ERR_IO_PENDING)); - cache_.reset(); + ResetCaches(); EXPECT_FALSE(cb.have_result()); } @@ -1099,7 +1099,7 @@ int rv = cache_->DoomEntry("some key", net::HIGHEST, cb.callback()); ASSERT_THAT(rv, IsError(net::ERR_IO_PENDING)); - cache_.reset(); + ResetCaches(); EXPECT_FALSE(cb.have_result()); } @@ -2400,8 +2400,7 @@ ASSERT_EQ(num_entries - 1, actual); } - cache_.reset(); - cache_impl_ = nullptr; + ResetCaches(); ASSERT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, MaxSize(), mask)); success_ = true; @@ -3621,7 +3620,7 @@ disk_cache::StatsItems::value_type hits("Create hit", "0x1"); EXPECT_EQ(1, base::ranges::count(stats, hits)); - cache_.reset(); + ResetCaches(); // Now open the cache and verify that the stats are still there. DisableFirstCleanup(); @@ -4145,7 +4144,7 @@ ASSERT_THAT(CreateEntry("key", &entry), IsOk()); ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false)); entry->Close(); - cache_.reset(); + ResetCaches(); // Check that the |SimpleBackendImpl| does not favor this structure. auto simple_cache = std::make_unique<disk_cache::SimpleBackendImpl>( @@ -4172,7 +4171,7 @@ ASSERT_THAT(CreateEntry("key", &entry), IsOk()); ASSERT_EQ(0, WriteData(entry, 0, 0, buffer.get(), 0, false)); entry->Close(); - cache_.reset(); + ResetCaches(); // Check that the |BackendImpl| does not favor this structure. auto cache = std::make_unique<disk_cache::BackendImpl>( @@ -4306,7 +4305,7 @@ EXPECT_TRUE(entry); disk_cache::ScopedEntryPtr entry_closer(entry); - cache_.reset(); + ResetCaches(); // This test passes if we don't leak memory. } @@ -4426,7 +4425,7 @@ SetSimpleCacheMode(); for (int i = 0; i < 100; ++i) { InitCache(); - cache_.reset(); + ResetCaches(); EXPECT_TRUE(CleanupCacheDir()); } } @@ -4448,7 +4447,7 @@ base::File::FLAG_OPEN | base::File::FLAG_READ); EXPECT_TRUE(cache_dir.Flush()); #endif // BUILDFLAG(IS_POSIX) - cache_.reset(); + ResetCaches(); disk_cache::FlushCacheThreadForTesting(); // The index is now written. Dooming the last entry can't delete a file, @@ -4847,7 +4846,7 @@ InitCache(); std::unique_ptr<disk_cache::Backend::Iterator> iter = cache_->CreateIterator(); - cache_.reset(); + ResetCaches(); EntryResult result = iter->OpenNextEntry(base::DoNothing()); ASSERT_EQ(net::ERR_FAILED, result.net_error()); } @@ -5012,7 +5011,7 @@ }, std::move(cleanup_context))); EXPECT_EQ(net::ERR_IO_PENDING, result.net_error()); - cache_.reset(); + ResetCaches(); // Give CleanupContext a chance to do its thing. RunUntilIdle(); @@ -5158,7 +5157,7 @@ std::move(cleanup_context))); EXPECT_EQ(net::ERR_IO_PENDING, entry_result.net_error()); - cache_.reset(); + ResetCaches(); RunUntilIdle(); EXPECT_TRUE(cleanup_context_ran); @@ -5195,7 +5194,7 @@ ASSERT_EQ(net::OK, result.net_error()); entry = result.ReleaseEntry(); - cache_.reset(); + ResetCaches(); // Entry is still supposed to be operable. This part is needed to see the bug // without a leak checker. @@ -5448,8 +5447,7 @@ entry->Close(); ASSERT_THAT(OpenEntry(kKey, &entry), IsOk()); - cache_.reset(); - simple_cache_impl_ = nullptr; // Hygiene. + ResetCaches(); entry->Doom(); entry->Close();
diff --git a/net/disk_cache/blockfile/block_files.cc b/net/disk_cache/blockfile/block_files.cc index 0f93817..aefc8031 100644 --- a/net/disk_cache/blockfile/block_files.cc +++ b/net/disk_cache/blockfile/block_files.cc
@@ -18,6 +18,7 @@ #include "net/disk_cache/blockfile/file_lock.h" #include "net/disk_cache/blockfile/stress_support.h" #include "net/disk_cache/cache_util.h" +#include "third_party/abseil-cpp/absl/types/optional.h" using base::TimeTicks; @@ -354,18 +355,24 @@ if (deep) file->Write(zero_buffer_.data(), size, offset); - BlockHeader file_header(file); - file_header.DeleteMapBlock(address.start_block(), address.num_blocks()); - file->Flush(); + absl::optional<FileType> type_to_delete; + { + // Block Header can't outlive file's buffer. + BlockHeader file_header(file); + file_header.DeleteMapBlock(address.start_block(), address.num_blocks()); + file->Flush(); - if (!file_header.Header()->num_entries) { - // This file is now empty. Let's try to delete it. - FileType type = Addr::RequiredFileType(file_header.Header()->entry_size); - if (Addr::BlockSizeForFileType(RANKINGS) == - file_header.Header()->entry_size) { - type = RANKINGS; + if (!file_header.Header()->num_entries) { + // This file is now empty. Let's try to delete it. + type_to_delete = Addr::RequiredFileType(file_header.Header()->entry_size); + if (Addr::BlockSizeForFileType(RANKINGS) == + file_header.Header()->entry_size) { + type_to_delete = RANKINGS; + } } - RemoveEmptyFile(type); // Ignore failures. + } + if (type_to_delete.has_value()) { + RemoveEmptyFile(type_to_delete.value()); // Ignore failures. } }
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index 4867ea15..a6e48ac 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc
@@ -102,7 +102,7 @@ ASSERT_THAT(cb.GetResult(rv), IsOk()); cache_impl_->ClearRefCountForTest(); - cache_.reset(); + ResetCaches(); EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, size_, mask_)); CreateBackend(disk_cache::kNoRandom); @@ -338,18 +338,24 @@ void DiskCacheTestWithCache::TearDown() { RunUntilIdle(); - cache_.reset(); - + ResetCaches(); if (!memory_only_ && !simple_cache_mode_ && integrity_) { EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, size_, mask_)); } RunUntilIdle(); - if (simple_cache_mode_ && simple_file_tracker_) + if (simple_cache_mode_ && simple_file_tracker_) { EXPECT_TRUE(simple_file_tracker_->IsEmptyForTesting()); - + } DiskCacheTest::TearDown(); } +void DiskCacheTestWithCache::ResetCaches() { + mem_cache_ = nullptr; + simple_cache_impl_ = nullptr; + cache_impl_ = nullptr; + cache_.reset(); +} + void DiskCacheTestWithCache::InitMemoryCache() { auto cache = std::make_unique<disk_cache::MemBackendImpl>(nullptr); mem_cache_ = cache.get();
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index eead0c3d..dc79d349 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h
@@ -83,6 +83,7 @@ void CreateBackend(uint32_t flags); + void ResetCaches(); void InitCache(); void SimulateCrash(); void SetTestMode();
diff --git a/net/docs/bug-triage.md b/net/docs/bug-triage.md index 61b03842..a77450c 100644 --- a/net/docs/bug-triage.md +++ b/net/docs/bug-triage.md
@@ -142,29 +142,27 @@ ## Management -* Your rotation will appear in Google Calendar as two days. You are expected to - work on it full-time (as best you can) during those calendar days, during your - ordinary working hours. +* Your rotation will appear in Google Calendar for three days, as a full day + event. However you should work on it during normal business hours only. + The bug triage work should be considered P1 during this period, but you + should feel free to work on project work once you triage outstanding issues. -* Google Calendar [google.com_52n2p39ad82hah9v7j26vek830@group.calendar.google.com](https://calendar.google.com/calendar/embed?src=google.com_52n2p39ad82hah9v7j26vek830%40group.calendar.google.com&ctz=America%2FLos_Angeles) +* Google Calendar [c_c76b86b0356db19c1e06879b16d84a2fb7b9747f066b671c46875261c9e7f17a@group.calendar.google.com](https://calendar.google.com/calendar/embed?src=c_c76b86b0356db19c1e06879b16d84a2fb7b9747f066b671c46875261c9e7f17a%40group.calendar.google.com&ctz=Asia%2FTokyo) * Owners for the network bug triage rotation can find instructions on -generating and modifying shifts -[here (internal-only)](https://goto.google.com/pflvb). + generating and modifying shifts +[here (internal-only)](https://goto.google.com/net-triage-setup). * An overview of bug trends can be seen on [Chromium Dashboard](https://chromiumdash.appspot.com/components/Internals/Network?project=Chromium) -* There is also an [internal dashboard with bug trends for Web - Platform](https://goto.google.com/blink-untriaged-by-team) that includes network issues. - -* And another [internal dashboard breaking down the bug trends for the - networking stack by components](https://goto.google.com/chrome-network-untriaged-by-component) - * The issue tracker doesn't track any official mappings between components and OWNERS. This [internal document](https://goto.google.com/kojfj) enumerates - the known owners for subcomponents. + the known owners for subcomponents. Owners information is dynamic, and the + document might become outdated, you can always go to the source, search for + the component in a DIR_METADATA file and look for an OWNERS file in the same, + or parent directory. * [Web Platform Team SLOs](https://docs.google.com/document/d/18ylPve6jd43m8B7Dil6xmS4G9MHL2_DhQon72je-O9o/edit) -* [Web Platform bug triage guidelines](https://docs.google.com/document/d/1JOtp1LS7suqTjMuv41jQFc7aCTR33zJKPoGjKpvVFCA) +* [Web Platform bug triage guidelines](https://docs.google.com/document/d/1JOtp1LS7suqTjMuv41jQFc7aCTR33zJKPoGjKpvVFCA) \ No newline at end of file
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 39d52d3..79fe095 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -170049,7 +170049,6 @@ { "name": "selltoec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "semeia.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sentiment.rest", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "septem.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "serail.biz.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "servant42.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "service-ways.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -175549,7 +175548,6 @@ { "name": "adidasyeezys.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adinaporter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "adityaes.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adjusterpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adminwells.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adorable-home.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -176005,7 +176003,6 @@ { "name": "asianetbroadband.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "askart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "askjan.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "asmpt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aso.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "assai.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "assecuro.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -176197,7 +176194,6 @@ { "name": "bankwithfidelity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bapco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "baptist-health.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "baptist-health.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "barcodelookup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bard-college.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bard-college.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -177312,7 +177308,6 @@ { "name": "coventryobserver.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "coveragent.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "coveteur.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "coviacorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "covidactnow.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "covidservicepoint.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "covidtesthonolulu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -177969,7 +177964,6 @@ { "name": "emakicms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emazzanti.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emberit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "embraco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emccglobal.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emersya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emilysweet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -178038,7 +178032,6 @@ { "name": "equity.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "equitybank.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "erb.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "erdemir.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ergobaby.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ergometrics.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "erhardt-leimer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -178053,7 +178046,6 @@ { "name": "erpid.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ersankaucuk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ertelswi.spdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ertico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eru.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "erzbistum-bamberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "esasafe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -179302,7 +179294,6 @@ { "name": "infarktniki.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "infarmbureau.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "infeedo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "infineon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "infinitelyvirtual.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "infinoe.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "infinum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -179710,7 +179701,6 @@ { "name": "kinoplex.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kiprotect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kiryuu.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "kisters.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kitchenwarehouseltd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kitenation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -180223,7 +180213,6 @@ { "name": "majestic-rp.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "majestic.games", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "majorhifi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "make-my-link-longer.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "makeitsimple.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "maketheconnection.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "makeupshopbynaho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -180514,7 +180503,6 @@ { "name": "minuterice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "minutoseguros.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "miomiojoyeria.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "mip.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mirakl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mirasee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "miroslavholec.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -180524,7 +180512,6 @@ { "name": "misooda.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "missingchildreneurope.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "missionbayresort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "missionfoods.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "missions.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mississaugaelite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mister-auto.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -181393,7 +181380,6 @@ { "name": "patent-zeglarski.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pathfindershirts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pathwaylibrary.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "pathways.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "patkiout.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "patrickdecokere.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "patricklaan.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -181609,7 +181595,6 @@ { "name": "plugshare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "plumperthumbs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "plurilock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "plusnet.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "plusport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pluxml.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pm-22711.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -182755,7 +182740,6 @@ { "name": "solweb.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sompo-intl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sompo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "sonoco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sonomotors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sonraisecurity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "soocial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -183636,7 +183620,6 @@ { "name": "twoseven.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "twosigmaventures.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "twr.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "twt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tx.group", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "txfb-ins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "txtpower.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -183753,7 +183736,6 @@ { "name": "usanamiru.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "usavingsbank.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "uscc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "usda.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "usdirect.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "usdirectory.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "usenetreviewz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -183864,7 +183846,6 @@ { "name": "veteranscrisisline.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vetmedmosul.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "veve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "vfc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vfmseo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vfnm.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vhg.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -184453,7 +184434,6 @@ { "name": "zeilendiebleiben.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zekelman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zeldamods.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "zelis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zenbox.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zenvia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zeoob.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -185819,7 +185799,6 @@ { "name": "fitnesstrainer-website.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fitnessvolt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fitpass.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "fix-boredom.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fixpart.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fizyonetistanbul.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fjournal.lol", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -190377,6 +190356,970 @@ { "name": "zshmvp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ztable.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zuidplein.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "09.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "0x90.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2-faktor-betaling.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "228826.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "234.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2mades.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2mp.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "365886.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "7203.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "740cashbuyers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "86606.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "880557.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "976-tuna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aadhibaat.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "accuracast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "accuracast.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "accuracast.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "accuracast.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "achireland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acorespro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acse.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acupuncturefoundation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "acupuncturefoundation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ad-pack.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ads-kuwait.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aerialworks.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "affect3d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "affinityplus.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ahosenjoni.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aikoly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aipderm.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aipderm.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aipderm.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aipderm.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aipderm.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "airconservicingcapetown.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aitokyolab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ajop.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "akmens.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "akode.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aleksac.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alex-wohl.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alezinhababykids.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aliahmadi.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alphageek.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alvarezbruned.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alyusr.com.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "am-yu.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amagroup.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amaztravail.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amazwerk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ambrosia.cafe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amco-br.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amirhanova-a.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ammoland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "angleline.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anol.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aorgroup.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aova.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aplicaciones.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "apnic.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arasozgun.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arcticpolitics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ariensfamilyfoundation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "armstrongremovals.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "artabrian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ary.photography", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "asianshop.com.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aspjvm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "astilleroslagos.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atmetalwork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atomic-corals.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "attyhub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aurabasketball.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "autohaus-brueggemann.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "autousados.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "axxemble.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "b17turkiye.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bambergerdatenschutz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bammatta.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "banfieldentertowin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bar-rique.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bawanghitamalibanu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bbbb.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bbqblessings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bceaf.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bebr.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "belarusmemorials.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bencheetham.me.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "better-teams.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "betwinner.com.gh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bewaredevapi.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bewfz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bigblockmotors.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bilgisayarprogramlari.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "binaa.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "binnen-buten.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "biocarbonregistry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "biotraxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "birebirvilla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bizcast.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blackdogammunition.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blackdoordc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blacklotusaudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blids.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogbrew.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogbuz.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogclouds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogdiva.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blogext.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blt-avocat-nantes.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bluedaisymedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bluescape.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boardmad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boelsen.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bogolyandras.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bokepsan.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bonkotsua.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "brakebills.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "breizhetho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "brenkman.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "brwn.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bytenews.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "caboleisurerealestate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "canyou.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cartooncollections.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cartoonstock.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "casaoggidomani.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "casino-spelletjes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "catfun-foto.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cccc.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cdf.fyi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cemregulveren.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "certfica4u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chamsocdidong.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "charuga.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cheapestwordpress.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cheeth.am", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cheetham.me.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cheetham.social", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chemeetconference.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chillybin.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chinen-hs41.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chinesewords.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chiniiki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "christianhendrickson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chriswservers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cialismarketimm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cialismarketimm.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cjcanarias.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cloudcastles.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cloudit.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "clubinholiterario.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "coactive.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cocinerosmx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cocinerosmxporelmundo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "coggle.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cogolloelegante.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cohu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "colazxk.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "colombiansuppliers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "combidarlehen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "comedy.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "concept4photography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conferencemanager.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "constructem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cosyneve.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cpc.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "crunchconsult.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cursocomunicacionnoverbal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cyber.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cybercore.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cybermaretique.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cyvault.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d10ses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dabedi.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dachlaeufer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "darrenflemingphotography.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "daxo.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "daymi.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dbautoservice.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dcampusbd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dddd.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deasserstadsloop.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "debarbas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "debesiukas.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "debraj.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "degreesofcomfort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "degrootsteshop.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dein.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dengi.desa.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "desinsectisation-punaise-de-lit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "devserver.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dghyp.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "diariodicucina.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dictionarybook.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "didc.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "digitale-ausleihe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dild.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dingcheng.ah.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "discordjs-japan.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "disermex.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "disruptglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "djprecisionmachine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dominicanmobility.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dongchenyue.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "donhatot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "doorsystemsweden.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dotprime.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drandrewlofman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dreambuilt.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dreamwebmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drivedvv.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drlaserskinsoprano.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drongea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dv-project.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dydesign.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dynastydr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "e-frontier.systems", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "e-lexia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eamrfid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eastmedia.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ebstv.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ect-cpg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eeeb.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eg-localisation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eggel.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ekatavirghost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ekgh.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elk.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elka-holzwerke.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elleaura.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elmoro.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emedpractice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emojikeyboard.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "empoweringdifferences.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emprendimientoyformacion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "engelliblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "envoybrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eov2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "erito.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "esilverstone.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eustomamc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "everycorneroftheworld.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "evidentiauniversity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "examly.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "expertowears.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "extremetreeandlandscape.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ezyfitdoors.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fadhlan.web.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "famousintel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fasab-portcenter.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "festfabriken.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fethtv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "filiotech.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "findingneverlandthemusical.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "firesolutionsinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fivestar.et", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fiwebs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fix-boredom.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flagma.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flickingercenter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flothow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flughafen-stellplatz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fob-china.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fob-india.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fob-iran.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "forgottenho.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "forumsig.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fotoszkolenia.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frandroid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "freight-broker.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fretpal.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frontconcept.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frostedgame.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ftlparksprojects.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fudgeapps.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fudgeapps.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fullhotfilm.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "furtodo.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fusionvr.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "futacockinside.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fuzzspencer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "g0nz0.me.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gabelli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gablesvets.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gaku-nkc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "galton.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "galtonbrands.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "galtonbrands.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gamersgrill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "garethbowker.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gasthausbauernhof.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gavvie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "geekachad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gehrdencarre.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gemik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gepo69.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "getmeloan.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gew.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gewis.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gggg.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gglinka.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gion-ent.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gion.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "giuliano.design", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glamorousgoat.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glamour-co.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glampingbuzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gleisner.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glonee.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "glorycambodia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gmo-cybersecurity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gobugfree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "goethe-gymnasium-stolberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "golitsyn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "goodwishes.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "goondocks.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gospelsmusic.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gost-energo.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "governmentphoneservice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gqhomecare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "grasski.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "grdnlife.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "greenislandgroupny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gretch.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "grfinefoods.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "guilda.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gule.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gustaw.net.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gwinteriors.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hakatemia.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "halcom.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "halukaka.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hanacademy.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "harmreductionwa.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hartslurrypumps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hataybitkisel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hearthandhomebuyers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heidinousiainen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "helpout.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hendersontennislessons.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "henko-consulting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "herniaclinic.com.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hiskill.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hisscentralen.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hisscraft.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hnbyalitim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hondaarabia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hoopweb.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hornbach-holding.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horntec.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horsa.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horsellscouts.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horsellscoutsandguides.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hosentaschenblog.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hotel-leda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hoteldel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "housesinportugal.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hr-tech.shop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hrcigroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "huibrotladen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hummingbird.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hydrolifehottubs.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hyper-network.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "i-cite.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "icsti.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ides.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ifdif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ifrabb.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "igdb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iiii.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ikutin.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ilearningengines.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imedhospital.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imexm.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "incognito.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "informalflowers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "informatique-13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "innosysdelft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "innsaimonitor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inorbit.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "instytutpsychologiibiznesu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "intercop.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "intersolar.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inveny.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "investbeneficios.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ishadow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "islcustomsbrokers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "isvw.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "itk.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ja-youth.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jacek.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jackass-as.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jaga-me.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jameswhite.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jbconsultant.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jdjamescorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jianseng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jinjafx.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jjjj.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jmob.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "joelkoen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jolihi.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jonathan-himmelreich.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "joshbyrne.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jouw-job.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jspartnersinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "juancadc.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "julianestrada.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jumoutinho.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "juneereccentre.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jura-versicherungen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jurat.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "justcall.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kamagramarketim.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kapaci.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "karakafa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kazu123.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "keks.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kellerencompass.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kerautretvian.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kervive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "keyestudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kidm4k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kidsbits.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kingsexyshop.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kini24.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kirche-bamberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kitchenkettle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kitsunes.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kkkkk.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "klaukegear.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "knhchula.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "knowbook.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "koffiekompaan.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kokk.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kokomoislandfiji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kolonie.turystyka.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kozbox.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kroldata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ksrv.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kstdlvr.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kstservice.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ksuu.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kunitomo.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kxc.inc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kyoto-sowa.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "labyrinthinetool.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lalunya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lamaisondufort.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "landingsencicoaqp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "langtonsant.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "larigami.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lasvegasfit.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lexxadata.net.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lgbtqtherapyspace.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "liam-le-may.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lifestylefoodies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lightstands.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linhim.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lion-log.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lions.gr.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ljusfallshammar.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "loansafe.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lollysmalls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lomond.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lonelybitcoin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "loopgolf.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lskgreengroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luckybeantravel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lukas21.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luppa.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luxuryportal.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "madinatech360.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "madmoizelle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "magieshop.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "make-my-link-longer.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "makemypost.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mamastyle.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mamufeeds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mangumsinc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "manychat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marinpet.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marketcrypto.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "maroochydorecitycentre.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mashrmail.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matthiaswillemsen.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mattwill.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mbpskill.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mcbbs.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "medbrief-vanity.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mediagus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "medical-instinct.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "medicalhelp.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "meffrepatrimoine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mehlogy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mein-es1.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "memarbash.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mensvanilla-magazine.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "metalgie.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mgateamtm.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mgcs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mhi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "michaelliunsky.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mildlysuspicio.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "milvilla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minebbs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mingyannet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minhtuongcomputer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minilu.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minweb.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mira.systems", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mirijiceramica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mizon.com.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mmasportsscienceindia.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mob-tok-shop.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mobcsp.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "moivao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "momtits.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "monsterlinkmarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mortgagesbyharman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motion504.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motorbiketenerife.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motum.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motumblekinge.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motumport.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "motumskane.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mrbeardcbd.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "muddy-bugs.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "musicarenagh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "musterionsec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mvn.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mycase.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mydlonline.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myhelo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mynewsinc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myserviceportal.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "n15.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nagradne-igre.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nahfe.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nakajima-kawara.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nalwin.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nbc.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "neatsvor.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "neatsvor.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "neawth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nesfb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nestlanddesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nettikasino.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "netvlies.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "netzpolitik.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newcoly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newoho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsbes.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsclue.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsdiva.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newseon.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newseue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsfiber.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsgenix.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsguyz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsiva.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newslia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newslookup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsmacro.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsmyth.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newspriest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsprix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsreach.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newswired.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newzlight.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newzlyup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nexiodev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nexiodevopslocal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nexiopaydevopslocal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nickwasused.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nipoafricaeng.co.tz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnc.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnc.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnc.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnc.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnnn.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nnnnn.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nodepoet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noestema.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noid.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noid.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nomadstays.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nonverbalcommunicationcertificate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nordiskhiss.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nordiskhissvarmland.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "northamericantrack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ntdf.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ntt-buses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nullvoid.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "numerama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nyliveauctions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nynadynasir.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nynadynasir.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "o11y.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "observability.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "off-gridodyssey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "offbeatbits.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oftransfer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ogpotterystudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ohako-inc.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ohaquiemcasa.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ohmymalware.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "okis.win", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oleg.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "omnidigital.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onedirectionit.com.bd", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onefestivaltower.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onehealthbehaviors.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onemansworkshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "onsweb.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oooo.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "opalys.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "openintel.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "optimization-online.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "orangerosa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "orbo.org.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ordinals.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ortahisarsigorta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ortiatuttogas.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oumlaut.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oxpow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "oyunshell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paaseiland.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "patrina-bukoting.my.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "peleti.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pepitadinamitastudios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "perevod-tekst-pesni.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "perigon.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pestprescription.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "peterslavik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "petfare.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pfandbriefbank.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pff.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ph1worlddevelopers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "phonebook.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "phyi.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pieropuschiavo.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pilot-gps.africa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pinnacletrailers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pinyonpass.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pinyonpass.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "piped.video", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pirate-proxy.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pisk.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "play4apk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "plov.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "plumber-in-fourways.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "poopa.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "portservice.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ppppp.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prefereal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "presscities.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "preussner-grafik-design.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prikaznoparty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "princewen.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "principalam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prizkod.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "problemshared.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "profeinnova.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "propertysex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proscore-vr2005-1plc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "protteapapelaria.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "provide-vr2003-1plc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "provide-vr2004-1plc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "provide-vr2006-1plc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proxy-bay.cam", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prpr.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prudenceandthecrow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ptrdata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qaq.gay", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qimingbu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qinglingyu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qnected.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "quantum.gl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "quicklyclosure.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "radarbogor.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raleighboneandjoint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raleighmedicalgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raleighpsych.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rangeforce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rangeforce.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ravenrepublic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rcdevs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "realtyfeature.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rebaltica.lv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "recetasdelospaises.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "redfox-media.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "redkite.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "remotebudget.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rencbrain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "renegadeexploration.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reportband.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "revilka.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "revolution-mining.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ricassiocosta.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ridgidgear.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "riscoscommunity.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "risesmartdev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rishav.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "risilience.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rmbs.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "roboquantico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "roomme.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "roquesevilla.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rosehishop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "routedlogic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "royalchess100.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rsblake.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rusa.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ruthmarques.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "s9h.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sageseeds.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sainama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sanalsergi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sanayigazetesi.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "santacruzgalapagoscruise.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "santosmanjares.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sapphireblinds.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "savrp.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sayhicp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scejournals.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schmiedecorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "school-korfbal.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scmhandling.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scooply.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scopeglass.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scpidcard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scytl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "selangdi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "semicolon.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sendflowers.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "senibongcove.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "senibonggolfclub.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seresponsable.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "setch.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shadowsocks.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shamiehlaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shcserv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shimmo.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shipgoldchandler.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shivamautozone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shivamnexa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shoppyad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "signuponline.events", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "silvu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sipuri.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skattebo.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skillnes.herokuapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skillsforall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skipr.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skipr.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "slamtradingcards.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "slideproducts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "slushat-tekst-pesni.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smart-broker.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartbookings.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartlook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartwheelz.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smitsdesigncenter.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smpn10kotagorontalo.sch.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smudge.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "socialace.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "socksfromholland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sofortindenurlaub.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "softfusion.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sokkenkraam.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sontakip.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "soso.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "southernlights.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spam.red", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spbelect.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spectrumtexas.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spiegelingenblog.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spotpriskollen.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spribe.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sreb.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sssss.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stagmarketim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "standard-wohnungsbaukredit.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "standardwohnungsbaukredit.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "standardwohnungsbaukredit.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "starsgab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stefanini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stellexshop.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "steuerimgriff.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stoffn.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "storri.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "storycopy.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strauss-advisor.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strefarysunku.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strover.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strutsdepot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stuartmoving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "studiozes.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "succmy.wang", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "summitcustomsbrokers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sunflyer.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sunwayxfarms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "superfans.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "supervisorbullying.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "surveytester.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sus.zone", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "svin.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "svn-yokaiispirit.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "svtl.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "symbiote.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "t.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tandtroomtransformations.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "taxinhanhphanthiet24h.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tdk.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techgrance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techni-k.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "temporada.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "textura.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thebugmanfraservalley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thediamondapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "themassageguy.capetown", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thenullpointer.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thepioneersgame.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "therapeiacosmetics.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "therhodesresidences.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thewebagent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "timefracture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "timelettings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "timochan.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "timothyyip.photography", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tinydogllc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tinylotta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tklm.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tln.lib.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "todaysparent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tomdapice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tooadalsauda.kz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toolsa.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toondah.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toot.haus", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "top-super-60.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toricafe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tpldevsg-mythiess-dev.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "traficus.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "transfers-sheregesh.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "travellings.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "travelmap.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "travelriny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "treasuremountainmining.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trendingxxl.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trigirlpainting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tripspoint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trouvetonplancul.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trtadalafil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trueamateurs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "truechimer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trueformroofing.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trueworlds.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tsutaya-ai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "turanogluoptik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tvorog.dedyn.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tzhsoj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ullrich-group.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ulsterbandsforum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "umtactivation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "umtactivation.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unisplendour.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unlocktoolactivation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unlocktoolactivation.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "unope.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "us.nl.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uscdn.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uuuu.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "valid.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vanilla-official.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vantharp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vanya.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ventiques.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "venzeo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "versus-sec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vetofficeproducts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vexsh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "viagramarketim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "victoriaharmandjieva.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vik.bio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vikcdn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vikpage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vingahiss.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vinoxo.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "virgulazero.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "virtuallanding.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "visaxplorer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vnya.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "voileux.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "von-haselberg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vova.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vps.auction", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vps.chat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vps.discount", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vrg-gruppe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vrg.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vrimmoinvest.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vshop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vuath.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vvpn.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vvvvvv.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "walkerfoundation.org.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wamia.wa.gov.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wanted.co.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "watchurdiet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "waterloo-abba-show.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wdophoto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "we-listen.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "webdrops.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "weboffice.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "weefriendskids.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "welloca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "werkenbijjunis.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "westminsternational.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wicstunvetgroup.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wilburyvets.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "willowchild.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wiseitguys.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wlnk.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wmmi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wokeupset.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wolfsmobile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "woopiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "worldsage.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wsparcie.gov.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wundertraining.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wwwwww.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wycoreconstruction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wynweightloss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xavy.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--d1acmf9g.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--das-anhngerzentrum-rtb.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--owsz47f6mh.xn--6qq986b3xl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xreverseporn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xxvv.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xyzmedia.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yakupyilmazboru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yapdentalsurgery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ydetc.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yeechie.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ylivemusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yokaiispirit.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yomyyomy.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "youmeandjunee.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yournewsfeed.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ytmous.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yumisign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yxcpapp14.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yybx.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zenfires.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zircly.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zlpa.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zomatree.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zzcc.loan", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zzzzz.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, // END OF 1-YEAR BULK HSTS ENTRIES // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index cdf9593..02c2ebe 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2023-01-25 12:54 UTC +# Last updated: 2023-01-26 12:56 UTC PinsListTimestamp -1674651297 +1674737796 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/tools/cert_verify_tool/cert_verify_tool.cc b/net/tools/cert_verify_tool/cert_verify_tool.cc index 5f7f67b..aadcd2ce7 100644 --- a/net/tools/cert_verify_tool/cert_verify_tool.cc +++ b/net/tools/cert_verify_tool/cert_verify_tool.cc
@@ -21,6 +21,7 @@ #include "net/cert/cert_verify_proc_builtin.h" #include "net/cert/crl_set.h" #include "net/cert/internal/system_trust_store.h" +#include "net/cert/pki/trust_store.h" #include "net/cert/x509_util.h" #include "net/cert_net/cert_net_fetcher_url_request.h" #include "net/tools/cert_verify_tool/cert_verify_tool_util.h" @@ -101,7 +102,8 @@ virtual bool VerifyCert(const CertInput& target_der_cert, const std::string& hostname, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& + der_certs_with_trust_settings, base::Time verify_time, net::CRLSet* crl_set, const base::FilePath& dump_prefix_path) = 0; @@ -119,7 +121,8 @@ bool VerifyCert(const CertInput& target_der_cert, const std::string& hostname, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& + der_certs_with_trust_settings, base::Time verify_time, net::CRLSet* crl_set, const base::FilePath& dump_prefix_path) override { @@ -140,9 +143,9 @@ .InsertBeforeExtensionASCII("." + GetName()); } - return VerifyUsingCertVerifyProc(proc_.get(), target_der_cert, hostname, - intermediate_der_certs, root_der_certs, - crl_set, dump_path); + return VerifyUsingCertVerifyProc( + proc_.get(), target_der_cert, hostname, intermediate_der_certs, + der_certs_with_trust_settings, crl_set, dump_path); } private: @@ -164,7 +167,8 @@ bool VerifyCert(const CertInput& target_der_cert, const std::string& hostname, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& + der_certs_with_trust_settings, base::Time verify_time, net::CRLSet* crl_set, const base::FilePath& dump_prefix_path) override { @@ -177,8 +181,9 @@ } return VerifyUsingPathBuilder(target_der_cert, intermediate_der_certs, - root_der_certs, verify_time, dump_prefix_path, - cert_net_fetcher_, system_trust_store_.get()); + der_certs_with_trust_settings, verify_time, + dump_prefix_path, cert_net_fetcher_, + system_trust_store_.get()); } private: @@ -266,11 +271,13 @@ std::cout << "\n"; } -void PrintAdditionalRoots(const std::vector<CertInput>& root_der_certs) { +void PrintAdditionalRoots(const std::vector<CertInputWithTrustSetting>& + der_certs_with_trust_settings) { std::cout << "Additional roots:\n"; - for (const auto& cert : root_der_certs) { + for (const auto& cert : der_certs_with_trust_settings) { + std::cout << " " << cert.trust.ToDebugString() << ":\n "; PrintCertHashAndSubject( - net::x509_util::CreateCryptoBuffer(cert.der_cert).get()); + net::x509_util::CreateCryptoBuffer(cert.cert_input.der_cert).get()); } std::cout << "\n"; } @@ -318,6 +325,14 @@ " as a root. This is useful when providing a <target/chain>\n" " parameter whose final certificate is a trust anchor.\n" "\n" + " --root-trust=<trust string>\n" + " Roots trusted by --roots and --trust-last-cert will be trusted\n" + " with the specified trust [2].\n" + "\n" + " --trust-leaf-cert=[trust string]\n" + " The leaf cert will be considered trusted with the specified\n" + " trust [2]. If [trust string] is omitted, defaults to TRUSTED_LEAF.\n" + "\n" " --time=<time>\n" " Use <time> instead of the current system time. <time> is\n" " interpreted in local time if a timezone is not specified.\n" @@ -340,7 +355,16 @@ " either be:\n" " * A binary file containing a single DER-encoded RFC 5280 Certificate\n" " * A PEM file containing one or more CERTIFICATE blocks (DER-encoded\n" - " RFC 5280 Certificate)\n"; + " RFC 5280 Certificate)\n" + "\n" + "[2] A \"trust string\" consists of a trust type and zero or more options\n" + " separated by '+' characters. Note that these trust settings are only\n" + " honored by the builtin & pathbuilder impls.\n" + " Trust types: UNSPECIFIED, DISTRUSTED, TRUSTED_ANCHOR,\n" + " TRUSTED_ANCHOR_OR_LEAF, TRUSTED_LEAF\n" + " Options: enforce_anchor_expiry, enforce_anchor_constraints,\n" + " require_anchor_basic_constraints, require_leaf_selfsigned\n" + " Ex: TRUSTED_ANCHOR+enforce_anchor_expiry+enforce_anchor_constraints\n"; void PrintUsage(const char* argv0) { std::cerr << "Usage: " << argv0 << kUsage; @@ -413,6 +437,7 @@ base::FilePath dump_prefix_path = command_line.GetSwitchValuePath("dump"); + std::vector<CertInputWithTrustSetting> der_certs_with_trust_settings; std::vector<CertInput> root_der_certs; std::vector<CertInput> intermediate_der_certs; CertInput target_der_cert; @@ -445,9 +470,44 @@ intermediate_der_certs.pop_back(); } + if (command_line.HasSwitch("trust-leaf-cert")) { + net::CertificateTrust trust = net::CertificateTrust::ForTrustedLeaf(); + std::string trust_str = command_line.GetSwitchValueASCII("trust-leaf-cert"); + if (!trust_str.empty()) { + absl::optional<net::CertificateTrust> parsed_trust = + net::CertificateTrust::FromDebugString(trust_str); + if (!parsed_trust) { + std::cerr << "ERROR: invalid leaf trust string " << trust_str << "\n"; + return 1; + } + trust = *parsed_trust; + } + der_certs_with_trust_settings.push_back({target_der_cert, trust}); + } + + // TODO(https://crbug.com/1408473): Maybe default to the trust setting that + // would be used for locally added anchors on the current platform? + net::CertificateTrust root_trust = net::CertificateTrust::ForTrustAnchor(); + + if (command_line.HasSwitch("root-trust")) { + std::string trust_str = command_line.GetSwitchValueASCII("root-trust"); + absl::optional<net::CertificateTrust> parsed_trust = + net::CertificateTrust::FromDebugString(trust_str); + if (!parsed_trust) { + std::cerr << "ERROR: invalid root trust string " << trust_str << "\n"; + return 1; + } + root_trust = *parsed_trust; + } + + for (const auto& cert_input : root_der_certs) { + der_certs_with_trust_settings.push_back({cert_input, root_trust}); + } + PrintInputChain(target_der_cert, intermediate_der_certs); - if (!root_der_certs.empty()) - PrintAdditionalRoots(root_der_certs); + if (!der_certs_with_trust_settings.empty()) { + PrintAdditionalRoots(der_certs_with_trust_settings); + } // Create a network thread to be used for AIA fetches, and wait for a // CertNetFetcher to be constructed on that thread. @@ -500,8 +560,8 @@ std::cout << impls[i]->GetName() << ":\n"; if (!impls[i]->VerifyCert(target_der_cert, hostname, intermediate_der_certs, - root_der_certs, verify_time, crl_set.get(), - dump_prefix_path)) { + der_certs_with_trust_settings, verify_time, + crl_set.get(), dump_prefix_path)) { all_impls_success = false; } }
diff --git a/net/tools/cert_verify_tool/cert_verify_tool_util.h b/net/tools/cert_verify_tool/cert_verify_tool_util.h index 3bf36118..61ffee7 100644 --- a/net/tools/cert_verify_tool/cert_verify_tool_util.h +++ b/net/tools/cert_verify_tool/cert_verify_tool_util.h
@@ -10,6 +10,7 @@ #include "third_party/boringssl/src/include/openssl/base.h" #include "base/files/file_path.h" +#include "net/cert/pki/trust_store.h" namespace base { class SupportsUserData; @@ -35,6 +36,13 @@ std::string source_details; }; +// Stores DER certificate bytes as well as a trust setting that should be +// applied to them. +struct CertInputWithTrustSetting { + CertInput cert_input; + net::CertificateTrust trust; +}; + // Parses |file_path| as a single DER cert or a PEM certificate list. bool ReadCertificatesFromFile(const base::FilePath& file_path, std::vector<CertInput>* certs);
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc index cdccee731..9c036573 100644 --- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc +++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -88,7 +88,7 @@ const CertInput& target_der_cert, const std::string& hostname, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& der_certs_with_trust_settings, net::CRLSet* crl_set, const base::FilePath& dump_path) { std::vector<base::StringPiece> der_cert_chain; @@ -108,43 +108,34 @@ return false; } - net::CertificateList x509_additional_trust_anchors; - for (const auto& cert : root_der_certs) { - scoped_refptr<net::X509Certificate> x509_root = - net::X509Certificate::CreateFromBytes( - base::as_bytes(base::make_span(cert.der_cert))); + net::TestRootCerts* test_root_certs = net::TestRootCerts::GetInstance(); + CHECK(test_root_certs->IsEmpty()); - if (!x509_root) - PrintCertError("ERROR: X509Certificate::CreateFromBytes failed:", cert); - else - x509_additional_trust_anchors.push_back(x509_root); + std::vector<net::ScopedTestRoot> scoped_test_roots; + for (const auto& cert_input_with_trust : der_certs_with_trust_settings) { + scoped_refptr<net::X509Certificate> x509_root = + net::X509Certificate::CreateFromBytes(base::as_bytes( + base::make_span(cert_input_with_trust.cert_input.der_cert))); + + if (!x509_root) { + PrintCertError("ERROR: X509Certificate::CreateFromBytes failed:", + cert_input_with_trust.cert_input); + } else { + scoped_test_roots.emplace_back(x509_root.get(), + cert_input_with_trust.trust); + } } // TODO(mattm): add command line flags to configure VerifyFlags. int flags = 0; - // Not all platforms support providing additional trust anchors to the - // verifier. To workaround this, use TestRootCerts to modify the - // system trust store globally. - net::TestRootCerts* test_root_certs = net::TestRootCerts::GetInstance(); - CHECK(test_root_certs->IsEmpty()); - - net::ScopedTestRoot scoped_test_roots; - if (!x509_additional_trust_anchors.empty() && - !cert_verify_proc->SupportsAdditionalTrustAnchors()) { - std::cerr << "NOTE: Additional trust anchors not supported on this " - "platform. Using TestRootCerts instead.\n"; - - scoped_test_roots.Reset(x509_additional_trust_anchors); - x509_additional_trust_anchors.clear(); - } - // TODO(crbug.com/634484): use a real netlog and print the results? net::CertVerifyResult result; int rv = cert_verify_proc->Verify( x509_target_and_intermediates.get(), hostname, /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set, x509_additional_trust_anchors, &result, net::NetLogWithSource()); + crl_set, /*additional_trust_anchors=*/{}, &result, + net::NetLogWithSource()); std::cout << "CertVerifyProc result: " << net::ErrorToShortString(rv) << "\n"; PrintCertVerifyResult(result);
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h index 1b8062e..f96fc6c 100644 --- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h +++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.h
@@ -19,6 +19,7 @@ } struct CertInput; +struct CertInputWithTrustSetting; void PrintCertVerifyResult(const net::CertVerifyResult& result); @@ -31,7 +32,7 @@ const CertInput& target_der_cert, const std::string& hostname, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& der_certs_with_trust_settings, net::CRLSet* crl_set, const base::FilePath& dump_path);
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.cc b/net/tools/cert_verify_tool/verify_using_path_builder.cc index d2f4980..47a80f9 100644 --- a/net/tools/cert_verify_tool/verify_using_path_builder.cc +++ b/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -149,7 +149,7 @@ bool VerifyUsingPathBuilder( const CertInput& target_der_cert, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& der_certs_with_trust_settings, const base::Time at_time, const base::FilePath& dump_prefix_path, scoped_refptr<net::CertNetFetcher> cert_net_fetcher, @@ -159,18 +159,20 @@ net::der::GeneralizedTime time = ConvertExplodedTime(exploded_time); net::TrustStoreInMemory additional_roots; - for (const auto& der_cert : root_der_certs) { + for (const auto& cert_input_with_trust : der_certs_with_trust_settings) { std::shared_ptr<const net::ParsedCertificate> cert = - ParseCertificate(der_cert); + ParseCertificate(cert_input_with_trust.cert_input); if (cert) { - additional_roots.AddTrustAnchor(std::move(cert)); + additional_roots.AddCertificate(std::move(cert), + cert_input_with_trust.trust); } } net::TrustStoreCollection trust_store; trust_store.AddTrustStore(&additional_roots); trust_store.AddTrustStore(system_trust_store->GetTrustStore()); - if (!system_trust_store->UsesSystemTrustStore() && root_der_certs.empty()) { + if (!system_trust_store->UsesSystemTrustStore() && + der_certs_with_trust_settings.empty()) { std::cerr << "NOTE: CertPathBuilder does not currently use OS trust " "settings (--roots must be specified).\n"; }
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.h b/net/tools/cert_verify_tool/verify_using_path_builder.h index 56e3a21..9a9ae88 100644 --- a/net/tools/cert_verify_tool/verify_using_path_builder.h +++ b/net/tools/cert_verify_tool/verify_using_path_builder.h
@@ -20,6 +20,7 @@ } struct CertInput; +struct CertInputWithTrustSetting; // Verifies |target_der_cert| using CertPathBuilder. Returns true if the // certificate verified successfully, false if it failed to verify or there was @@ -28,7 +29,7 @@ bool VerifyUsingPathBuilder( const CertInput& target_der_cert, const std::vector<CertInput>& intermediate_der_certs, - const std::vector<CertInput>& root_der_certs, + const std::vector<CertInputWithTrustSetting>& der_certs_with_trust_settings, const base::Time at_time, const base::FilePath& dump_prefix_path, scoped_refptr<net::CertNetFetcher> cert_net_fetcher,
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 9f99f7f..0d6c64d 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -230,10 +230,6 @@ // set. bool IsPartitionedCookiesEnabled() const; - // Creates the CookieSettingOverrides that should be used when accessing any - // cookies for this request job. - CookieSettingOverrides GetCookieSettingOverrides() const; - RequestPriority priority_ = DEFAULT_PRIORITY; HttpRequestInfo request_info_;
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index d37a409..23d6267 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -341,6 +341,7 @@ kStageBeforeRedirect | // a delegate can trigger a redirection kStageCompletedError; // request canceled by delegate created_requests_++; + cookie_setting_overrides_ = request->cookie_setting_overrides(); return OK; }
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index bcdc183e..0531e8c5 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -293,6 +293,10 @@ fps_cache_filter_ = std::move(cache_filter); } + CookieSettingOverrides cookie_setting_overrides() const { + return cookie_setting_overrides_; + } + protected: // NetworkDelegate: int OnBeforeURLRequest(URLRequest* request, @@ -377,6 +381,8 @@ int next_request_id_ = 0; FirstPartySetsCacheFilter fps_cache_filter_; + + CookieSettingOverrides cookie_setting_overrides_; }; // ----------------------------------------------------------------------------
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc index b79961d..a745942 100644 --- a/net/websockets/websocket_handshake_stream_create_helper_test.cc +++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -177,6 +177,10 @@ : public TestWithParam<HandshakeStreamType>, public WithTaskEnvironment { protected: + WebSocketHandshakeStreamCreateHelperTest() + : quic_version_(quic::HandshakeProtocol::PROTOCOL_TLS1_3, + quic::QuicTransportVersion::QUIC_VERSION_IETF_RFC_V1), + mock_quic_data_(quic_version_) {} std::unique_ptr<WebSocketStream> CreateAndInitializeStream( const std::vector<std::string>& sub_protocols, const WebSocketExtraHeaders& extra_request_headers, @@ -318,6 +322,176 @@ EXPECT_EQ(200, response.headers->response_code()); return handshake->Upgrade(); } + case HTTP3_HANDSHAKE_STREAM: { + const quic::QuicStreamId client_data_stream_id( + quic::QuicUtils::GetFirstBidirectionalStreamId( + quic_version_.transport_version, quic::Perspective::IS_CLIENT)); + quic::QuicCryptoClientConfig crypto_config( + quic::test::crypto_test_utils::ProofVerifierForTesting()); + + const quic::QuicConnectionId connection_id( + quic::test::TestConnectionId(2)); + test::QuicTestPacketMaker client_maker( + quic_version_, connection_id, &clock_, "mail.example.org", + quic::Perspective::IS_CLIENT, + /*client_headers_include_h2_stream_dependency_=*/false); + test::QuicTestPacketMaker server_maker( + quic_version_, connection_id, &clock_, "mail.example.org", + quic::Perspective::IS_SERVER, + /*client_headers_include_h2_stream_dependency_=*/false); + IPEndPoint peer_addr(IPAddress(192, 0, 2, 23), 443); + quic::test::MockConnectionIdGenerator connection_id_generator; + + testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor; + ProofVerifyDetailsChromium verify_details; + MockCryptoClientStreamFactory crypto_client_stream_factory; + TransportSecurityState transport_security_state; + + FLAGS_quic_enable_http3_grease_randomness = false; + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20)); + quic::QuicEnableVersion(quic_version_); + quic::test::MockRandom random_generator{0}; + + spdy::Http2HeaderBlock request_header_block = WebSocketHttp2Request( + kPath, "www.example.org", kOrigin, extra_request_headers); + + int packet_number = 1; + mock_quic_data_.AddWrite( + SYNCHRONOUS, + client_maker.MakeInitialSettingsPacket(packet_number++)); + + mock_quic_data_.AddWrite( + ASYNC, + client_maker.MakeRequestHeadersPacket( + packet_number++, client_data_stream_id, + /*should_include_version=*/true, + /*fin=*/false, ConvertRequestPriorityToQuicPriority(LOWEST), + std::move(request_header_block), 0, nullptr)); + + spdy::Http2HeaderBlock response_header_block = + WebSocketHttp2Response(extra_response_headers); + + mock_quic_data_.AddRead( + ASYNC, server_maker.MakeResponseHeadersPacket( + /*packet_number=*/1, client_data_stream_id, + /*should_include_version=*/true, /*fin=*/false, + std::move(response_header_block), + /*spdy_headers_frame_length=*/nullptr)); + + mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + + mock_quic_data_.AddWrite( + SYNCHRONOUS, + client_maker.MakeAckAndRstPacket( + packet_number++, /*include_version=*/false, + client_data_stream_id, quic::QUIC_STREAM_CANCELLED, 1, 0, + /*include_stop_sending_if_v99=*/true)); + auto socket = std::make_unique<MockUDPClientSocket>( + mock_quic_data_.InitializeAndGetSequencedSocketData(), + NetLog::Get()); + socket->Connect(peer_addr); + + scoped_refptr<test::TestTaskRunner> runner = + base::MakeRefCounted<test::TestTaskRunner>(&clock_); + auto helper = std::make_unique<QuicChromiumConnectionHelper>( + &clock_, &random_generator); + auto alarm_factory = + std::make_unique<QuicChromiumAlarmFactory>(runner.get(), &clock_); + // Ownership of 'writer' is passed to 'QuicConnection'. + QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter( + socket.get(), + base::SingleThreadTaskRunner::GetCurrentDefault().get()); + quic::QuicConnection* connection = new quic::QuicConnection( + connection_id, quic::QuicSocketAddress(), + net::ToQuicSocketAddress(peer_addr), helper.get(), + alarm_factory.get(), writer, true /* owns_writer */, + quic::Perspective::IS_CLIENT, + quic::test::SupportedVersions(quic_version_), + connection_id_generator); + connection->set_visitor(&visitor); + + // Load a certificate that is valid for *.example.org + scoped_refptr<X509Certificate> test_cert( + ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); + EXPECT_TRUE(test_cert.get()); + + verify_details.cert_verify_result.verified_cert = test_cert; + verify_details.cert_verify_result.is_issued_by_known_root = true; + crypto_client_stream_factory.AddProofVerifyDetails(&verify_details); + + base::TimeTicks dns_end = base::TimeTicks::Now(); + base::TimeTicks dns_start = dns_end - base::Milliseconds(1); + + session_ = std::make_unique<QuicChromiumClientSession>( + connection, std::move(socket), + /*stream_factory=*/nullptr, &crypto_client_stream_factory, &clock_, + &transport_security_state, /*ssl_config_service=*/nullptr, + /*server_info=*/nullptr, + QuicSessionKey("mail.example.org", 80, PRIVACY_MODE_DISABLED, + SocketTag(), NetworkAnonymizationKey(), + SecureDnsPolicy::kAllow, + /*require_dns_https_alpn=*/false), + /*require_confirmation=*/false, + /*migrate_session_early_v2=*/false, + /*migrate_session_on_network_change_v2=*/false, + /*default_network=*/handles::kInvalidNetworkHandle, + quic::QuicTime::Delta::FromMilliseconds( + kDefaultRetransmittableOnWireTimeout.InMilliseconds()), + /*migrate_idle_session=*/true, /*allow_port_migration=*/false, + kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork, + kMaxMigrationsToNonDefaultNetworkOnWriteError, + kMaxMigrationsToNonDefaultNetworkOnPathDegrading, + kQuicYieldAfterPacketsRead, + quic::QuicTime::Delta::FromMilliseconds( + kQuicYieldAfterDurationMilliseconds), + /*client_headers_include_h2_stream_dependency_=*/false, + /*cert_verify_flags=*/0, quic::test::DefaultQuicConfig(), + std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config), + "CONNECTION_UNKNOWN", dns_start, dns_end, + std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, + base::DefaultTickClock::GetInstance(), + base::SingleThreadTaskRunner::GetCurrentDefault().get(), + /*socket_performance_watcher=*/nullptr, NetLog::Get()); + + session_->Initialize(); + + // Blackhole QPACK decoder stream instead of constructing mock writes. + session_->qpack_decoder()->set_qpack_stream_sender_delegate( + &noop_qpack_stream_sender_delegate_); + TestCompletionCallback callback; + EXPECT_THAT(session_->CryptoConnect(callback.callback()), IsOk()); + EXPECT_TRUE(session_->OneRttKeysAvailable()); + std::unique_ptr<QuicChromiumClientSession::Handle> session_handle = + session_->CreateHandle( + url::SchemeHostPort(url::kHttpsScheme, "mail.example.org", 80)); + + std::unique_ptr<WebSocketHandshakeStreamBase> handshake = + create_helper.CreateHttp3Stream(std::move(session_handle), + {} /* dns_aliases */); + + handshake->RegisterRequest(&request_info); + int rv = handshake->InitializeStream(true, DEFAULT_PRIORITY, net_log, + CompletionOnceCallback()); + EXPECT_THAT(rv, IsOk()); + + HttpResponseInfo response; + TestCompletionCallback request_callback; + rv = handshake->SendRequest(headers, &response, + request_callback.callback()); + EXPECT_THAT(rv, IsOk()); + + session_->StartReading(); + + TestCompletionCallback response_callback; + rv = handshake->ReadResponseHeaders(response_callback.callback()); + EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); + rv = response_callback.WaitForResult(); + EXPECT_THAT(rv, IsOk()); + + EXPECT_EQ(200, response.headers->response_code()); + + return handshake->Upgrade(); + } default: NOTREACHED(); return nullptr; @@ -329,12 +503,20 @@ TestConnectDelegate connect_delegate_; StrictMock<MockWebSocketStreamRequestAPI> stream_request_; WebSocketEndpointLockManager websocket_endpoint_lock_manager_; + + // For HTTP3_HANDSHAKE_STREAM + quic::ParsedQuicVersion quic_version_; + quic::MockClock clock_; + std::unique_ptr<QuicChromiumClientSession> session_; + test::MockQuicData mock_quic_data_; + quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_; }; INSTANTIATE_TEST_SUITE_P(All, WebSocketHandshakeStreamCreateHelperTest, Values(BASIC_HANDSHAKE_STREAM, - HTTP2_HANDSHAKE_STREAM)); + HTTP2_HANDSHAKE_STREAM, + HTTP3_HANDSHAKE_STREAM)); // Confirm that the basic case works as expected. TEST_P(WebSocketHandshakeStreamCreateHelperTest, BasicStream) { @@ -380,226 +562,6 @@ stream->GetExtensions()); } -// Temporary test class to test the creation of WebSocketHttp3HandshakeStream. -// TODO(momoka): Move this function inside -// HandshakeStreamCreateHelperTest::CreateAndInitializeStream() once -// implementation of WebSocketHttp3HandshakeStream is done. -class TemporaryHttp3WebSocketHandshakeStreamCreateHelperTest - : public TestWithTaskEnvironment { - protected: - TemporaryHttp3WebSocketHandshakeStreamCreateHelperTest() - : quic_version_(quic::HandshakeProtocol::PROTOCOL_TLS1_3, - quic::QuicTransportVersion::QUIC_VERSION_IETF_RFC_V1), - mock_quic_data_(quic_version_) {} - - std::unique_ptr<WebSocketStream> CreateAndInitializeStream( - const std::vector<std::string>& sub_protocols, - const WebSocketExtraHeaders& extra_request_headers, - const WebSocketExtraHeaders& extra_response_headers) { - const char kPath[] = "/"; - const char kOrigin[] = "http://origin.example.org"; - const GURL url("wss://www.example.org/"); - NetLogWithSource net_log; - - WebSocketHandshakeStreamCreateHelper create_helper( - &connect_delegate_, sub_protocols, &stream_request_); - - EXPECT_CALL(stream_request_, OnHttp3HandshakeStreamCreated(_)); - - EXPECT_CALL(stream_request_, OnFailure(_, _, _)).Times(0); - - HttpRequestInfo request_info; - request_info.url = url; - request_info.method = "GET"; - request_info.load_flags = LOAD_DISABLE_CACHE; - request_info.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - auto headers = WebSocketCommonTestHeaders(); - - const quic::QuicStreamId client_data_stream_id1( - quic::QuicUtils::GetFirstBidirectionalStreamId( - quic_version_.transport_version, quic::Perspective::IS_CLIENT)); - quic::QuicCryptoClientConfig crypto_config( - quic::test::crypto_test_utils::ProofVerifierForTesting()); - - const quic::QuicConnectionId connection_id(quic::test::TestConnectionId(2)); - test::QuicTestPacketMaker client_maker( - quic_version_, connection_id, &clock_, "mail.example.org", - quic::Perspective::IS_CLIENT, - /*client_headers_include_h2_stream_dependency_=*/false); - test::QuicTestPacketMaker server_maker( - quic_version_, connection_id, &clock_, "mail.example.org", - quic::Perspective::IS_SERVER, - /*client_headers_include_h2_stream_dependency_=*/false); - IPEndPoint peer_addr(IPAddress(192, 0, 2, 23), 443); - quic::test::MockConnectionIdGenerator connection_id_generator; - - testing::StrictMock<quic::test::MockQuicConnectionVisitor> visitor; - ProofVerifyDetailsChromium verify_details; - MockCryptoClientStreamFactory crypto_client_stream_factory; - TransportSecurityState transport_security_state; - quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate; - - FLAGS_quic_enable_http3_grease_randomness = false; - clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20)); - quic::QuicEnableVersion(quic_version_); - quic::test::MockRandom random_generator{0}; - - spdy::Http2HeaderBlock request_header_block = WebSocketHttp2Request( - kPath, "www.example.org", kOrigin, extra_request_headers); - - int packet_number = 1; - mock_quic_data_.AddWrite( - SYNCHRONOUS, client_maker.MakeInitialSettingsPacket(packet_number++)); - - mock_quic_data_.AddWrite( - ASYNC, client_maker.MakeRequestHeadersPacket( - packet_number++, client_data_stream_id1, - /*should_include_version=*/true, - /*fin=*/false, ConvertRequestPriorityToQuicPriority(LOWEST), - std::move(request_header_block), 0, nullptr)); - - spdy::Http2HeaderBlock response_header_block = - WebSocketHttp2Response(extra_response_headers); - - mock_quic_data_.AddRead(ASYNC, - server_maker.MakeResponseHeadersPacket( - /*packet_number=*/1, client_data_stream_id1, - /*should_include_version=*/true, /*fin=*/false, - std::move(response_header_block), - /*spdy_headers_frame_length=*/nullptr)); - - mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING); - - mock_quic_data_.AddWrite( - SYNCHRONOUS, - client_maker.MakeAckAndRstPacket( - packet_number++, /*include_version=*/false, client_data_stream_id1, - quic::QUIC_STREAM_CANCELLED, 1, 0, - /*include_stop_sending_if_v99=*/true)); - auto socket = std::make_unique<MockUDPClientSocket>( - mock_quic_data_.InitializeAndGetSequencedSocketData(), NetLog::Get()); - socket->Connect(peer_addr); - - scoped_refptr<test::TestTaskRunner> runner = - base::MakeRefCounted<test::TestTaskRunner>(&clock_); - auto helper = std::make_unique<QuicChromiumConnectionHelper>( - &clock_, &random_generator); - auto alarm_factory = - std::make_unique<QuicChromiumAlarmFactory>(runner.get(), &clock_); - // Ownership of 'writer' is passed to 'QuicConnection'. - QuicChromiumPacketWriter* writer = new QuicChromiumPacketWriter( - socket.get(), base::SingleThreadTaskRunner::GetCurrentDefault().get()); - quic::QuicConnection* connection = new quic::QuicConnection( - connection_id, quic::QuicSocketAddress(), - net::ToQuicSocketAddress(peer_addr), helper.get(), alarm_factory.get(), - writer, true /* owns_writer */, quic::Perspective::IS_CLIENT, - quic::test::SupportedVersions(quic_version_), connection_id_generator); - connection->set_visitor(&visitor); - - // Load a certificate that is valid for *.example.org - scoped_refptr<X509Certificate> test_cert( - ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); - EXPECT_TRUE(test_cert.get()); - - verify_details.cert_verify_result.verified_cert = test_cert; - verify_details.cert_verify_result.is_issued_by_known_root = true; - crypto_client_stream_factory.AddProofVerifyDetails(&verify_details); - - base::TimeTicks dns_end = base::TimeTicks::Now(); - base::TimeTicks dns_start = dns_end - base::Milliseconds(1); - - session_ = std::make_unique<QuicChromiumClientSession>( - connection, std::move(socket), - /*stream_factory=*/nullptr, &crypto_client_stream_factory, &clock_, - &transport_security_state, /*ssl_config_service=*/nullptr, - /*server_info=*/nullptr, - QuicSessionKey("mail.example.org", 80, PRIVACY_MODE_DISABLED, - SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, - /*require_dns_https_alpn=*/false), - /*require_confirmation=*/false, - /*migrate_session_early_v2=*/false, - /*migrate_session_on_network_change_v2=*/false, - /*default_network=*/handles::kInvalidNetworkHandle, - quic::QuicTime::Delta::FromMilliseconds( - kDefaultRetransmittableOnWireTimeout.InMilliseconds()), - /*migrate_idle_session=*/true, /*allow_port_migration=*/false, - kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork, - kMaxMigrationsToNonDefaultNetworkOnWriteError, - kMaxMigrationsToNonDefaultNetworkOnPathDegrading, - kQuicYieldAfterPacketsRead, - quic::QuicTime::Delta::FromMilliseconds( - kQuicYieldAfterDurationMilliseconds), - /*client_headers_include_h2_stream_dependency_=*/false, - /*cert_verify_flags=*/0, quic::test::DefaultQuicConfig(), - std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config), - "CONNECTION_UNKNOWN", dns_start, dns_end, - std::make_unique<quic::QuicClientPushPromiseIndex>(), nullptr, - base::DefaultTickClock::GetInstance(), - base::SingleThreadTaskRunner::GetCurrentDefault().get(), - /*socket_performance_watcher=*/nullptr, NetLog::Get()); - - session_->Initialize(); - - // Blackhole QPACK decoder stream instead of constructing mock writes. - session_->qpack_decoder()->set_qpack_stream_sender_delegate( - &noop_qpack_stream_sender_delegate_); - TestCompletionCallback callback; - EXPECT_THAT(session_->CryptoConnect(callback.callback()), IsOk()); - EXPECT_TRUE(session_->OneRttKeysAvailable()); - std::unique_ptr<QuicChromiumClientSession::Handle> session_handle = - session_->CreateHandle( - url::SchemeHostPort(url::kHttpsScheme, "mail.example.org", 80)); - - std::unique_ptr<WebSocketHandshakeStreamBase> handshake = - create_helper.CreateHttp3Stream(std::move(session_handle), - {} /* dns_aliases */); - - handshake->RegisterRequest(&request_info); - int rv = handshake->InitializeStream(true, DEFAULT_PRIORITY, net_log, - CompletionOnceCallback()); - EXPECT_THAT(rv, IsOk()); - - HttpResponseInfo response; - TestCompletionCallback request_callback; - rv = - handshake->SendRequest(headers, &response, request_callback.callback()); - EXPECT_THAT(rv, IsOk()); - - session_->StartReading(); - - TestCompletionCallback response_callback; - rv = handshake->ReadResponseHeaders(response_callback.callback()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - rv = response_callback.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - - EXPECT_EQ(200, response.headers->response_code()); - - return handshake->Upgrade(); - } - - private: - quic::ParsedQuicVersion quic_version_; - quic::MockClock clock_; - MockClientSocketHandleFactory socket_handle_factory_; - TestConnectDelegate connect_delegate_; - StrictMock<MockWebSocketStreamRequestAPI> stream_request_; - WebSocketEndpointLockManager websocket_endpoint_lock_manager_; - std::unique_ptr<QuicChromiumClientSession> session_; - test::MockQuicData mock_quic_data_; - quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_; -}; - -TEST_F(TemporaryHttp3WebSocketHandshakeStreamCreateHelperTest, BasicStream) { - std::unique_ptr<WebSocketStream> stream = - CreateAndInitializeStream({}, {}, {}); - EXPECT_EQ("", stream->GetExtensions()); - EXPECT_EQ("", stream->GetSubProtocol()); -} - } // namespace } // namespace net
diff --git a/net/websockets/websocket_http3_handshake_stream.cc b/net/websockets/websocket_http3_handshake_stream.cc index 3220126..11b9e31 100644 --- a/net/websockets/websocket_http3_handshake_stream.cc +++ b/net/websockets/websocket_http3_handshake_stream.cc
@@ -4,11 +4,8 @@ #include "net/websockets/websocket_http3_handshake_stream.h" -#include <cstddef> -#include <set> #include <utility> -#include "base/check_op.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "net/base/ip_endpoint.h" @@ -50,7 +47,6 @@ } WebSocketHttp3HandshakeStream::~WebSocketHttp3HandshakeStream() { - quic_stream_request_.reset(); RecordHandshakeResult(result_); } @@ -153,7 +149,6 @@ } void WebSocketHttp3HandshakeStream::Close(bool not_reusable) { - quic_stream_request_.reset(); if (stream_adapter_) { stream_adapter_->Disconnect(); stream_closed_ = true;
diff --git a/net/websockets/websocket_http3_handshake_stream.h b/net/websockets/websocket_http3_handshake_stream.h index 9eccc99e..6f8a6a8 100644 --- a/net/websockets/websocket_http3_handshake_stream.h +++ b/net/websockets/websocket_http3_handshake_stream.h
@@ -162,8 +162,6 @@ NetLogWithSource net_log_; - std::unique_ptr<QuicStreamRequest> quic_stream_request_; - // WebSocketQuicStreamAdapter holding a WeakPtr to `stream_`. // This can be passed on to WebSocketBasicStream when created. std::unique_ptr<WebSocketQuicStreamAdapter> stream_adapter_;
diff --git a/printing/print_job_constants_cups.cc b/printing/print_job_constants_cups.cc index 27635e3..ae5b9cc7 100644 --- a/printing/print_job_constants_cups.cc +++ b/printing/print_job_constants_cups.cc
@@ -7,6 +7,8 @@ namespace printing { // Variations of identifier used for specifying printer color model. +// New ways of specifying a color model should include an entry in +// `kKnownPpdColorSettings`. const char kCUPSColorMode[] = "ColorMode"; const char kCUPSColorModel[] = "ColorModel"; const char kCUPSPrintoutMode[] = "PrintoutMode"; @@ -61,4 +63,26 @@ const char kXeroxBW[] = "BW"; const char kZero[] = "0"; +#if BUILDFLAG(IS_MAC) +base::span<const PpdColorSetting> GetKnownPpdColorSettings() { + static const PpdColorSetting kKnownPpdColorSettings[] = { + {kCUPSBrotherMonoColor, kMono, kFullColor}, // Brother + {kCUPSBrotherPrintQuality, kBlack, kColor}, // Brother + {kCUPSCanonCNIJGrayScale, kOne, kZero}, // Canon + {kCUPSColorMode, kMonochrome, kColor}, // Samsung + {kCUPSColorModel, kGray, kColor}, // Generic + {kCUPSEpsonInk, kEpsonMono, kEpsonColor}, // Epson + {kCUPSHpColorMode, kHpGrayscalePrint, kHpColorPrint}, // HP + {kCUPSLexmarkBLW, kLexmarkBLWTrue, kLexmarkBLWFalse}, // Lexmark + {kCUPSOkiControl, kGray, kAuto}, // Oki + {kCUPSPrintoutMode, kNormalGray, kNormal}, // Foomatic + {kCUPSSelectColor, kGrayscale, kColor}, // Konica Minolta + {kCUPSSharpARCMode, kSharpCMBW, kSharpCMColor}, // Sharp + {kCUPSXeroxXROutputColor, kPrintAsGrayscale, kPrintAsColor}, // Xerox + {kCUPSXeroxXRXColor, kXeroxBW, kXeroxAutomatic}, // Xerox + }; + return base::make_span(kKnownPpdColorSettings); +} +#endif + } // namespace printing
diff --git a/printing/print_job_constants_cups.h b/printing/print_job_constants_cups.h index 8c8c834b..e8baf09 100644 --- a/printing/print_job_constants_cups.h +++ b/printing/print_job_constants_cups.h
@@ -9,6 +9,11 @@ #include "build/build_config.h" #include "printing/buildflags/buildflags.h" +#if BUILDFLAG(IS_MAC) +#include "base/containers/span.h" +#include "base/strings/string_piece.h" +#endif + #if !BUILDFLAG(USE_CUPS) #error "CUPS must be enabled." #endif @@ -70,6 +75,25 @@ COMPONENT_EXPORT(PRINTING_BASE) extern const char kXeroxBW[]; COMPONENT_EXPORT(PRINTING_BASE) extern const char kZero[]; +#if BUILDFLAG(IS_MAC) +// Represents set identifier used to specifier to select the color model for a +// particular printer manufacturer, and the corresponding names used with that +// to choose either black and white or color printing. +struct COMPONENT_EXPORT(PRINTING_BASE) PpdColorSetting { + constexpr PpdColorSetting(base::StringPiece name, + base::StringPiece bw, + base::StringPiece color) + : name(name), bw(bw), color(color) {} + + base::StringPiece name; + base::StringPiece bw; + base::StringPiece color; +}; + +COMPONENT_EXPORT(PRINTING_BASE) +base::span<const PpdColorSetting> GetKnownPpdColorSettings(); +#endif + } // namespace printing #endif // PRINTING_PRINT_JOB_CONSTANTS_CUPS_H_
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm index 844c3be..22df5f2 100644 --- a/printing/printing_context_mac.mm +++ b/printing/printing_context_mac.mm
@@ -414,41 +414,12 @@ return false; } - struct PpdColorSetting { - constexpr PpdColorSetting(base::StringPiece name, - base::StringPiece bw, - base::StringPiece color) - : name(name), bw(bw), color(color) {} - base::StringPiece name; - base::StringPiece bw; - base::StringPiece color; - }; - - // TODO(crbug.com/1210992): Move `kKnownPpdColorSettings` elsewhere so it can - // be used for general CUPS printing code (e.g., for parsing PPDs). - static const PpdColorSetting kKnownPpdColorSettings[] = { - {kCUPSBrotherMonoColor, kMono, kFullColor}, // Brother - {kCUPSBrotherPrintQuality, kBlack, kColor}, // Brother - {kCUPSCanonCNIJGrayScale, kOne, kZero}, // Canon - {kCUPSColorMode, kMonochrome, kColor}, // Samsung - {kCUPSColorModel, kGray, kColor}, // Generic - {kCUPSEpsonInk, kEpsonMono, kEpsonColor}, // Epson - {kCUPSHpColorMode, kHpGrayscalePrint, kHpColorPrint}, // HP - {kCUPSLexmarkBLW, kLexmarkBLWTrue, kLexmarkBLWFalse}, // Lexmark - {kCUPSOkiControl, kGray, kAuto}, // Oki - {kCUPSPrintoutMode, kNormalGray, kNormal}, // Foomatic - {kCUPSSelectColor, kGrayscale, kColor}, // Konica Minolta - {kCUPSSharpARCMode, kSharpCMBW, kSharpCMColor}, // Sharp - {kCUPSXeroxXROutputColor, kPrintAsGrayscale, kPrintAsColor}, // Xerox - {kCUPSXeroxXRXColor, kXeroxBW, kXeroxAutomatic}, // Xerox - }; - // Even when interfacing with printer settings using CUPS IPP, the print job // may still expect PPD color values if the printer was added to the system // with a PPD. To avoid parsing PPDs (which is the point of using CUPS IPP), // set every single known PPD color setting and hope that one of them sticks. const bool is_color = IsColorModelSelected(color_model).value_or(false); - for (const auto& setting : kKnownPpdColorSettings) { + for (const auto& setting : GetKnownPpdColorSettings()) { const base::StringPiece& color_setting_name = setting.name; const base::StringPiece& color_value = is_color ? setting.color : setting.bw;
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn index 687175d..047f723 100644 --- a/remoting/host/linux/BUILD.gn +++ b/remoting/host/linux/BUILD.gn
@@ -41,7 +41,7 @@ if (is_component_build) { sources += [ "$root_build_dir/libbase.so", - "$root_build_dir/libboringssl.so", + "$root_build_dir/libthird_party_boringssl.so", ] deps += [ "//base:base" ] if (use_custom_libcxx) {
diff --git a/sandbox/policy/win/sandbox_win_unittest.cc b/sandbox/policy/win/sandbox_win_unittest.cc index 3863f3f4..d3cc47a 100644 --- a/sandbox/policy/win/sandbox_win_unittest.cc +++ b/sandbox/policy/win/sandbox_win_unittest.cc
@@ -135,8 +135,6 @@ ResultCode SetStderrHandle(HANDLE handle) override { return SBOX_ALL_OK; } void AddHandleToShare(HANDLE handle) override {} - void SetEffectiveToken(HANDLE token) override {} - private: TestTargetConfig config_; };
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn index 174200e..678f0e0 100644 --- a/sandbox/win/BUILD.gn +++ b/sandbox/win/BUILD.gn
@@ -101,8 +101,6 @@ "src/sandbox_policy_diagnostic.h", "src/sandbox_rand.cc", "src/sandbox_rand.h", - "src/sandbox_utils.cc", - "src/sandbox_utils.h", "src/security_capabilities.cc", "src/security_capabilities.h", "src/service_resolver.cc",
diff --git a/sandbox/win/src/acl.cc b/sandbox/win/src/acl.cc index c2e5e421..9996fe1 100644 --- a/sandbox/win/src/acl.cc +++ b/sandbox/win/src/acl.cc
@@ -7,91 +7,9 @@ #include <windows.h> #include "base/notreached.h" -#include "base/win/access_token.h" namespace sandbox { -namespace { - -absl::optional<DWORD> GetIntegrityLevelValue(IntegrityLevel integrity_level) { - switch (integrity_level) { - case INTEGRITY_LEVEL_SYSTEM: - return DWORD{SECURITY_MANDATORY_SYSTEM_RID}; - case INTEGRITY_LEVEL_HIGH: - return DWORD{SECURITY_MANDATORY_HIGH_RID}; - case INTEGRITY_LEVEL_MEDIUM: - return DWORD{SECURITY_MANDATORY_MEDIUM_RID}; - case INTEGRITY_LEVEL_MEDIUM_LOW: - return DWORD{SECURITY_MANDATORY_MEDIUM_RID - 2048}; - case INTEGRITY_LEVEL_LOW: - return DWORD{SECURITY_MANDATORY_LOW_RID}; - case INTEGRITY_LEVEL_BELOW_LOW: - return DWORD{SECURITY_MANDATORY_LOW_RID - 2048}; - case INTEGRITY_LEVEL_UNTRUSTED: - return DWORD{SECURITY_MANDATORY_UNTRUSTED_RID}; - case INTEGRITY_LEVEL_LAST: - return absl::nullopt; - } - - NOTREACHED(); - return absl::nullopt; -} - -bool AddSidToDefaultDacl(base::win::AccessToken& token, - const base::win::Sid& sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access) { - absl::optional<base::win::AccessControlList> dacl = token.DefaultDacl(); - if (!dacl || !dacl->SetEntry(sid, access_mode, access, 0)) { - return false; - } - return token.SetDefaultDacl(*dacl); -} - -} // namespace - -bool AddSidToDefaultDacl(HANDLE token, - const base::win::Sid& sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access) { - absl::optional<base::win::AccessToken> query_token = - base::win::AccessToken::FromToken(token, TOKEN_ADJUST_DEFAULT); - if (!query_token) - return false; - - return AddSidToDefaultDacl(*query_token, sid, access_mode, access); -} - -bool AddSidToDefaultDacl(HANDLE token, - base::win::WellKnownSid known_sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access) { - return AddSidToDefaultDacl(token, base::win::Sid(known_sid), access_mode, - access); -} - -bool RevokeLogonSidFromDefaultDacl(HANDLE token) { - absl::optional<base::win::AccessToken> query_token = - base::win::AccessToken::FromToken(token, TOKEN_ADJUST_DEFAULT); - if (!query_token) - return false; - absl::optional<base::win::Sid> logon_sid = query_token->LogonId(); - if (!logon_sid) - return ::GetLastError() == ERROR_NOT_FOUND; - - return AddSidToDefaultDacl(*query_token, *logon_sid, - base::win::SecurityAccessMode::kRevoke, 0); -} - -bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) { - absl::optional<base::win::AccessToken> query_token = - base::win::AccessToken::FromToken(token, TOKEN_ADJUST_DEFAULT); - if (!query_token) - return false; - return AddSidToDefaultDacl(*query_token, query_token->User(), - base::win::SecurityAccessMode::kGrant, access); -} - bool AddKnownSidToObject(HANDLE object, base::win::SecurityObjectType object_type, const base::win::Sid& sid, @@ -134,19 +52,35 @@ base::win::SecurityAccessMode::kGrant, access); } -absl::optional<base::win::Sid> GetIntegrityLevelSid( - IntegrityLevel integrity_level) { - absl::optional<DWORD> value = GetIntegrityLevelValue(integrity_level); - if (!value) - return absl::nullopt; - return base::win::Sid::FromIntegrityLevel(*value); +absl::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level) { + switch (integrity_level) { + case INTEGRITY_LEVEL_SYSTEM: + return DWORD{SECURITY_MANDATORY_SYSTEM_RID}; + case INTEGRITY_LEVEL_HIGH: + return DWORD{SECURITY_MANDATORY_HIGH_RID}; + case INTEGRITY_LEVEL_MEDIUM: + return DWORD{SECURITY_MANDATORY_MEDIUM_RID}; + case INTEGRITY_LEVEL_MEDIUM_LOW: + return DWORD{SECURITY_MANDATORY_MEDIUM_RID - 2048}; + case INTEGRITY_LEVEL_LOW: + return DWORD{SECURITY_MANDATORY_LOW_RID}; + case INTEGRITY_LEVEL_BELOW_LOW: + return DWORD{SECURITY_MANDATORY_LOW_RID - 2048}; + case INTEGRITY_LEVEL_UNTRUSTED: + return DWORD{SECURITY_MANDATORY_UNTRUSTED_RID}; + case INTEGRITY_LEVEL_LAST: + return absl::nullopt; + } + + NOTREACHED(); + return absl::nullopt; } DWORD SetObjectIntegrityLabel(HANDLE handle, base::win::SecurityObjectType object_type, DWORD mandatory_policy, IntegrityLevel integrity_level) { - absl::optional<DWORD> value = GetIntegrityLevelValue(integrity_level); + absl::optional<DWORD> value = GetIntegrityLevelRid(integrity_level); if (!value) { return ERROR_INVALID_SID; }
diff --git a/sandbox/win/src/acl.h b/sandbox/win/src/acl.h index 0d3af4d..585d982 100644 --- a/sandbox/win/src/acl.h +++ b/sandbox/win/src/acl.h
@@ -5,7 +5,6 @@ #ifndef SANDBOX_WIN_SRC_ACL_H_ #define SANDBOX_WIN_SRC_ACL_H_ -#include "base/memory/free_deleter.h" #include "base/win/access_control_list.h" #include "base/win/security_descriptor.h" #include "base/win/sid.h" @@ -15,37 +14,16 @@ namespace sandbox { -// Adds an ACE represented by |sid| and |access| with |access_mode| to the -// default dacl present in the token. -bool AddSidToDefaultDacl(HANDLE token, - const base::win::Sid& sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access); - -// Adds an ACE represented by |known_sid| and |access| with |access_mode| to the -// default dacl present in the token. -bool AddSidToDefaultDacl(HANDLE token, - base::win::WellKnownSid known_sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access); - -// Revokes access to the logon SID for the default dacl present in the token. -bool RevokeLogonSidFromDefaultDacl(HANDLE token); - -// Adds an ACE represented by the user sid and |access| to the default dacl -// present in the token. -bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access); - -// Adds an ACE represented by |known_sid|, |access_mode|, and |access| to -// the dacl of the kernel object referenced by |object| and of |object_type|. +// Adds an ACE represented by `known_sid`, `access_mode`, and `access` to +// the dacl of the kernel object referenced by `object` and of `object_type`. bool AddKnownSidToObject(HANDLE object, base::win::SecurityObjectType object_type, base::win::WellKnownSid known_sid, base::win::SecurityAccessMode access_mode, ACCESS_MASK access); -// Adds an ACE represented by |sid|, |access_mode|, and |access| to -// the dacl of the kernel object referenced by |object| and of |object_type|. +// Adds an ACE represented by `sid`, `access_mode`, and `access` to +// the dacl of the kernel object referenced by `object` and of `object_type`. bool AddKnownSidToObject(HANDLE object, base::win::SecurityObjectType object_type, const base::win::Sid& sid, @@ -60,20 +38,19 @@ const base::win::Sid& package_sid, ACCESS_MASK access); -// Returns the Sid associated with a given IntegrityLevel value. This returns -// an empty value if |integrity_level| is set to INTEGRITY_LEVEL_LAST. -absl::optional<base::win::Sid> GetIntegrityLevelSid( - IntegrityLevel integrity_level); +// Returns the RID associated with a given IntegrityLevel value. This returns +// an empty value if `integrity_level` is set to INTEGRITY_LEVEL_LAST. +absl::optional<DWORD> GetIntegrityLevelRid(IntegrityLevel integrity_level); // Sets the integrity label on a object. -// |handle| should be an open handle with WRITE_OWNER access. -// |object_type| represents the kernel object type of the handle. -// |mandatory_policy| is the mandatory policy to use. This can be zero or more +// `handle` should be an open handle with WRITE_OWNER access. +// `object_type` represents the kernel object type of the handle. +// `mandatory_policy` is the mandatory policy to use. This can be zero or more // of the following bit flags: // SYSTEM_MANDATORY_LABEL_NO_WRITE_UP - Block write access. // SYSTEM_MANDATORY_LABEL_NO_READ_UP - Block read access. // SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP - Block execute access. -// |integrity_level| is the level to set. +// `integrity_level` is the level to set. // If the function succeeds, the return value is ERROR_SUCCESS. If the // function fails, the return value is the win32 error code corresponding to // the error.
diff --git a/sandbox/win/src/acl_unittest.cc b/sandbox/win/src/acl_unittest.cc index b8ddb29..7584624a 100644 --- a/sandbox/win/src/acl_unittest.cc +++ b/sandbox/win/src/acl_unittest.cc
@@ -19,10 +19,9 @@ absl::optional<base::win::Sid> sddl_sid = base::win::Sid::FromSddlString(sddl); ASSERT_TRUE(sddl_sid); - absl::optional<base::win::Sid> integrity_sid = - GetIntegrityLevelSid(integrity_level); - ASSERT_TRUE(integrity_sid); - EXPECT_EQ(*sddl_sid, *integrity_sid); + absl::optional<DWORD> integrity_value = GetIntegrityLevelRid(integrity_level); + ASSERT_TRUE(integrity_value); + EXPECT_EQ(*sddl_sid, base::win::Sid::FromIntegrityLevel(*integrity_value)); } void CheckSetObjectIntegrityLabel(DWORD mandatory_policy, @@ -49,18 +48,17 @@ ASSERT_EQ(ace->Header.AceType, SYSTEM_MANDATORY_LABEL_ACE_TYPE); EXPECT_EQ(ace->Header.AceFlags, 0); EXPECT_EQ(ace->Mask, mandatory_policy); - absl::optional<base::win::Sid> integrity_sid = - GetIntegrityLevelSid(integrity_level); - ASSERT_TRUE(integrity_sid); + absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level); + base::win::Sid sid = base::win::Sid::FromIntegrityLevel(*rid); ASSERT_TRUE(::IsValidSid(&ace->SidStart)); - EXPECT_TRUE(integrity_sid->Equal(&ace->SidStart)); + EXPECT_TRUE(sid.Equal(&ace->SidStart)); } } // namespace -// Checks the functionality of GetIntegrityLevelSid. -TEST(AclTest, GetIntegrityLevelSid) { - EXPECT_FALSE(GetIntegrityLevelSid(INTEGRITY_LEVEL_LAST)); +// Checks the functionality of GetIntegrityLevelRid. +TEST(AclTest, GetIntegrityLevelRid) { + EXPECT_FALSE(GetIntegrityLevelRid(INTEGRITY_LEVEL_LAST)); CheckGetIntegrityLevelSid(INTEGRITY_LEVEL_SYSTEM, L"S-1-16-16384"); CheckGetIntegrityLevelSid(INTEGRITY_LEVEL_HIGH, L"S-1-16-12288"); CheckGetIntegrityLevelSid(INTEGRITY_LEVEL_MEDIUM, L"S-1-16-8192");
diff --git a/sandbox/win/src/app_container_base.cc b/sandbox/win/src/app_container_base.cc index 392fbb4..61c453e 100644 --- a/sandbox/win/src/app_container_base.cc +++ b/sandbox/win/src/app_container_base.cc
@@ -264,8 +264,8 @@ ResultCode AppContainerBase::BuildLowBoxToken(base::win::ScopedHandle* token) { if (type_ == AppContainerType::kLowbox) { - if (!CreateLowBoxToken(token->get(), PRIMARY, package_sid_, capabilities_, - token)) { + if (!CreateLowBoxToken(token->get(), TokenType::kPrimary, package_sid_, + capabilities_, token)) { return SBOX_ERROR_CANNOT_CREATE_LOWBOX_TOKEN; } @@ -274,8 +274,8 @@ package_sid_, TOKEN_ALL_ACCESS)) { return SBOX_ERROR_CANNOT_MODIFY_LOWBOX_TOKEN_DACL; } - } else if (!CreateLowBoxToken(nullptr, IMPERSONATION, package_sid_, - capabilities_, token)) { + } else if (!CreateLowBoxToken(nullptr, TokenType::kImpersonation, + package_sid_, capabilities_, token)) { return SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN; }
diff --git a/sandbox/win/src/filesystem_policy.cc b/sandbox/win/src/filesystem_policy.cc index 6d2387f1..1685cf59 100644 --- a/sandbox/win/src/filesystem_policy.cc +++ b/sandbox/win/src/filesystem_policy.cc
@@ -4,6 +4,9 @@ #include "sandbox/win/src/filesystem_policy.h" +#include <windows.h> +#include <winternl.h> + #include <ntstatus.h> #include <stdint.h> @@ -11,16 +14,36 @@ #include "base/notreached.h" #include "base/win/scoped_handle.h" +#include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/ipc_tags.h" +#include "sandbox/win/src/nt_internals.h" #include "sandbox/win/src/policy_engine_opcodes.h" #include "sandbox/win/src/policy_params.h" #include "sandbox/win/src/sandbox_nt_util.h" #include "sandbox/win/src/sandbox_types.h" -#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/win_utils.h" +namespace sandbox { + namespace { +struct ObjectAttribs : public OBJECT_ATTRIBUTES { + UNICODE_STRING uni_name; + SECURITY_QUALITY_OF_SERVICE security_qos; + ObjectAttribs(const std::wstring& name, ULONG attributes) { + ::RtlInitUnicodeString(&uni_name, name.c_str()); + InitializeObjectAttributes(this, &uni_name, attributes, nullptr, nullptr); + if (IsPipe(name)) { + security_qos.Length = sizeof(security_qos); + security_qos.ImpersonationLevel = SecurityAnonymous; + // Set dynamic tracking to not capture the broker's token + security_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + security_qos.EffectiveOnly = TRUE; + SecurityQualityOfService = &security_qos; + } + } +}; + NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle, ACCESS_MASK desired_access, OBJECT_ATTRIBUTES* obj_attributes, @@ -33,7 +56,7 @@ ULONG ea_length, HANDLE target_process) { HANDLE local_handle = INVALID_HANDLE_VALUE; - NTSTATUS status = sandbox::GetNtExports()->CreateFile( + NTSTATUS status = GetNtExports()->CreateFile( &local_handle, desired_access, obj_attributes, io_status_block, nullptr, file_attributes, share_access, create_disposition, create_options, ea_buffer, ea_length); @@ -41,7 +64,7 @@ return status; } - if (!sandbox::SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { + if (!SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { // The handle points somewhere else. Fail the operation. ::CloseHandle(local_handle); return STATUS_ACCESS_DENIED; @@ -55,22 +78,8 @@ return STATUS_SUCCESS; } -// Get an initialized anonymous level Security QOS. -SECURITY_QUALITY_OF_SERVICE GetAnonymousQOS() { - SECURITY_QUALITY_OF_SERVICE security_qos = {0}; - security_qos.Length = sizeof(security_qos); - security_qos.ImpersonationLevel = SecurityAnonymous; - // Set dynamic tracking so that a pipe doesn't capture the broker's token - security_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; - security_qos.EffectiveOnly = true; - - return security_qos; -} - } // namespace. -namespace sandbox { - bool FileSystemPolicy::GenerateRules(const wchar_t* name, Semantics semantics, LowLevelPolicy* policy) { @@ -198,12 +207,7 @@ return false; } IO_STATUS_BLOCK io_block = {}; - UNICODE_STRING uni_name = {}; - OBJECT_ATTRIBUTES obj_attributes = {}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name, - IsPipe(file) ? &security_qos : nullptr); + ObjectAttribs obj_attributes(file, attributes); *nt_status = NtCreateFileInTarget(handle, desired_access, &obj_attributes, &io_block, file_attributes, share_access, create_disposition, @@ -233,12 +237,8 @@ // An NtOpen is equivalent to an NtCreate with FileAttributes = 0 and // CreateDisposition = FILE_OPEN. IO_STATUS_BLOCK io_block = {}; - UNICODE_STRING uni_name = {}; - OBJECT_ATTRIBUTES obj_attributes = {}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); + ObjectAttribs obj_attributes(file, attributes); - InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name, - IsPipe(file) ? &security_qos : nullptr); *nt_status = NtCreateFileInTarget( handle, desired_access, &obj_attributes, &io_block, 0, share_access, FILE_OPEN, open_options, nullptr, 0, client_info.process); @@ -261,12 +261,7 @@ return false; } - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name, - IsPipe(file) ? &security_qos : nullptr); + ObjectAttribs obj_attributes(file, attributes); *nt_status = GetNtExports()->QueryAttributesFile(&obj_attributes, file_info); return true; @@ -285,12 +280,7 @@ *nt_status = STATUS_ACCESS_DENIED; return false; } - UNICODE_STRING uni_name = {0}; - OBJECT_ATTRIBUTES obj_attributes = {0}; - SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS(); - - InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name, - IsPipe(file) ? &security_qos : nullptr); + ObjectAttribs obj_attributes(file, attributes); *nt_status = GetNtExports()->QueryFullAttributesFile(&obj_attributes, file_info);
diff --git a/sandbox/win/src/policy_target_test.cc b/sandbox/win/src/policy_target_test.cc index 4faeb50..969c4bac 100644 --- a/sandbox/win/src/policy_target_test.cc +++ b/sandbox/win/src/policy_target_test.cc
@@ -15,7 +15,6 @@ #include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/sandbox_policy.h" -#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/target_services.h" #include "sandbox/win/tests/common/controller.h" #include "testing/gtest/include/gtest/gtest.h" @@ -526,31 +525,6 @@ ::WaitForSingleObject(target.process_handle(), INFINITE); } -// Dummy target that just reports that's it spawned correctly. -SBOX_TESTS_COMMAND int PolicyTargetTest_SetEffectiveToken(int argc, - wchar_t** argv) { - return SBOX_TEST_SUCCEEDED; -} - -// Test whether after using SetEffectiveToken spawning a target works as -// expected. -TEST(PolicyTargetTest, SetEffectiveToken) { - TestRunner runner; - HANDLE token; - - // Get current process token. - EXPECT_TRUE( - ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); - - // Setup token guard. - base::win::ScopedHandle token_guard(token); - - // Set token and run target. - runner.GetPolicy()->SetEffectiveToken(token_guard.Get()); - EXPECT_EQ(SBOX_TEST_SUCCEEDED, - runner.RunTest(L"PolicyTargetTest_SetEffectiveToken")); -} - // Test if shared policies can be created by the broker. TEST(SharedTargetConfig, BrokerConfigManagement) { BrokerServices* broker = GetBroker();
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc index a4d8757b..2b2b5c1 100644 --- a/sandbox/win/src/restricted_token.cc +++ b/sandbox/win/src/restricted_token.cc
@@ -9,314 +9,221 @@ #include <stddef.h> #include <memory> -#include <unordered_set> +#include <utility> #include <vector> #include "base/logging.h" +#include "base/ranges/algorithm.h" #include "base/win/access_token.h" +#include "base/win/security_util.h" #include "sandbox/win/src/acl.h" -namespace { - -std::vector<SID_AND_ATTRIBUTES> ConvertToAttributes( - const std::vector<base::win::Sid>& sids, - DWORD attributes) { - std::vector<SID_AND_ATTRIBUTES> ret(sids.size()); - for (size_t i = 0; i < sids.size(); ++i) { - ret[i].Attributes = attributes; - ret[i].Sid = sids[i].GetPSID(); - } - return ret; -} - -bool DeletePrivilege(const base::win::ScopedHandle& token, - const wchar_t* name) { - TOKEN_PRIVILEGES privs = {}; - privs.PrivilegeCount = 1; - if (!::LookupPrivilegeValue(nullptr, name, &privs.Privileges[0].Luid)) - return false; - privs.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED; - return !!::AdjustTokenPrivileges(token.Get(), FALSE, &privs, 0, nullptr, - nullptr); -} - -} // namespace - namespace sandbox { -RestrictedToken::RestrictedToken() - : integrity_level_(INTEGRITY_LEVEL_LAST), - init_(false), - lockdown_default_dacl_(false), - delete_all_privileges_(false), - remove_traversal_privilege_(false) {} +RestrictedToken::RestrictedToken() = default; +RestrictedToken::~RestrictedToken() = default; -RestrictedToken::~RestrictedToken() {} - -DWORD RestrictedToken::Init(const HANDLE effective_token) { - if (init_) - return ERROR_ALREADY_INITIALIZED; - - HANDLE temp_token; - if (effective_token) { - // We duplicate the handle to be able to use it even if the original handle - // is closed. - if (!::DuplicateHandle(::GetCurrentProcess(), effective_token, - ::GetCurrentProcess(), &temp_token, 0, false, - DUPLICATE_SAME_ACCESS)) { - return ::GetLastError(); - } - } else { - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, - &temp_token)) { - return ::GetLastError(); - } +absl::optional<base::win::AccessToken> RestrictedToken::GetRestrictedToken() + const { + absl::optional<base::win::AccessToken> token = + base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false, + TOKEN_ALL_ACCESS); + if (!token) { + return absl::nullopt; } - effective_token_.Set(temp_token); - absl::optional<base::win::AccessToken> query_token = - base::win::AccessToken::FromToken(effective_token_.Get()); - if (!query_token) - return ERROR_NO_TOKEN; - query_token_.swap(query_token); - - init_ = true; - return ERROR_SUCCESS; + return CreateRestricted(*token); } -DWORD RestrictedToken::GetRestrictedToken( - base::win::ScopedHandle* token) const { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - std::vector<SID_AND_ATTRIBUTES> deny_sids = - ConvertToAttributes(sids_for_deny_only_, SE_GROUP_USE_FOR_DENY_ONLY); - std::vector<SID_AND_ATTRIBUTES> restrict_sids = - ConvertToAttributes(sids_to_restrict_, 0); - - bool result = true; - HANDLE new_token_handle = nullptr; - if (!deny_sids.empty() || !restrict_sids.empty() || delete_all_privileges_) { - result = ::CreateRestrictedToken( - effective_token_.Get(), - delete_all_privileges_ ? DISABLE_MAX_PRIVILEGE : 0, - static_cast<DWORD>(deny_sids.size()), deny_sids.data(), 0, nullptr, - static_cast<DWORD>(restrict_sids.size()), restrict_sids.data(), - &new_token_handle); - } else { - // Duplicate the token even if it's not modified at this point - // because any subsequent changes to this token would also affect the - // current process. - result = ::DuplicateTokenEx(effective_token_.Get(), TOKEN_ALL_ACCESS, - nullptr, SecurityIdentification, TokenPrimary, - &new_token_handle); - } - - if (!result) - return ::GetLastError(); - - base::win::ScopedHandle new_token(new_token_handle); - if (delete_all_privileges_ && remove_traversal_privilege_) { - if (!DeletePrivilege(new_token, SE_CHANGE_NOTIFY_NAME)) - return ::GetLastError(); - } - - if (lockdown_default_dacl_) { - // Don't add Restricted sid and also remove logon sid access. - if (!RevokeLogonSidFromDefaultDacl(new_token.Get())) - return ::GetLastError(); - } else { - // Modify the default dacl on the token to contain Restricted. - if (!AddSidToDefaultDacl( - new_token.Get(), base::win::WellKnownSid::kRestricted, - base::win::SecurityAccessMode::kGrant, GENERIC_ALL)) { - return ::GetLastError(); - } - } - - for (const auto& default_dacl_sid : sids_for_default_dacl_) { - if (!AddSidToDefaultDacl(new_token.Get(), std::get<0>(default_dacl_sid), - std::get<1>(default_dacl_sid), - std::get<2>(default_dacl_sid))) { - return ::GetLastError(); - } - } - - // Add user to default dacl. - if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL)) - return ::GetLastError(); - - DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_); - if (ERROR_SUCCESS != error) - return error; - - HANDLE token_handle; - if (!::DuplicateHandle(::GetCurrentProcess(), new_token.Get(), - ::GetCurrentProcess(), &token_handle, TOKEN_ALL_ACCESS, - false, // Don't inherit. - 0)) { - return ::GetLastError(); - } - - token->Set(token_handle); - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::GetRestrictedTokenForImpersonation( - base::win::ScopedHandle* token) const { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - base::win::ScopedHandle restricted_token; - DWORD err_code = GetRestrictedToken(&restricted_token); - if (ERROR_SUCCESS != err_code) - return err_code; - - HANDLE impersonation_token_handle; - if (!::DuplicateTokenEx(restricted_token.Get(), TOKEN_ALL_ACCESS, nullptr, - SecurityImpersonation, TokenImpersonation, - &impersonation_token_handle)) { - return ::GetLastError(); - } - token->Set(impersonation_token_handle); - return ERROR_SUCCESS; -} - -DWORD RestrictedToken::AddAllSidsForDenyOnly( +void RestrictedToken::AddAllSidsForDenyOnly( const std::vector<base::win::Sid>& exceptions) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - // Build the list of the deny only group SIDs - for (const base::win::AccessToken::Group& group : query_token_->Groups()) { - if (group.IsIntegrity() || group.IsLogonId()) - continue; - bool should_ignore = false; - for (const base::win::Sid& sid : exceptions) { - if (sid == group.GetSid()) { - should_ignore = true; - break; - } - } - if (!should_ignore) { - sids_for_deny_only_.push_back(group.GetSid().Clone()); - } - } - - return ERROR_SUCCESS; + add_all_sids_for_deny_only_ = true; + add_all_exceptions_ = base::win::CloneSidVector(exceptions); } -DWORD RestrictedToken::AddSidForDenyOnly(const base::win::Sid& sid) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - +void RestrictedToken::AddSidForDenyOnly(const base::win::Sid& sid) { sids_for_deny_only_.push_back(sid.Clone()); - return ERROR_SUCCESS; } -DWORD RestrictedToken::AddSidForDenyOnly(base::win::WellKnownSid known_sid) { - return AddSidForDenyOnly(base::win::Sid(known_sid)); +void RestrictedToken::AddSidForDenyOnly(base::win::WellKnownSid known_sid) { + sids_for_deny_only_.emplace_back(known_sid); } -DWORD RestrictedToken::AddUserSidForDenyOnly() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - sids_for_deny_only_.push_back(query_token_->User()); - return ERROR_SUCCESS; +void RestrictedToken::AddUserSidForDenyOnly() { + add_user_sid_for_deny_only_ = true; } -DWORD RestrictedToken::DeleteAllPrivileges(bool remove_traversal_privilege) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; +void RestrictedToken::DeleteAllPrivileges(bool remove_traversal_privilege) { delete_all_privileges_ = true; remove_traversal_privilege_ = remove_traversal_privilege; - return ERROR_SUCCESS; } -DWORD RestrictedToken::AddRestrictingSid(const base::win::Sid& sid) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - sids_to_restrict_.push_back(sid.Clone()); // No attributes - return ERROR_SUCCESS; +void RestrictedToken::AddRestrictingSid(const base::win::Sid& sid) { + sids_to_restrict_.push_back(sid.Clone()); } -DWORD RestrictedToken::AddRestrictingSid(base::win::WellKnownSid known_sid) { - return AddRestrictingSid(base::win::Sid(known_sid)); +void RestrictedToken::AddRestrictingSid(base::win::WellKnownSid known_sid) { + sids_to_restrict_.emplace_back(known_sid); } -DWORD RestrictedToken::AddRestrictingSidLogonSession() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - absl::optional<base::win::Sid> logon_sid = query_token_->LogonId(); - if (logon_sid) - sids_to_restrict_.push_back(std::move(*logon_sid)); - return ERROR_SUCCESS; +void RestrictedToken::AddRestrictingSidLogonSession() { + add_restricting_sid_logon_session_ = true; } -DWORD RestrictedToken::AddRestrictingSidCurrentUser() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - sids_to_restrict_.push_back(query_token_->User()); - return ERROR_SUCCESS; +void RestrictedToken::AddRestrictingSidCurrentUser() { + add_restricting_sid_current_user_ = true; } -DWORD RestrictedToken::AddRestrictingSidAllSids() { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - // Add the current user to the list. - DWORD error = AddRestrictingSidCurrentUser(); - if (ERROR_SUCCESS != error) - return error; - - for (const base::win::AccessToken::Group& group : query_token_->Groups()) { - if (group.IsIntegrity()) - continue; - AddRestrictingSid(group.GetSid()); - } - - return ERROR_SUCCESS; +void RestrictedToken::AddRestrictingSidAllSids() { + add_restricting_sid_all_sids_ = true; + AddRestrictingSidCurrentUser(); } -DWORD RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) { - integrity_level_ = integrity_level; - return ERROR_SUCCESS; +void RestrictedToken::SetIntegrityLevel(IntegrityLevel integrity_level) { + integrity_rid_ = GetIntegrityLevelRid(integrity_level); } void RestrictedToken::SetLockdownDefaultDacl() { lockdown_default_dacl_ = true; } -DWORD RestrictedToken::AddDefaultDaclSid( +void RestrictedToken::AddDefaultDaclSid( const base::win::Sid& sid, base::win::SecurityAccessMode access_mode, ACCESS_MASK access) { - DCHECK(init_); - if (!init_) - return ERROR_NO_TOKEN; - - sids_for_default_dacl_.push_back( - std::make_tuple(sid.Clone(), access_mode, access)); - return ERROR_SUCCESS; + sids_for_default_dacl_.emplace_back(sid.Clone(), access_mode, access, 0); } -DWORD RestrictedToken::AddDefaultDaclSid( +void RestrictedToken::AddDefaultDaclSid( base::win::WellKnownSid known_sid, base::win::SecurityAccessMode access_mode, ACCESS_MASK access) { - return AddDefaultDaclSid(base::win::Sid(known_sid), access_mode, access); + sids_for_default_dacl_.emplace_back(known_sid, access_mode, access, 0); +} + +absl::optional<base::win::AccessToken> +RestrictedToken::GetRestrictedTokenForTesting(base::win::AccessToken& token) { + return CreateRestricted(token); +} + +std::vector<base::win::Sid> RestrictedToken::BuildDenyOnlySids( + const base::win::AccessToken& token) const { + std::vector<base::win::Sid> sids = + base::win::CloneSidVector(sids_for_deny_only_); + if (add_user_sid_for_deny_only_) { + sids.push_back(token.User()); + } + if (add_all_sids_for_deny_only_) { + // Build the list of the deny only group SIDs + for (const base::win::AccessToken::Group& group : token.Groups()) { + if (group.IsIntegrity() || group.IsLogonId()) { + continue; + } + if (base::ranges::find(add_all_exceptions_, group.GetSid()) == + add_all_exceptions_.end()) { + sids.push_back(group.GetSid().Clone()); + } + } + } + return sids; +} + +std::vector<base::win::Sid> RestrictedToken::BuildRestrictedSids( + const base::win::AccessToken& token) const { + std::vector<base::win::Sid> sids = + base::win::CloneSidVector(sids_to_restrict_); + if (add_restricting_sid_current_user_) { + sids.push_back(token.User()); + } + if (add_restricting_sid_all_sids_) { + for (const base::win::AccessToken::Group& group : token.Groups()) { + if (group.IsIntegrity()) { + continue; + } + sids.push_back(group.GetSid().Clone()); + } + } + if (add_restricting_sid_logon_session_) { + absl::optional<base::win::Sid> logon_sid = token.LogonId(); + if (logon_sid.has_value()) { + sids.push_back(std::move(*logon_sid)); + } + } + return sids; +} + +absl::optional<base::win::AccessToken> RestrictedToken::CreateRestricted( + base::win::AccessToken& token) const { + absl::optional<base::win::AccessToken> new_token; + + std::vector<base::win::Sid> deny_sids = BuildDenyOnlySids(token); + std::vector<base::win::Sid> restrict_sids = BuildRestrictedSids(token); + if (!deny_sids.empty() || !restrict_sids.empty() || delete_all_privileges_) { + new_token = token.CreateRestricted( + delete_all_privileges_ ? DISABLE_MAX_PRIVILEGE : 0, deny_sids, {}, + restrict_sids, TOKEN_ALL_ACCESS); + } else { + // Duplicate the token even if it's not modified at this point + // because any subsequent changes to this token would also affect the + // current process. + new_token = token.DuplicatePrimary(TOKEN_ALL_ACCESS); + } + + if (!new_token) { + return absl::nullopt; + } + + if (delete_all_privileges_ && remove_traversal_privilege_ && + !new_token->RemovePrivilege(SE_CHANGE_NOTIFY_NAME)) { + return absl::nullopt; + } + + std::vector<base::win::ExplicitAccessEntry> dacl_entries; + + absl::optional<base::win::AccessControlList> dacl = new_token->DefaultDacl(); + if (!dacl) { + return absl::nullopt; + } + + if (lockdown_default_dacl_) { + // Don't add Restricted sid and also remove logon sid access. + absl::optional<base::win::Sid> logon_sid = new_token->LogonId(); + if (logon_sid.has_value()) { + dacl_entries.emplace_back(*logon_sid, + base::win::SecurityAccessMode::kRevoke, 0, 0); + } else { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_NOT_FOUND) { + return absl::nullopt; + } + } + } else { + dacl_entries.emplace_back(base::win::WellKnownSid::kRestricted, + base::win::SecurityAccessMode::kGrant, + GENERIC_ALL, 0); + } + + for (const base::win::ExplicitAccessEntry& entry : sids_for_default_dacl_) { + dacl_entries.push_back(entry.Clone()); + } + + dacl_entries.emplace_back( + new_token->User(), base::win::SecurityAccessMode::kGrant, GENERIC_ALL, 0); + + if (!dacl->SetEntries(dacl_entries)) { + return absl::nullopt; + } + + if (!new_token->SetDefaultDacl(*dacl)) { + return absl::nullopt; + } + + if (integrity_rid_.has_value()) { + if (!new_token->SetIntegrityLevel(*integrity_rid_)) { + return absl::nullopt; + } + } + + return new_token; } } // namespace sandbox
diff --git a/sandbox/win/src/restricted_token.h b/sandbox/win/src/restricted_token.h index 7e007fd3..2cb9031 100644 --- a/sandbox/win/src/restricted_token.h +++ b/sandbox/win/src/restricted_token.h
@@ -7,15 +7,10 @@ #include <vector> -#include <string> -#include <tuple> - +#include "base/win/access_control_list.h" #include "base/win/access_token.h" -#include "base/win/scoped_handle.h" #include "base/win/sid.h" #include "base/win/windows_types.h" -#include "sandbox/win/src/acl.h" -#include "sandbox/win/src/restricted_token_utils.h" #include "sandbox/win/src/security_level.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -25,22 +20,15 @@ // any token handle. // Sample usage: // RestrictedToken restricted_token; -// DWORD err_code = restricted_token.Init(nullptr); // Use the current -// // effective token -// if (ERROR_SUCCESS != err_code) { -// // handle error. -// } // -// restricted_token.AddRestrictingSid(ATL::Sids::Users().GetPSID()); -// base::win::ScopedHandle token_handle; -// err_code = restricted_token.GetRestrictedToken(&token_handle); -// if (ERROR_SUCCESS != err_code) { +// restricted_token.AddRestrictingSid(base::win::WellKnownSid::kUsers); +// auto token = restricted_token.GetRestrictedToken(); +// if (!token) { // // handle error. // } // [...] class RestrictedToken { public: - // Init() has to be called before calling any other method in the class. RestrictedToken(); RestrictedToken(const RestrictedToken&) = delete; @@ -48,79 +36,46 @@ ~RestrictedToken(); - // Initializes the RestrictedToken object with effective_token. - // If effective_token is nullptr, it initializes the RestrictedToken object - // with the effective token of the current process. - DWORD Init(HANDLE effective_token); - - // Creates a restricted token. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD GetRestrictedToken(base::win::ScopedHandle* token) const; - - // Creates a restricted token and uses this new token to create a new token - // for impersonation. Returns this impersonation token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // - // The sample usage is the same as the GetRestrictedToken function. - DWORD GetRestrictedTokenForImpersonation( - base::win::ScopedHandle* token) const; + // Creates a restricted token. This creates a primary token for process + // creation. If the function fails an empty value is returned. + absl::optional<base::win::AccessToken> GetRestrictedToken() const; // Lists all sids in the token and mark them as Deny Only except for those // present in the exceptions parameter. If there is no exception needed, // the caller can pass an empty list or nullptr for the exceptions // parameter. // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - // // Sample usage: // std::vector<base::win::Sid> sid_exceptions; - // sid_exceptions.push_back(*base::win::Sid::FromPSID(psid)); + // sid_exceptions.emplace_back(base::win::WellKnownSid::kWorld); // restricted_token.AddAllSidsForDenyOnly(sid_exceptions); // Note: A Sid marked for Deny Only in a token cannot be used to grant // access to any resource. It can only be used to deny access. - DWORD AddAllSidsForDenyOnly(const std::vector<base::win::Sid>& exceptions); + void AddAllSidsForDenyOnly(const std::vector<base::win::Sid>& exceptions); // Adds a user or group SID for Deny Only in the restricted token. - // Parameter: sid is the SID to add in the Deny Only list. - // The return value is always ERROR_SUCCESS. + // `sid` is the SID to add in the Deny Only list. // // Sample Usage: // restricted_token.AddSidForDenyOnly(sid); - DWORD AddSidForDenyOnly(const base::win::Sid& sid); + void AddSidForDenyOnly(const base::win::Sid& sid); // Adds a known SID for Deny Only in the restricted token. - // Parameter: known_sid is the SID to add in the Deny Only list. - // The return value is always ERROR_SUCCESS. - // + // `known_sid` is the SID to add in the Deny Only list. // Sample Usage: // restricted_token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld); - DWORD AddSidForDenyOnly(base::win::WellKnownSid known_sid); + void AddSidForDenyOnly(base::win::WellKnownSid known_sid); // Adds the user sid of the token for Deny Only in the restricted token. - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddUserSidForDenyOnly(); + void AddUserSidForDenyOnly(); // Specify to remove all privileges in the restricted token. By default this // will not remove SeChangeNotifyPrivilege, however you can specify true for - // |remove_traversal_privilege| to remove that privilege as well. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD DeleteAllPrivileges(bool remove_traversal_privilege); + // `remove_traversal_privilege` to remove that privilege as well. + void DeleteAllPrivileges(bool remove_traversal_privilege); // Adds a SID to the list of restricting sids in the restricted token. - // Parameter: sid is the sid to add to the list restricting sids. - // The return value is always ERROR_SUCCESS. + // `sid` is the sid to add to the list restricting sids. // // Sample usage: // restricted_token.AddRestrictingSid(ATL::Sids::Users().GetPSID()); @@ -128,46 +83,33 @@ // access checks twice. The first time using your user SID and your groups, // and the second time using your list of restricting sids. The access has // to be granted in both places to get access to the resource requested. - DWORD AddRestrictingSid(const base::win::Sid& sid); + void AddRestrictingSid(const base::win::Sid& sid); // Adds a known SID to the list of restricting sids in the restricted token. - // Parameter: known_sid is the sid to add to the list restricting sids. - // The return value is always ERROR_SUCCESS. - // + // `known_sid` is the sid to add to the list restricting sids. + // Sample usage: // restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld); // Note: The list of restricting is used to force Windows to perform all // access checks twice. The first time using your user SID and your groups, // and the second time using your list of restricting sids. The access has // to be granted in both places to get access to the resource requested. - DWORD AddRestrictingSid(base::win::WellKnownSid known_sid); + void AddRestrictingSid(base::win::WellKnownSid known_sid); // Adds the logon sid of the token in the list of restricting sids for the // restricted token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidLogonSession(); + void AddRestrictingSidLogonSession(); // Adds the owner sid of the token in the list of restricting sids for the // restricted token. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidCurrentUser(); + void AddRestrictingSidCurrentUser(); // Adds all group sids and the user sid to the restricting sids list. - // - // If the function succeeds, the return value is ERROR_SUCCESS. If the - // function fails, the return value is the win32 error code corresponding to - // the error. - DWORD AddRestrictingSidAllSids(); + void AddRestrictingSidAllSids(); // Sets the token integrity level. The integrity level cannot be higher than // your current integrity level. - DWORD SetIntegrityLevel(IntegrityLevel integrity_level); + void SetIntegrityLevel(IntegrityLevel integrity_level); // Set a flag which indicates the created token should have a locked down // default DACL when created. @@ -175,39 +117,57 @@ // Add a SID to the default DACL. These SIDs are added regardless of the // SetLockdownDefaultDacl state. - DWORD AddDefaultDaclSid(const base::win::Sid& sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access); + void AddDefaultDaclSid(const base::win::Sid& sid, + base::win::SecurityAccessMode access_mode, + ACCESS_MASK access); // Add a SID to the default DACL. These SIDs are added regardless of the // SetLockdownDefaultDacl state. - DWORD AddDefaultDaclSid(base::win::WellKnownSid known_sid, - base::win::SecurityAccessMode access_mode, - ACCESS_MASK access); + void AddDefaultDaclSid(base::win::WellKnownSid known_sid, + base::win::SecurityAccessMode access_mode, + ACCESS_MASK access); + + // Creates a restricted token. This is only used for testing to change the + // token used to build the restricted token. + absl::optional<base::win::AccessToken> GetRestrictedTokenForTesting( + base::win::AccessToken& token); private: + std::vector<base::win::Sid> BuildDenyOnlySids( + const base::win::AccessToken& token) const; + std::vector<base::win::Sid> BuildRestrictedSids( + const base::win::AccessToken& token) const; + absl::optional<base::win::AccessToken> CreateRestricted( + base::win::AccessToken& token) const; + // The list of restricting sids in the restricted token. std::vector<base::win::Sid> sids_to_restrict_; // The list of sids to mark as Deny Only in the restricted token. std::vector<base::win::Sid> sids_for_deny_only_; // The list of sids to add to the default DACL of the restricted token. - std::vector< - std::tuple<base::win::Sid, base::win::SecurityAccessMode, ACCESS_MASK>> - sids_for_default_dacl_; - // The token to restrict. Can only be set in a constructor. - base::win::ScopedHandle effective_token_; - // The token in a form for querying. - absl::optional<base::win::AccessToken> query_token_; - // The token integrity level. - IntegrityLevel integrity_level_; - // Tells if the object is initialized or not (if Init() has been called) - bool init_; + std::vector<base::win::ExplicitAccessEntry> sids_for_default_dacl_; + // The token to restrict, this is only used for testing. + absl::optional<base::win::AccessToken> effective_token_; + // The token integrity level RID. + absl::optional<DWORD> integrity_rid_; // Lockdown the default DACL when creating new tokens. - bool lockdown_default_dacl_; + bool lockdown_default_dacl_ = false; // Delete all privileges except for SeChangeNotifyPrivilege. - bool delete_all_privileges_; + bool delete_all_privileges_ = false; // Also delete SeChangeNotifyPrivilege if delete_all_privileges_ is true. - bool remove_traversal_privilege_; + bool remove_traversal_privilege_ = false; + // Add all SIDs for deny only. + bool add_all_sids_for_deny_only_ = false; + // The list of exceptions when adding all SIDs for deny only. + std::vector<base::win::Sid> add_all_exceptions_; + // Add the user's sid to the deny only list. + bool add_user_sid_for_deny_only_ = false; + // Add the logon session SID to the restricted SID list. + bool add_restricting_sid_logon_session_ = false; + // Add the current user SID to the restricted SID list. + bool add_restricting_sid_current_user_ = false; + // Add all SIDs to the restricted SIDs. + bool add_restricting_sid_all_sids_ = false; }; } // namespace sandbox
diff --git a/sandbox/win/src/restricted_token_unittest.cc b/sandbox/win/src/restricted_token_unittest.cc index 0312949..6d34c8e 100644 --- a/sandbox/win/src/restricted_token_unittest.cc +++ b/sandbox/win/src/restricted_token_unittest.cc
@@ -6,14 +6,20 @@ #include "sandbox/win/src/restricted_token.h" +#include <windows.h> + #include <utility> #include <vector> +#include "base/ranges/algorithm.h" +#include "base/win/access_control_list.h" #include "base/win/access_token.h" -#include "base/win/atl.h" #include "base/win/scoped_handle.h" +#include "base/win/security_descriptor.h" +#include "base/win/security_util.h" #include "base/win/sid.h" #include "sandbox/win/src/acl.h" +#include "sandbox/win/src/restricted_token_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -21,106 +27,69 @@ namespace { -void TestDefaultDalc(bool restricted_required, bool additional_sid_required) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - if (!restricted_required) - token.SetLockdownDefaultDacl(); - ATL::CSid additional_sid = ATL::Sids::Guests(); - ATL::CSid additional_sid2 = ATL::Sids::Batch(); - if (additional_sid_required) { - token.AddDefaultDaclSid( - *base::win::Sid::FromPSID(const_cast<SID*>(additional_sid.GetPSID())), - base::win::SecurityAccessMode::kGrant, READ_CONTROL); - token.AddDefaultDaclSid( - *base::win::Sid::FromPSID(const_cast<SID*>(additional_sid2.GetPSID())), - base::win::SecurityAccessMode::kDeny, GENERIC_ALL); - } - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(base::win::WellKnownSid::kWorld)); - - base::win::ScopedHandle handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&handle)); - - ATL::CAccessToken restricted_token; - restricted_token.Attach(handle.Take()); - - ATL::CDacl dacl; - ASSERT_TRUE(restricted_token.GetDefaultDacl(&dacl)); - - ATL::CSid logon_sid; - ASSERT_TRUE(restricted_token.GetLogonSid(&logon_sid)); - - bool restricted_found = false; - bool logon_sid_found = false; - bool additional_sid_found = false; - bool additional_sid2_found = false; - - unsigned int ace_count = dacl.GetAceCount(); - for (unsigned int i = 0; i < ace_count; ++i) { - ATL::CSid sid; - ACCESS_MASK mask = 0; - BYTE ace_type = 0; - dacl.GetAclEntry(i, &sid, &mask, &ace_type); - if (sid == ATL::Sids::RestrictedCode() && mask == GENERIC_ALL) { - restricted_found = true; - } else if (sid == logon_sid) { - logon_sid_found = true; - } else if (sid == additional_sid && mask == READ_CONTROL && - ace_type == ACCESS_ALLOWED_ACE_TYPE) { - additional_sid_found = true; - } else if (sid == additional_sid2 && mask == GENERIC_ALL && - ace_type == ACCESS_DENIED_ACE_TYPE) { - additional_sid2_found = true; +bool IsSidInDacl(const base::win::AccessControlList& dacl, + bool allowed, + absl::optional<ACCESS_MASK> mask, + const base::win::Sid& sid) { + DWORD ace_type = allowed ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE; + PACL pacl = dacl.get(); + for (unsigned int i = 0; i < pacl->AceCount; ++i) { + // Allowed and deny ACEs have the same structure. + PACCESS_ALLOWED_ACE ace; + CHECK(::GetAce(pacl, i, reinterpret_cast<LPVOID*>(&ace))); + if (ace->Header.AceType == ace_type && sid.Equal(&ace->SidStart) && + (!mask.has_value() || mask == ace->Mask)) { + return true; } } + return false; +} - ASSERT_EQ(restricted_required, restricted_found); - ASSERT_EQ(additional_sid_required, additional_sid_found); - ASSERT_EQ(additional_sid_required, additional_sid2_found); +void TestDefaultDacl(bool restricted_required, bool additional_sid_required) { + RestrictedToken token; + if (!restricted_required) - ASSERT_FALSE(logon_sid_found); + token.SetLockdownDefaultDacl(); + base::win::Sid additional_sid(base::win::WellKnownSid::kBuiltinGuests); + base::win::Sid additional_sid2(base::win::WellKnownSid::kBatch); + if (additional_sid_required) { + token.AddDefaultDaclSid( + additional_sid, base::win::SecurityAccessMode::kGrant, READ_CONTROL); + token.AddDefaultDaclSid(additional_sid2, + base::win::SecurityAccessMode::kDeny, GENERIC_ALL); + } + + token.AddRestrictingSid(base::win::WellKnownSid::kWorld); + auto restricted_token = *token.GetRestrictedToken(); + auto dacl = *restricted_token.DefaultDacl(); + + EXPECT_EQ(restricted_required, + IsSidInDacl(dacl, true, GENERIC_ALL, + base::win::Sid(base::win::WellKnownSid::kRestricted))); + EXPECT_EQ(additional_sid_required, + IsSidInDacl(dacl, true, READ_CONTROL, additional_sid)); + EXPECT_EQ(additional_sid_required, + IsSidInDacl(dacl, false, GENERIC_ALL, additional_sid2)); + auto logon_sid = restricted_token.LogonId(); + if (logon_sid) { + EXPECT_EQ(restricted_required, + IsSidInDacl(dacl, true, absl::nullopt, *logon_sid)); + } } void CheckDaclForPackageSid(const base::win::ScopedHandle& token, const base::win::Sid& package_sid, bool package_sid_required) { - DWORD length_needed = 0; - ::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, nullptr, 0, - &length_needed); - ASSERT_EQ(::GetLastError(), DWORD{ERROR_INSUFFICIENT_BUFFER}); + auto sd = *base::win::SecurityDescriptor::FromHandle( + token.get(), base::win::SecurityObjectType::kKernel, + DACL_SECURITY_INFORMATION); - std::vector<char> security_desc_buffer(length_needed); - SECURITY_DESCRIPTOR* security_desc = - reinterpret_cast<SECURITY_DESCRIPTOR*>(security_desc_buffer.data()); - - ASSERT_TRUE(::GetKernelObjectSecurity(token.Get(), DACL_SECURITY_INFORMATION, - security_desc, length_needed, - &length_needed)); - - ATL::CSecurityDesc token_sd(*security_desc); - ATL::CDacl dacl; - ASSERT_TRUE(token_sd.GetDacl(&dacl)); - - base::win::Sid all_package_sid( - base::win::WellKnownSid::kAllApplicationPackages); - - unsigned int ace_count = dacl.GetAceCount(); - for (unsigned int i = 0; i < ace_count; ++i) { - ATL::CSid sid; - ACCESS_MASK mask = 0; - BYTE type = 0; - dacl.GetAclEntry(i, &sid, &mask, &type); - if (mask != TOKEN_ALL_ACCESS || type != ACCESS_ALLOWED_ACE_TYPE) - continue; - PSID psid = const_cast<SID*>(sid.GetPSID()); - if (package_sid.Equal(psid)) - EXPECT_TRUE(package_sid_required); - else if (all_package_sid.Equal(psid)) - EXPECT_FALSE(package_sid_required); - } + EXPECT_EQ(package_sid_required, + IsSidInDacl(*sd.dacl(), true, TOKEN_ALL_ACCESS, package_sid)); + EXPECT_NE(package_sid_required, + IsSidInDacl(*sd.dacl(), true, TOKEN_ALL_ACCESS, + base::win::Sid( + base::win::WellKnownSid::kAllApplicationPackages))); } void CheckLowBoxToken(const base::win::ScopedHandle& lowbox_token, @@ -142,12 +111,13 @@ CheckDaclForPackageSid(lowbox_token, package_sid, true); } -// Checks if a sid is in the restricting list of the restricted token. +// Checks if a sid is or is not in the restricting list of the restricted token. // Asserts if it's not the case. If count is a positive number, the number of // elements in the restricting sids list has to be equal. void CheckRestrictingSid(const base::win::AccessToken& token, const base::win::Sid& sid, - int count) { + int count, + bool check_present = true) { auto restricted_sids = token.RestrictedSids(); if (count >= 0) ASSERT_EQ(static_cast<unsigned>(count), restricted_sids.size()); @@ -160,7 +130,7 @@ } } - ASSERT_TRUE(present); + ASSERT_EQ(present, check_present); } void CheckRestrictingSid(const base::win::AccessToken& token, @@ -196,137 +166,182 @@ } base::win::AccessToken GetPrimaryToken(ACCESS_MASK desired_access) { + return *base::win::AccessToken::FromCurrentProcess(false, TOKEN_DUPLICATE) + ->DuplicatePrimary(desired_access); +} + +void CheckUniqueSid(TokenLevel level, bool check_present) { + absl::optional<base::win::Sid> random_sid = + base::win::Sid::GenerateRandomSid(); + auto token = *CreateRestrictedToken(level, INTEGRITY_LEVEL_LAST, + TokenType::kPrimary, false, random_sid); + CheckRestrictingSid(token, *random_sid, -1, check_present); + auto dacl = *token.DefaultDacl(); + EXPECT_TRUE(IsSidInDacl(dacl, true, GENERIC_ALL, *random_sid)); + EXPECT_TRUE(IsSidInDacl( + dacl, true, READ_CONTROL, + base::win::Sid(base::win::WellKnownSid::kCreatorOwnerRights))); +} + +void CheckIntegrityLevel(IntegrityLevel integrity_level) { absl::optional<base::win::AccessToken> token = - base::win::AccessToken::FromCurrentProcess(false, TOKEN_DUPLICATE); - CHECK(token); - token = token->DuplicatePrimary(desired_access); - CHECK(token); - return std::move(*token); + CreateRestrictedToken(USER_LOCKDOWN, integrity_level, TokenType::kPrimary, + false, absl::nullopt); + ASSERT_TRUE(token); + absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level); + if (rid) { + EXPECT_EQ(token->IntegrityLevel(), *rid); + } else { + EXPECT_EQ(token->IntegrityLevel(), GetPrimaryToken(0).IntegrityLevel()); + } +} + +void CheckPrivileges(TokenLevel level, bool delete_all, bool remove_traversal) { + absl::optional<base::win::AccessToken> token = CreateRestrictedToken( + level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt); + ASSERT_TRUE(token); + std::vector<base::win::AccessToken::Privilege> privs = token->Privileges(); + if (remove_traversal) { + EXPECT_EQ(privs.size(), 0U); + } else if (delete_all) { + EXPECT_EQ(privs.size(), 1U); + EXPECT_EQ(privs[0].GetName(), SE_CHANGE_NOTIFY_NAME); + } else { + std::vector<base::win::AccessToken::Privilege> primary_privs = + GetPrimaryToken(0).Privileges(); + ASSERT_EQ(privs.size(), primary_privs.size()); + for (size_t i = 0; i < privs.size(); ++i) { + EXPECT_EQ(privs[i].GetLuid(), primary_privs[i].GetLuid()); + } + } +} + +void CheckRestricted(const base::win::AccessToken& token, + const std::vector<base::win::Sid>& sids) { + std::vector<base::win::AccessToken::Group> restricted = + token.RestrictedSids(); + ASSERT_EQ(sids.size(), restricted.size()); + for (size_t i = 0; i < sids.size(); ++i) { + EXPECT_EQ(sids[i], restricted[i].GetSid()) + << *sids[i].ToSddlString() + L" != " + + *restricted[i].GetSid().ToSddlString(); + } +} + +void CheckRestricted(TokenLevel level, + const std::vector<base::win::WellKnownSid>& known_sids, + bool user, + bool logon) { + absl::optional<base::win::AccessToken> token = CreateRestrictedToken( + level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt); + std::vector<base::win::Sid> sids = + base::win::Sid::FromKnownSidVector(known_sids); + if (user) { + sids.push_back(token->User()); + } + if (logon) { + absl::optional<base::win::Sid> logon_sid = token->LogonId(); + if (logon_sid) { + sids.push_back(logon_sid->Clone()); + } + } + CheckRestricted(*token, sids); +} + +void CompareDenyOnly( + TokenLevel level, + const std::vector<base::win::WellKnownSid>& known_exceptions, + bool allow_all, + bool user) { + absl::optional<base::win::AccessToken> token = CreateRestrictedToken( + level, INTEGRITY_LEVEL_LAST, TokenType::kPrimary, false, absl::nullopt); + ASSERT_TRUE(token); + std::vector<base::win::Sid> exceptions = + base::win::Sid::FromKnownSidVector(known_exceptions); + std::vector<base::win::AccessToken::Group> groups = + GetPrimaryToken(0).Groups(); + std::vector<base::win::AccessToken::Group> compare_groups = token->Groups(); + ASSERT_EQ(groups.size(), compare_groups.size()); + for (size_t i = 0; i < groups.size(); ++i) { + const base::win::Sid& group_sid = groups[i].GetSid(); + ASSERT_EQ(group_sid, compare_groups[i].GetSid()); + if (groups[i].IsLogonId() || groups[i].IsIntegrity() || + groups[i].IsDenyOnly() || compare_groups[i].IsDenyOnly() || allow_all) { + continue; + } + EXPECT_NE(base::ranges::find(exceptions, group_sid), exceptions.end()); + } + EXPECT_EQ(user, token->UserGroup().IsDenyOnly()); } } // namespace -// Tests the initializatioin with an invalid token handle. -TEST(RestrictedTokenTest, InvalidHandle) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_INVALID_HANDLE), - token.Init(reinterpret_cast<HANDLE>(0x5555))); -} - -// Tests the initialization with nullptr as parameter. +// Tests default initialization of the class. TEST(RestrictedTokenTest, DefaultInit) { + RestrictedToken token_default; + absl::optional<base::win::AccessToken> restricted_token = + token_default.GetRestrictedToken(); + ASSERT_TRUE(restricted_token); + // Get the current process token. absl::optional<base::win::AccessToken> access_token = base::win::AccessToken::FromCurrentProcess(); ASSERT_TRUE(access_token); - - // Create the token using the current token. - RestrictedToken token_default; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token_default.Init(nullptr)); - - // Get the handle to the restricted token. - base::win::ScopedHandle restricted_token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token_default.GetRestrictedToken(&restricted_token_handle)); - - auto restricted_token = - base::win::AccessToken::FromToken(restricted_token_handle.Get()); - ASSERT_TRUE(restricted_token); // Check if both token have the same owner and user. EXPECT_EQ(restricted_token->User(), access_token->User()); EXPECT_EQ(restricted_token->Owner(), access_token->Owner()); + EXPECT_FALSE(restricted_token->IsImpersonation()); + EXPECT_FALSE(restricted_token->IsRestricted()); + EXPECT_EQ(DWORD{TOKEN_ALL_ACCESS}, + base::win::GetGrantedAccess(restricted_token->get())); } -// Tests the initialization with a custom token as parameter. -TEST(RestrictedTokenTest, CustomInit) { - CAccessToken access_token; - ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS)); - // Change the primary group. - access_token.SetPrimaryGroup(ATL::Sids::World()); - - // Create the token using the current token. - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - base::win::ScopedHandle restricted_token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&restricted_token_handle)); - auto restricted_token = - base::win::AccessToken::FromToken(restricted_token_handle.Get()); - ASSERT_TRUE(restricted_token); - - ATL::CSid sid_default; - ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default)); - // Check if both token have the same primary grou. - ASSERT_TRUE(restricted_token->PrimaryGroup().Equal( - const_cast<SID*>(sid_default.GetPSID()))); -} - -// Verifies that the token created by the object are valid. +// Verifies that the token created is valid. TEST(RestrictedTokenTest, ResultToken) { RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); + token.AddRestrictingSid(base::win::WellKnownSid::kWorld); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(base::win::WellKnownSid::kWorld)); - - base::win::ScopedHandle restricted_token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&restricted_token)); - - auto primary = base::win::AccessToken::FromToken(restricted_token.Get()); - ASSERT_TRUE(primary); - EXPECT_TRUE(primary->IsRestricted()); - EXPECT_FALSE(primary->IsImpersonation()); - - base::win::ScopedHandle impersonation_token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedTokenForImpersonation(&impersonation_token)); - auto impersonation = - base::win::AccessToken::FromToken(impersonation_token.Get()); - ASSERT_TRUE(impersonation); - ASSERT_TRUE(impersonation->IsRestricted()); - ASSERT_TRUE(impersonation->IsImpersonation()); - ASSERT_FALSE(impersonation->IsIdentification()); + absl::optional<base::win::AccessToken> restricted_token = + token.GetRestrictedToken(); + ASSERT_TRUE(restricted_token); + EXPECT_TRUE(restricted_token->IsRestricted()); + EXPECT_FALSE(restricted_token->IsImpersonation()); } // Verifies that the token created has "Restricted" in its default dacl. TEST(RestrictedTokenTest, DefaultDacl) { - TestDefaultDalc(true, false); + TestDefaultDacl(true, false); } // Verifies that the token created does not have "Restricted" in its default // dacl. TEST(RestrictedTokenTest, DefaultDaclLockdown) { - TestDefaultDalc(false, false); + TestDefaultDacl(false, false); } // Verifies that the token created has an additional SID in its default dacl. TEST(RestrictedTokenTest, DefaultDaclWithAddition) { - TestDefaultDalc(true, true); + TestDefaultDacl(true, true); } // Verifies that the token created does not have "Restricted" in its default // dacl and also has an additional SID. TEST(RestrictedTokenTest, DefaultDaclLockdownWithAddition) { - TestDefaultDalc(false, true); + TestDefaultDacl(false, true); } // Tests the method "AddSidForDenyOnly". TEST(RestrictedTokenTest, DenySid) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld); + absl::optional<base::win::AccessToken> restricted_token = + token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); - auto sid = base::win::Sid(base::win::WellKnownSid::kWorld); + base::win::Sid sid(base::win::WellKnownSid::kWorld); bool found_sid = false; - for (const auto& group : restricted_token->Groups()) { + for (const base::win::AccessToken::Group& group : + restricted_token->Groups()) { if (sid == group.GetSid()) { ASSERT_TRUE(group.IsDenyOnly()); found_sid = true; @@ -338,17 +353,14 @@ // Tests the method "AddAllSidsForDenyOnly". TEST(RestrictedTokenTest, DenySids) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddAllSidsForDenyOnly({})); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddAllSidsForDenyOnly({}); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); bool found_sid = false; // Verify that all sids are really gone. - for (const auto& group : restricted_token->Groups()) { + for (const base::win::AccessToken::Group& group : + restricted_token->Groups()) { if (group.IsLogonId() || group.IsIntegrity()) continue; ASSERT_TRUE(group.IsDenyOnly()); @@ -361,23 +373,18 @@ // Tests the method "AddAllSidsForDenyOnly" using an exception list. TEST(RestrictedTokenTest, DenySidsException) { RestrictedToken token; - base::win::ScopedHandle token_handle; std::vector<base::win::Sid> sids_exception = base::win::Sid::FromKnownSidVector({base::win::WellKnownSid::kWorld}); + token.AddAllSidsForDenyOnly(sids_exception); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddAllSidsForDenyOnly(sids_exception)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); bool found_sid = false; // Verify that all sids are really gone. - for (const auto& group : restricted_token->Groups()) { + for (const base::win::AccessToken::Group& group : + restricted_token->Groups()) { if (group.IsLogonId() || group.IsIntegrity()) continue; if (sids_exception[0] == group.GetSid()) { @@ -394,29 +401,8 @@ // Tests test method AddOwnerSidForDenyOnly. TEST(RestrictedTokenTest, DenyOwnerSid) { RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); - ASSERT_TRUE(restricted_token); - EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly()); -} - -// Tests test method AddOwnerSidForDenyOnly with a custom effective token. -TEST(RestrictedTokenTest, DenyOwnerSidCustom) { - CAccessToken access_token; - ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS)); - RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddUserSidForDenyOnly(); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly()); } @@ -424,14 +410,8 @@ // Tests the method DeleteAllPrivileges. TEST(RestrictedTokenTest, DeleteAllPrivileges) { RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.DeleteAllPrivileges(/*remove_traversal_privilege=*/true)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.DeleteAllPrivileges(/*remove_traversal_privilege=*/true); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); EXPECT_TRUE(restricted_token->Privileges().empty()); } @@ -439,15 +419,8 @@ // Tests the method DeleteAllPrivileges with an exception list. TEST(RestrictedTokenTest, DeleteAllPrivilegesException) { RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.DeleteAllPrivileges(/*remove_traversal_privilege=*/false)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.DeleteAllPrivileges(/*remove_traversal_privilege=*/false); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); auto privileges = restricted_token->Privileges(); ASSERT_EQ(1U, privileges.size()); @@ -457,15 +430,8 @@ // Tests the method AddRestrictingSid. TEST(RestrictedTokenTest, AddRestrictingSid) { RestrictedToken token; - base::win::ScopedHandle token_handle; - - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(base::win::WellKnownSid::kWorld)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddRestrictingSid(base::win::WellKnownSid::kWorld); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); CheckRestrictingSid(*restricted_token, base::win::WellKnownSid::kWorld, 1); } @@ -473,33 +439,9 @@ // Tests the method AddRestrictingSidCurrentUser. TEST(RestrictedTokenTest, AddRestrictingSidCurrentUser) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); - ASSERT_TRUE(restricted_token); - CheckRestrictingSid(*restricted_token, restricted_token->User(), 1); -} - -// Tests the method AddRestrictingSidCurrentUser with a custom effective token. -TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) { - CAccessToken access_token; - ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS)); - RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.Init(access_token.GetHandle())); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddRestrictingSidCurrentUser(); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); CheckRestrictingSid(*restricted_token, restricted_token->User(), 1); } @@ -507,15 +449,9 @@ // Tests the method AddRestrictingSidLogonSession. TEST(RestrictedTokenTest, AddRestrictingSidLogonSession) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidLogonSession()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddRestrictingSidLogonSession(); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); auto session = restricted_token->LogonId(); if (!session) { @@ -529,19 +465,11 @@ // Tests adding a lot of restricting sids. TEST(RestrictedTokenTest, AddMultipleRestrictingSids) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidCurrentUser()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidLogonSession()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSid(base::win::WellKnownSid::kWorld)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddRestrictingSidCurrentUser(); + token.AddRestrictingSidLogonSession(); + token.AddRestrictingSid(base::win::WellKnownSid::kWorld); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); ASSERT_EQ(3u, restricted_token->RestrictedSids().size()); } @@ -549,20 +477,14 @@ // Tests the method "AddRestrictingSidAllSids". TEST(RestrictedTokenTest, AddAllSidToRestrictingSids) { RestrictedToken token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.AddRestrictingSidAllSids()); - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), - token.GetRestrictedToken(&token_handle)); - - auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get()); + token.AddRestrictingSidAllSids(); + auto restricted_token = token.GetRestrictedToken(); ASSERT_TRUE(restricted_token); - auto groups = restricted_token->Groups(); // Verify that all group sids are in the restricting sid list. - for (const auto& group : groups) { + for (const base::win::AccessToken::Group& group : + restricted_token->Groups()) { if (!group.IsIntegrity()) CheckRestrictingSid(*restricted_token, group.GetSid(), -1); } @@ -570,29 +492,20 @@ CheckRestrictingSid(*restricted_token, restricted_token->User(), -1); } -// Checks the error code when the object is initialized twice. -TEST(RestrictedTokenTest, DoubleInit) { - RestrictedToken token; - ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr)); - - ASSERT_EQ(static_cast<DWORD>(ERROR_ALREADY_INITIALIZED), token.Init(nullptr)); -} - TEST(RestrictedTokenTest, LockdownDefaultDaclNoLogonSid) { - ATL::CAccessToken anonymous_token; ASSERT_TRUE(::ImpersonateAnonymousToken(::GetCurrentThread())); - ASSERT_TRUE(anonymous_token.GetThreadToken(TOKEN_ALL_ACCESS)); + absl::optional<base::win::AccessToken> anonymous_token = + base::win::AccessToken::FromCurrentThread(/*open_as_self=*/true, + TOKEN_ALL_ACCESS); ::RevertToSelf(); - ATL::CSid logon_sid; + ASSERT_TRUE(anonymous_token); // Verify that the anonymous token doesn't have the logon sid. - ASSERT_FALSE(anonymous_token.GetLogonSid(&logon_sid)); + ASSERT_FALSE(anonymous_token->LogonId()); RestrictedToken token; - ASSERT_EQ(DWORD{ERROR_SUCCESS}, token.Init(anonymous_token.GetHandle())); token.SetLockdownDefaultDacl(); - base::win::ScopedHandle handle; - ASSERT_EQ(DWORD{ERROR_SUCCESS}, token.GetRestrictedToken(&handle)); + ASSERT_TRUE(token.GetRestrictedTokenForTesting(*anonymous_token)); } TEST(RestrictedTokenTest, LowBoxToken) { @@ -600,8 +513,10 @@ auto package_sid = *base::win::Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-7"); - ASSERT_FALSE(CreateLowBoxToken(nullptr, PRIMARY, package_sid, {}, nullptr)); - ASSERT_TRUE(CreateLowBoxToken(nullptr, PRIMARY, package_sid, {}, &token)); + ASSERT_FALSE(CreateLowBoxToken(nullptr, TokenType::kPrimary, package_sid, {}, + nullptr)); + ASSERT_TRUE( + CreateLowBoxToken(nullptr, TokenType::kPrimary, package_sid, {}, &token)); ASSERT_TRUE(token.IsValid()); CheckLowBoxToken(token, false, package_sid, {}); @@ -610,29 +525,28 @@ package_sid, TOKEN_ALL_ACCESS)); CheckDaclForPackageSid(token, package_sid, false); - ASSERT_TRUE( - CreateLowBoxToken(nullptr, IMPERSONATION, package_sid, {}, &token)); + ASSERT_TRUE(CreateLowBoxToken(nullptr, TokenType::kImpersonation, package_sid, + {}, &token)); ASSERT_TRUE(token.is_valid()); CheckLowBoxToken(token, true, package_sid, {}); - auto capabilities = base::win::Sid::FromKnownCapabilityVector( - {base::win::WellKnownCapability::kInternetClient, - base::win::WellKnownCapability::kPrivateNetworkClientServer}); - ASSERT_TRUE( - CreateLowBoxToken(nullptr, PRIMARY, package_sid, capabilities, &token)); + std::vector<base::win::Sid> capabilities = + base::win::Sid::FromKnownCapabilityVector( + {base::win::WellKnownCapability::kInternetClient, + base::win::WellKnownCapability::kPrivateNetworkClientServer}); + ASSERT_TRUE(CreateLowBoxToken(nullptr, TokenType::kPrimary, package_sid, + capabilities, &token)); ASSERT_TRUE(token.is_valid()); CheckLowBoxToken(token, false, package_sid, capabilities); RestrictedToken restricted_token; - base::win::ScopedHandle token_handle; - ASSERT_EQ(DWORD{ERROR_SUCCESS}, restricted_token.Init(nullptr)); - ASSERT_EQ(DWORD{ERROR_SUCCESS}, restricted_token.AddRestrictingSid( - base::win::WellKnownSid::kWorld)); - ASSERT_EQ(DWORD{ERROR_SUCCESS}, - restricted_token.GetRestrictedToken(&token_handle)); + restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld); + absl::optional<base::win::AccessToken> base_token = + restricted_token.GetRestrictedToken(); + ASSERT_TRUE(base_token); - ASSERT_TRUE(CreateLowBoxToken(token_handle.Get(), PRIMARY, package_sid, - capabilities, &token)); + ASSERT_TRUE(CreateLowBoxToken(base_token->get(), TokenType::kPrimary, + package_sid, capabilities, &token)); ASSERT_TRUE(token.is_valid()); CheckLowBoxToken(token, false, package_sid, capabilities); CheckRestrictingSid(token.get(), base::win::WellKnownSid::kWorld, 1); @@ -667,4 +581,107 @@ SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP); } +TEST(RestrictedTokenTest, TokenType) { + absl::optional<base::win::AccessToken> token = + CreateRestrictedToken(USER_LOCKDOWN, INTEGRITY_LEVEL_LAST, + TokenType::kPrimary, false, absl::nullopt); + ASSERT_TRUE(token); + EXPECT_FALSE(token->IsImpersonation()); + EXPECT_EQ(DWORD{TOKEN_ALL_ACCESS}, base::win::GetGrantedAccess(token->get())); + token = + CreateRestrictedToken(USER_LOCKDOWN, INTEGRITY_LEVEL_LAST, + TokenType::kImpersonation, false, absl::nullopt); + ASSERT_TRUE(token); + EXPECT_TRUE(token->IsImpersonation()); + EXPECT_EQ(token->ImpersonationLevel(), + base::win::SecurityImpersonationLevel::kImpersonation); + EXPECT_EQ(DWORD{TOKEN_ALL_ACCESS}, base::win::GetGrantedAccess(token->get())); +} + +TEST(RestrictedTokenTest, UniqueSid) { + CheckUniqueSid(USER_UNPROTECTED, false); + CheckUniqueSid(USER_RESTRICTED_SAME_ACCESS, false); + CheckUniqueSid(USER_RESTRICTED_NON_ADMIN, true); + CheckUniqueSid(USER_INTERACTIVE, true); + CheckUniqueSid(USER_LIMITED, true); + CheckUniqueSid(USER_LOCKDOWN, true); +} + +TEST(RestrictedTokenTest, IntegrityLevel) { + CheckIntegrityLevel(INTEGRITY_LEVEL_LAST); + CheckIntegrityLevel(INTEGRITY_LEVEL_MEDIUM); + CheckIntegrityLevel(INTEGRITY_LEVEL_MEDIUM_LOW); + CheckIntegrityLevel(INTEGRITY_LEVEL_LOW); + CheckIntegrityLevel(INTEGRITY_LEVEL_BELOW_LOW); + CheckIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED); +} + +TEST(RestrictedTokenTest, Privileges) { + CheckPrivileges(USER_UNPROTECTED, false, false); + CheckPrivileges(USER_RESTRICTED_SAME_ACCESS, false, false); + CheckPrivileges(USER_RESTRICTED_NON_ADMIN, true, false); + CheckPrivileges(USER_INTERACTIVE, true, false); + CheckPrivileges(USER_LIMITED, true, false); + CheckPrivileges(USER_LOCKDOWN, true, true); +} + +TEST(RestrictedTokenTest, Restricted) { + CheckRestricted(USER_UNPROTECTED, {}, false, false); + CheckRestricted( + USER_RESTRICTED_NON_ADMIN, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kInteractive, + base::win::WellKnownSid::kAuthenticatedUser, + base::win::WellKnownSid::kRestricted}, + true, true); + CheckRestricted( + USER_INTERACTIVE, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kRestricted}, + true, true); + CheckRestricted( + USER_LIMITED, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kRestricted}, + false, true); + CheckRestricted(USER_LOCKDOWN, {base::win::WellKnownSid::kNull}, false, + false); + + absl::optional<base::win::AccessToken> token = + CreateRestrictedToken(USER_RESTRICTED_SAME_ACCESS, INTEGRITY_LEVEL_LAST, + TokenType::kPrimary, false, absl::nullopt); + ASSERT_TRUE(token); + std::vector<base::win::Sid> sids; + sids.push_back(token->User()); + for (const base::win::AccessToken::Group& group : token->Groups()) { + if (!group.IsIntegrity()) { + sids.push_back(group.GetSid().Clone()); + } + } + CheckRestricted(*token, sids); +} + +TEST(RestrictedTokenTest, DenyOnly) { + CompareDenyOnly(USER_UNPROTECTED, {}, true, false); + CompareDenyOnly(USER_RESTRICTED_SAME_ACCESS, {}, true, false); + CompareDenyOnly( + USER_RESTRICTED_NON_ADMIN, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kInteractive, + base::win::WellKnownSid::kAuthenticatedUser}, + false, false); + CompareDenyOnly( + USER_INTERACTIVE, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kInteractive, + base::win::WellKnownSid::kAuthenticatedUser}, + false, false); + CompareDenyOnly( + USER_LIMITED, + {base::win::WellKnownSid::kBuiltinUsers, base::win::WellKnownSid::kWorld, + base::win::WellKnownSid::kInteractive}, + false, false); + CompareDenyOnly(USER_LOCKDOWN, {}, false, true); +} + } // namespace sandbox
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc index e959b27..72605d34 100644 --- a/sandbox/win/src/restricted_token_utils.cc +++ b/sandbox/win/src/restricted_token_utils.cc
@@ -12,9 +12,9 @@ #include "base/win/access_token.h" #include "base/win/scoped_handle.h" #include "base/win/security_descriptor.h" +#include "sandbox/win/src/acl.h" #include "sandbox/win/src/restricted_token.h" #include "sandbox/win/src/sandbox_nt_util.h" -#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/security_level.h" #include "sandbox/win/src/win_utils.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -30,18 +30,16 @@ } // namespace -DWORD CreateRestrictedToken( - HANDLE effective_token, +absl::optional<base::win::AccessToken> CreateRestrictedToken( TokenLevel security_level, IntegrityLevel integrity_level, TokenType token_type, bool lockdown_default_dacl, - const absl::optional<base::win::Sid>& unique_restricted_sid, - base::win::ScopedHandle* token) { + const absl::optional<base::win::Sid>& unique_restricted_sid) { RestrictedToken restricted_token; - restricted_token.Init(effective_token); - if (lockdown_default_dacl) + if (lockdown_default_dacl) { restricted_token.SetLockdownDefaultDacl(); + } if (unique_restricted_sid) { restricted_token.AddDefaultDaclSid(*unique_restricted_sid, base::win::SecurityAccessMode::kGrant, @@ -59,22 +57,16 @@ bool remove_traverse_privilege = false; switch (security_level) { - case USER_UNPROTECTED: { + case USER_UNPROTECTED: deny_sids = false; remove_privileges = false; break; - } - case USER_RESTRICTED_SAME_ACCESS: { + case USER_RESTRICTED_SAME_ACCESS: deny_sids = false; remove_privileges = false; - - unsigned err_code = restricted_token.AddRestrictingSidAllSids(); - if (ERROR_SUCCESS != err_code) - return err_code; - + restricted_token.AddRestrictingSidAllSids(); break; - } - case USER_RESTRICTED_NON_ADMIN: { + case USER_RESTRICTED_NON_ADMIN: AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers); AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld); AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive); @@ -89,11 +81,11 @@ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted); restricted_token.AddRestrictingSidCurrentUser(); restricted_token.AddRestrictingSidLogonSession(); - if (unique_restricted_sid) + if (unique_restricted_sid) { restricted_token.AddRestrictingSid(*unique_restricted_sid); + } break; - } - case USER_INTERACTIVE: { + case USER_INTERACTIVE: AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers); AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld); AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive); @@ -105,11 +97,11 @@ restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted); restricted_token.AddRestrictingSidCurrentUser(); restricted_token.AddRestrictingSidLogonSession(); - if (unique_restricted_sid) + if (unique_restricted_sid) { restricted_token.AddRestrictingSid(*unique_restricted_sid); + } break; - } - case USER_LIMITED: { + case USER_LIMITED: AddSidException(sid_exceptions, base::win::WellKnownSid::kBuiltinUsers); AddSidException(sid_exceptions, base::win::WellKnownSid::kWorld); AddSidException(sid_exceptions, base::win::WellKnownSid::kInteractive); @@ -117,101 +109,53 @@ base::win::WellKnownSid::kBuiltinUsers); restricted_token.AddRestrictingSid(base::win::WellKnownSid::kWorld); restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted); - if (unique_restricted_sid) + if (unique_restricted_sid) { restricted_token.AddRestrictingSid(*unique_restricted_sid); - + } // This token has to be able to create objects in BNO, it needs the // current logon sid in the token to achieve this. You should also set the // process to be low integrity level so it can't access object created by // other processes. restricted_token.AddRestrictingSidLogonSession(); break; - } - case USER_RESTRICTED: { - restricted_token.AddUserSidForDenyOnly(); - restricted_token.AddRestrictingSid(base::win::WellKnownSid::kRestricted); - if (unique_restricted_sid) - restricted_token.AddRestrictingSid(*unique_restricted_sid); - break; - } - case USER_LOCKDOWN: { + case USER_LOCKDOWN: remove_traverse_privilege = true; restricted_token.AddUserSidForDenyOnly(); restricted_token.AddRestrictingSid(base::win::WellKnownSid::kNull); - if (unique_restricted_sid) + if (unique_restricted_sid) { restricted_token.AddRestrictingSid(*unique_restricted_sid); + } break; - } case USER_LAST: - return ERROR_BAD_ARGUMENTS; + return absl::nullopt; } - DWORD err_code = ERROR_SUCCESS; if (deny_sids) { - err_code = restricted_token.AddAllSidsForDenyOnly(sid_exceptions); - if (ERROR_SUCCESS != err_code) - return err_code; + restricted_token.AddAllSidsForDenyOnly(sid_exceptions); } if (remove_privileges) { - err_code = restricted_token.DeleteAllPrivileges(remove_traverse_privilege); - if (ERROR_SUCCESS != err_code) - return err_code; + restricted_token.DeleteAllPrivileges(remove_traverse_privilege); } restricted_token.SetIntegrityLevel(integrity_level); - - switch (token_type) { - case PRIMARY: { - err_code = restricted_token.GetRestrictedToken(token); - break; - } - case IMPERSONATION: { - err_code = restricted_token.GetRestrictedTokenForImpersonation(token); - break; - } - default: { - err_code = ERROR_BAD_ARGUMENTS; - break; - } + absl::optional<base::win::AccessToken> result = + restricted_token.GetRestrictedToken(); + if (!result) { + return absl::nullopt; } - return err_code; -} - -DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level) { - absl::optional<base::win::Sid> sid = GetIntegrityLevelSid(integrity_level); - if (!sid) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; + if (token_type == TokenType::kPrimary) { + return result; } - TOKEN_MANDATORY_LABEL label = {}; - label.Label.Attributes = SE_GROUP_INTEGRITY; - label.Label.Sid = sid->GetPSID(); - - if (!::SetTokenInformation(token, TokenIntegrityLevel, &label, sizeof(label))) - return ::GetLastError(); - - return ERROR_SUCCESS; -} - -DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level) { - // We don't check for an invalid level here because we'll just let it - // fail on the SetTokenIntegrityLevel call later on. - if (integrity_level == INTEGRITY_LEVEL_LAST) { - // No mandatory level specified, we don't change it. - return ERROR_SUCCESS; + result = result->DuplicateImpersonation( + base::win::SecurityImpersonationLevel::kImpersonation, TOKEN_ALL_ACCESS); + if (!result) { + return absl::nullopt; } - HANDLE token_handle; - if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, - &token_handle)) - return ::GetLastError(); - - base::win::ScopedHandle token(token_handle); - - return SetTokenIntegrityLevel(token.Get(), integrity_level); + return result; } DWORD HardenTokenIntegrityLevelPolicy(const base::win::AccessToken& token) { @@ -252,10 +196,6 @@ const base::win::Sid& package_sid, const std::vector<base::win::Sid>& capabilities, base::win::ScopedHandle* token) { - if (token_type != PRIMARY && token_type != IMPERSONATION) { - return false; - } - if (!token) { return false; } @@ -280,7 +220,7 @@ } // Default from CreateAppContainer is a Primary token. - if (token_type == PRIMARY) { + if (token_type == TokenType::kPrimary) { *token = token_lowbox->release(); return true; }
diff --git a/sandbox/win/src/restricted_token_utils.h b/sandbox/win/src/restricted_token_utils.h index 2c511db..386edddf 100644 --- a/sandbox/win/src/restricted_token_utils.h +++ b/sandbox/win/src/restricted_token_utils.h
@@ -22,55 +22,34 @@ // The type of the token returned by the CreateRestrictedToken and // CreateLowBoxToken APIs. -enum TokenType { IMPERSONATION = 0, PRIMARY }; +enum class TokenType { kImpersonation, kPrimary }; -// Creates a restricted token from effective token. If it's nullptr then -// effective token of process is used instead. The parameter security_level -// determines how much the token isrestricted. The token_type determines if -// the token will be used as a primarytoken or impersonation token. The -// integrity level of the token is set to |integrity level|. -// |token| is the output value containing the handle of the newly created -// restricted token. -// |lockdown_default_dacl| indicates the token's default DACL should be locked +// Creates a restricted token from the current process' token. The parameter +// `security_level` determines how much the token is restricted. +// `token_type` determines if the token will be used as a primary or +// impersonation token. +// `integrity level` set the token's integrity level. +// `lockdown_default_dacl` indicates the token's default DACL should be locked // down to restrict what other process can open kernel resources created while // running under the token. -// |unique_restricted_sid| indicates an optional restricted SID to add to the -// token's restricted SID list defined by |security_level|. This allows a +// `unique_restricted_sid` indicates an optional restricted SID to add to the +// token's restricted SID list defined by `security_level`. This allows a // sandbox process to be grant access to itself and its resources but not // other sandboxed processes at the same security level. -// If the function succeeds, the return value is ERROR_SUCCESS. If the -// function fails, the return value is the win32 error code corresponding to -// the error. -DWORD CreateRestrictedToken( - HANDLE effective_token, +// If the function succeeds, the return value is the restricted token. If it +// fails then the return value is empty. +absl::optional<base::win::AccessToken> CreateRestrictedToken( TokenLevel security_level, IntegrityLevel integrity_level, TokenType token_type, bool lockdown_default_dacl, - const absl::optional<base::win::Sid>& unique_restricted_sid, - base::win::ScopedHandle* token); - -// Sets the integrity level on a token. If the integrity level that you specify -// is greater than the current integrity level, the function will fail. -// |token| must be a token handle with TOKEN_ADJUST_DEFAULTS access. -// If the function succeeds, the return value is ERROR_SUCCESS. If the -// function fails, the return value is the win32 error code corresponding to -// the error. -DWORD SetTokenIntegrityLevel(HANDLE token, IntegrityLevel integrity_level); - -// Sets the integrity level on the current process token. If the integrity level -// that you specify is greater than the current integrity level, the function -// will fail. -// If the function succeeds, the return value is ERROR_SUCCESS. If the -// function fails, the return value is the win32 error code corresponding to -// the error. -DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level); + const absl::optional<base::win::Sid>& unique_restricted_sid); // Hardens the integrity level policy on a token. Specifically it sets the // policy to block read and execute so that a lower privileged process cannot // open the token for impersonate or duplicate permissions. This should limit // potential security holes. -// |token| must be a token with READ_CONTROL and WRITE_OWNER access. +// `token` must be a token with READ_CONTROL and WRITE_OWNER access. // If the function succeeds, the return value is ERROR_SUCCESS. If the // function fails, the return value is the win32 error code corresponding to // the error.
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h index fb3773e..a198fbd8 100644 --- a/sandbox/win/src/sandbox_policy.h +++ b/sandbox/win/src/sandbox_policy.h
@@ -280,11 +280,6 @@ // Adds a handle that will be shared with the target process. Does not take // ownership of the handle. virtual void AddHandleToShare(HANDLE handle) = 0; - - // Set effective token that will be used for creating the initial and - // lockdown tokens. The token the caller passes must remain valid for the - // lifetime of the policy object. - virtual void SetEffectiveToken(HANDLE token) = 0; }; } // namespace sandbox
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc index d1eac82..46aa13a 100644 --- a/sandbox/win/src/sandbox_policy_base.cc +++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "base/logging.h" +#include "base/win/access_token.h" #include "base/win/sid.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" @@ -30,10 +31,10 @@ #include "sandbox/win/src/restricted_token_utils.h" #include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_policy_diagnostic.h" -#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/signed_policy.h" #include "sandbox/win/src/target_process.h" #include "sandbox/win/src/top_level_dispatcher.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace sandbox { namespace { @@ -419,7 +420,6 @@ config_ptr_(nullptr), stdout_handle_(INVALID_HANDLE_VALUE), stderr_handle_(INVALID_HANDLE_VALUE), - effective_token_(nullptr), job_() { dispatcher_ = std::make_unique<TopLevelDispatcher>(this); } @@ -529,19 +529,20 @@ absl::optional<base::win::Sid> random_sid; if (config()->add_restricting_random_sid()) { random_sid = base::win::Sid::GenerateRandomSid(); - if (!random_sid) - return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN; } IntegrityLevel integrity_level = config()->integrity_level(); bool lockdown_default_dacl = config()->lockdown_default_dacl(); // Create the 'naked' token. This will be the permanent token associated // with the process and therefore with any thread that is not impersonating. - DWORD result = CreateRestrictedToken( - effective_token_, config()->GetLockdownTokenLevel(), integrity_level, - PRIMARY, lockdown_default_dacl, random_sid, lockdown); - if (ERROR_SUCCESS != result) + absl::optional<base::win::AccessToken> primary = CreateRestrictedToken( + config()->GetLockdownTokenLevel(), integrity_level, TokenType::kPrimary, + lockdown_default_dacl, random_sid); + if (!primary) { return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN; + } + + *lockdown = primary->release(); AppContainerBase* app_container = config()->app_container(); if (app_container && @@ -549,18 +550,21 @@ // Build the lowbox lockdown (primary) token. The initial token will be // put in the same lowbox later by GetAppContainerImpersonationToken. ResultCode result_code = app_container->BuildLowBoxToken(lockdown); - if (result_code != SBOX_ALL_OK) + if (result_code != SBOX_ALL_OK) { return result_code; + } } // Create the 'better' token. We use this token as the one that the main // thread uses when booting up the process. It should contain most of // what we need (before reaching main( )) - result = CreateRestrictedToken( - effective_token_, config()->GetInitialTokenLevel(), integrity_level, - IMPERSONATION, lockdown_default_dacl, random_sid, initial); - if (ERROR_SUCCESS != result) + absl::optional<base::win::AccessToken> impersonation = CreateRestrictedToken( + config()->GetInitialTokenLevel(), integrity_level, + TokenType::kImpersonation, lockdown_default_dacl, random_sid); + if (!impersonation) { return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN; + } + *initial = impersonation->release(); return SBOX_ALL_OK; } @@ -674,11 +678,6 @@ return stderr_handle_; } -void PolicyBase::SetEffectiveToken(HANDLE token) { - CHECK(token); - effective_token_ = token; -} - ResultCode PolicyBase::SetupAllInterceptions(TargetProcess& target) { InterceptionManager manager(target); PolicyGlobal* policy = config()->policy();
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h index ee7aad0..82398517 100644 --- a/sandbox/win/src/sandbox_policy_base.h +++ b/sandbox/win/src/sandbox_policy_base.h
@@ -172,7 +172,6 @@ ResultCode SetStdoutHandle(HANDLE handle) override; ResultCode SetStderrHandle(HANDLE handle) override; void AddHandleToShare(HANDLE handle) override; - void SetEffectiveToken(HANDLE token) override; // Creates a Job object with the level specified in a previous call to // SetJobLevel(). @@ -253,7 +252,6 @@ // shared with the target at times. base::HandlesToInheritVector handles_to_share_; - HANDLE effective_token_; Job job_; };
diff --git a/sandbox/win/src/sandbox_policy_diagnostic.cc b/sandbox/win/src/sandbox_policy_diagnostic.cc index c81385020..e8c2e9b3 100644 --- a/sandbox/win/src/sandbox_policy_diagnostic.cc +++ b/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -56,8 +56,6 @@ switch (token) { case USER_LOCKDOWN: return "Lockdown"; - case USER_RESTRICTED: - return "Restricted"; case USER_LIMITED: return "Limited"; case USER_INTERACTIVE:
diff --git a/sandbox/win/src/sandbox_utils.cc b/sandbox/win/src/sandbox_utils.cc deleted file mode 100644 index 64c5505..0000000 --- a/sandbox/win/src/sandbox_utils.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sandbox/win/src/sandbox_utils.h" - -#include <windows.h> -#include <winternl.h> - -#include "base/check.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/nt_internals.h" - -namespace sandbox { - -void InitObjectAttribs(const std::wstring& name, - ULONG attributes, - HANDLE root, - OBJECT_ATTRIBUTES* obj_attr, - UNICODE_STRING* uni_name, - SECURITY_QUALITY_OF_SERVICE* security_qos) { - ::RtlInitUnicodeString(uni_name, name.c_str()); - InitializeObjectAttributes(obj_attr, uni_name, attributes, root, nullptr); - obj_attr->SecurityQualityOfService = security_qos; -} - -} // namespace sandbox
diff --git a/sandbox/win/src/sandbox_utils.h b/sandbox/win/src/sandbox_utils.h deleted file mode 100644 index 6752e2e..0000000 --- a/sandbox/win/src/sandbox_utils.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_WIN_SRC_SANDBOX_UTILS_H_ -#define SANDBOX_WIN_SRC_SANDBOX_UTILS_H_ - -#include <windows.h> -#include <winternl.h> - -#include <string> - -namespace sandbox { - -void InitObjectAttribs(const std::wstring& name, - ULONG attributes, - HANDLE root, - OBJECT_ATTRIBUTES* obj_attr, - UNICODE_STRING* uni_name, - SECURITY_QUALITY_OF_SERVICE* security_qos); - -} // namespace sandbox - -#endif // SANDBOX_WIN_SRC_SANDBOX_UTILS_H_
diff --git a/sandbox/win/src/security_level.h b/sandbox/win/src/security_level.h index 6764e25..a028062 100644 --- a/sandbox/win/src/security_level.h +++ b/sandbox/win/src/security_level.h
@@ -43,8 +43,6 @@ // ----------------------------|--------------|----------------|----------| // USER_LOCKDOWN | Null Sid | All | None | // ----------------------------|--------------|----------------|----------| -// USER_RESTRICTED | RESTRICTED | All | Traverse | -// ----------------------------|--------------|----------------|----------| // USER_LIMITED | Users | All except: | Traverse | // | Everyone | Users | | // | RESTRICTED | Everyone | | @@ -76,14 +74,12 @@ // applied to the target process depends both on the token level selected // and on the broker token itself. // -// The LOCKDOWN and RESTRICTED are designed to allow access to almost -// nothing that has security associated with and they are the recommended -// levels to run sandboxed code specially if there is a chance that the -// broker is process might be started by a user that belongs to the Admins -// or power users groups. +// The LOCKDOWN level is designed to allow access to almost nothing that has +// security associated with and they are the recommended levels to run sandboxed +// code specially if there is a chance that the broker is process might be +// started by a user that belongs to the Admins or power users groups. enum TokenLevel { USER_LOCKDOWN = 0, - USER_RESTRICTED, USER_LIMITED, USER_INTERACTIVE, USER_RESTRICTED_NON_ADMIN,
diff --git a/sandbox/win/src/service_resolver_unittest.cc b/sandbox/win/src/service_resolver_unittest.cc index ed1ee45..aa05e37c 100644 --- a/sandbox/win/src/service_resolver_unittest.cc +++ b/sandbox/win/src/service_resolver_unittest.cc
@@ -13,8 +13,8 @@ #include "base/bit_cast.h" #include "base/memory/raw_ptr.h" +#include "sandbox/win/src/nt_internals.h" #include "sandbox/win/src/resolver.h" -#include "sandbox/win/src/sandbox_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace {
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc index fe1f0d7..25a47e66 100644 --- a/sandbox/win/src/target_process.cc +++ b/sandbox/win/src/target_process.cc
@@ -84,8 +84,9 @@ auto app_container_sid = token->AppContainerSid(); if (!app_container_sid) return false; - return CreateLowBoxToken(initial_token, IMPERSONATION, *app_container_sid, - capabilities, impersonation_token); + return CreateLowBoxToken(initial_token, TokenType::kImpersonation, + *app_container_sid, capabilities, + impersonation_token); } } // namespace
diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc index faf3cc0..89a902c4 100644 --- a/sandbox/win/src/target_services.cc +++ b/sandbox/win/src/target_services.cc
@@ -13,6 +13,8 @@ #include <stdint.h> #include "base/logging.h" +#include "base/win/access_token.h" +#include "sandbox/win/src/acl.h" #include "sandbox/win/src/crosscall_client.h" #include "sandbox/win/src/handle_closer_agent.h" #include "sandbox/win/src/heap_helper.h" @@ -110,6 +112,22 @@ return (0 != ::GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH)); } +bool SetProcessIntegrityLevel(IntegrityLevel integrity_level) { + absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level); + if (!rid) { + // No mandatory level specified, we don't change it. + return true; + } + + absl::optional<base::win::AccessToken> token = + base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false, + TOKEN_ADJUST_DEFAULT); + if (!token) { + return false; + } + return token->SetIntegrityLevel(*rid); +} + // Used as storage for g_target_services, because other allocation facilities // are not available early. We can't use a regular function static because on // VS2015, because the CRT tries to acquire a lock to guard initialization, but @@ -131,9 +149,9 @@ // Failure here is a breach of security so the process is terminated. void TargetServicesBase::LowerToken() { - if (ERROR_SUCCESS != - SetProcessIntegrityLevel(g_shared_delayed_integrity_level)) + if (!SetProcessIntegrityLevel(g_shared_delayed_integrity_level)) { ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_INTEGRITY); + } process_state_.SetRevertedToSelf(); // If the client code as called RegOpenKey, advapi32.dll has cached some // handles. The following code gets rid of them.
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc index 98df360..c40b9e6 100644 --- a/services/network/cookie_settings.cc +++ b/services/network/cookie_settings.cc
@@ -247,7 +247,9 @@ IsAllowedByStorageAccessGrant(url, first_party_url)) { storage_access_result = net::cookie_util::StorageAccessResult:: ACCESS_ALLOWED_STORAGE_ACCESS_GRANT; - } else if (ShouldConsiderTopLevelStorageAccessGrants(query_reason) && + } else if (overrides.Has(net::CookieSettingOverride:: + kTopLevelStorageAccessGrantEligible) && + ShouldConsiderTopLevelStorageAccessGrants(query_reason) && IsAllowedByTopLevelStorageAccessGrant(url, first_party_url)) { storage_access_result = net::cookie_util::StorageAccessResult:: ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT;
diff --git a/services/network/cookie_settings_unittest.cc b/services/network/cookie_settings_unittest.cc index e4b6359..c030bab 100644 --- a/services/network/cookie_settings_unittest.cc +++ b/services/network/cookie_settings_unittest.cc
@@ -62,6 +62,7 @@ struct TestCase { std::string test_name; bool storage_access_api_enabled; + bool top_level_storage_access_grant_eligible; bool force_allow_third_party_cookies; }; @@ -93,12 +94,20 @@ return GetParam().storage_access_api_enabled; } + bool IsTopLevelStorageAccessGrantEligible() const { + return GetParam().top_level_storage_access_grant_eligible; + } + bool IsForceAllowThirdPartyCookies() const { return GetParam().force_allow_third_party_cookies; } net::CookieSettingOverrides GetCookieSettingOverrides() const { net::CookieSettingOverrides overrides; + if (IsTopLevelStorageAccessGrantEligible()) { + overrides.Put( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible); + } if (IsForceAllowThirdPartyCookies()) { overrides.Put(net::CookieSettingOverride::kForceThirdPartyByUser); } @@ -116,6 +125,18 @@ : CONTENT_SETTING_BLOCK; } + // A version of above that considers Top-Level Storage Access API grant + // instead of Storage Access API grant, and user force allow. + ContentSetting SettingWithEitherOverrideForTopLevel() const { + // TODO(crbug.com/1385156): Check TopLevelStorageAccessAPI instead after + // separating the feature flag. + return (IsStorageAccessAPIEnabled() && + IsTopLevelStorageAccessGrantEligible()) || + IsForceAllowThirdPartyCookies() + ? CONTENT_SETTING_ALLOW + : CONTENT_SETTING_BLOCK; + } + ContentSetting SettingWithForceAllowThirdPartyCookies() const { return IsForceAllowThirdPartyCookies() ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; @@ -128,6 +149,8 @@ : net::cookie_util::StorageAccessResult::ACCESS_BLOCKED; } + // The cookie access result would be blocked if not for a Storage Access API + // grant or force allow. net::cookie_util::StorageAccessResult BlockedStorageAccessResultWithEitherOverride() const { if (IsStorageAccessAPIEnabled()) { @@ -140,6 +163,23 @@ return net::cookie_util::StorageAccessResult::ACCESS_BLOCKED; } + // A version of above that considers Top-Level Storage Access API grant + // instead of Storage Access API grant, and user force allow to allow cookie + // access. + net::cookie_util::StorageAccessResult + BlockedStorageAccessResultWithEitherOverrideForTopLevel() const { + // TODO(crbug.com/1385156): Check TopLevelStorageAccessAPI instead after + // separating the feature flag. + if (IsStorageAccessAPIEnabled() && IsTopLevelStorageAccessGrantEligible()) { + return net::cookie_util::StorageAccessResult:: + ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT; + } + if (IsForceAllowThirdPartyCookies()) { + return net::cookie_util::StorageAccessResult::ACCESS_ALLOWED_FORCED; + } + return net::cookie_util::StorageAccessResult::ACCESS_BLOCKED; + } + private: base::test::ScopedFeatureList features_; base::test::TaskEnvironment task_environment_; @@ -339,6 +379,109 @@ } } +// The Top-Level Storage Access API should unblock storage access that would +// otherwise be blocked. +TEST_P(CookieSettingsTest, GetCookieSettingTopLevelStorageAccessUnblocks) { + const GURL top_level_url(kURL); + const GURL url(kOtherURL); + const GURL third_url(kDomainURL); + + base::HistogramTester histogram_tester; + histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0); + + CookieSettings settings; + settings.set_content_settings( + {CreateSetting("*", "*", CONTENT_SETTING_ALLOW)}); + settings.set_block_third_party_cookies(true); + + // Only set the storage access granted by Top-Level Storage Access API. + settings.set_top_level_storage_access_grants( + {CreateSetting(url.host(), top_level_url.host(), CONTENT_SETTING_ALLOW)}); + + // When requesting our setting for the embedder/top-level combination our + // grant is for access should be allowed. For any other domain pairs access + // should still be blocked. + EXPECT_EQ( + settings.GetCookieSetting(url, top_level_url, GetCookieSettingOverrides(), + nullptr, QueryReason::kCookies), + SettingWithEitherOverrideForTopLevel()); + histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1); + histogram_tester.ExpectBucketCount( + kAllowedRequestsHistogram, + static_cast<int>( + BlockedStorageAccessResultWithEitherOverrideForTopLevel()), + 1); + + // Check the cookie setting that does not match the top-level storage access + // grant--the |top_level_url| granting access to |url| is now being loaded + // under |url| as the top level url. + EXPECT_EQ( + settings.GetCookieSetting(top_level_url, url, GetCookieSettingOverrides(), + nullptr, QueryReason::kCookies), + SettingWithForceAllowThirdPartyCookies()); + histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 2); + // TODO(crbug.com/1385156): Separate metrics between StorageAccessAPI + // and the page-level variant. + histogram_tester.ExpectBucketCount( + kAllowedRequestsHistogram, + static_cast<int>(net::cookie_util::StorageAccessResult:: + ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT), + IsStorageAccessAPIEnabled() && IsTopLevelStorageAccessGrantEligible() + ? 1 + : 0); + histogram_tester.ExpectBucketCount( + kAllowedRequestsHistogram, + static_cast<int>( + BlockedStorageAccessResultWithEitherOverrideForTopLevel()), + IsStorageAccessAPIEnabled() && IsTopLevelStorageAccessGrantEligible() + ? 1 + : 2); + + // Check the cookie setting that does not match the top-level storage access + // grant where a |third_url| is used. + EXPECT_EQ( + settings.GetCookieSetting(url, third_url, GetCookieSettingOverrides(), + nullptr, QueryReason::kCookies), + SettingWithForceAllowThirdPartyCookies()); + EXPECT_EQ(settings.GetCookieSetting(third_url, top_level_url, + GetCookieSettingOverrides(), nullptr, + QueryReason::kCookies), + SettingWithForceAllowThirdPartyCookies()); + + // If third-party cookies are blocked, Top-Level Storage Access grant takes + // precedence over possible override to force allow third-party cookies. + { + base::HistogramTester histogram_tester_2; + EXPECT_EQ(settings.GetCookieSetting(url, top_level_url, + GetCookieSettingOverrides(), nullptr, + QueryReason::kCookies), + SettingWithEitherOverrideForTopLevel()); + histogram_tester_2.ExpectTotalCount(kAllowedRequestsHistogram, 1); + histogram_tester_2.ExpectBucketCount( + kAllowedRequestsHistogram, + static_cast<int>( + BlockedStorageAccessResultWithEitherOverrideForTopLevel()), + 1); + } + + // If cookies are globally blocked, Top-Level Storage Access grants and 3PC + // override should both be ignored. + { + settings.set_content_settings( + {CreateSetting("*", "*", CONTENT_SETTING_BLOCK)}); + base::HistogramTester histogram_tester_2; + EXPECT_EQ(settings.GetCookieSetting(url, top_level_url, + GetCookieSettingOverrides(), nullptr, + QueryReason::kCookies), + CONTENT_SETTING_BLOCK); + histogram_tester_2.ExpectTotalCount(kAllowedRequestsHistogram, 1); + histogram_tester_2.ExpectBucketCount( + kAllowedRequestsHistogram, + static_cast<int>(net::cookie_util::StorageAccessResult::ACCESS_BLOCKED), + 1); + } +} + // Subdomains of the granted embedding url should not gain access if a valid // grant exists. TEST_P(CookieSettingsTest, GetCookieSettingSAAResourceWildcards) { @@ -1055,10 +1198,14 @@ /* no prefix */, CookieSettingsTest, testing::ValuesIn<TestCase>({ - {"disable_SAA", false, false}, - {"enable_SAA", true, false}, - {"disable_SAA_force_3PCs", false, true}, - {"enable_SAA_force_3PCs", true, true}, + {"disable_all", false, false, false}, + {"disable_SAA_disable_TopLevel_force_3PCs", false, false, true}, + {"disable_SAA_enable_TopLevel", false, true, false}, + {"disable_SAA_enable_TopLevel_force_3PCs", false, true, true}, + {"enable_SAA_disable_TopLevel", true, false, false}, + {"enable_SAA_disable_TopLevel_force_3PCs", true, false, true}, + {"enable_SAA_enable_TopLevel", true, true, false}, + {"enable_all", true, true, true}, }), [](const testing::TestParamInfo<CookieSettingsTest::ParamType>& info) { return info.param.test_name;
diff --git a/services/network/public/cpp/self_deleting_url_loader_factory.cc b/services/network/public/cpp/self_deleting_url_loader_factory.cc index bac705f4..e574ee3 100644 --- a/services/network/public/cpp/self_deleting_url_loader_factory.cc +++ b/services/network/public/cpp/self_deleting_url_loader_factory.cc
@@ -37,6 +37,14 @@ receivers_.Add(this, std::move(loader)); } +void SelfDeletingURLLoaderFactory::ReportBadMessage( + const std::string& message) { + receivers_.ReportBadMessage(message); + if (receivers_.empty()) { + delete this; + } +} + void SelfDeletingURLLoaderFactory::OnDisconnect() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/services/network/public/cpp/self_deleting_url_loader_factory.h b/services/network/public/cpp/self_deleting_url_loader_factory.h index dad09a3a..37bb913 100644 --- a/services/network/public/cpp/self_deleting_url_loader_factory.h +++ b/services/network/public/cpp/self_deleting_url_loader_factory.h
@@ -49,6 +49,13 @@ // CreateLoaderAndStart. void DisconnectReceiversAndDestroy(); + // Reports the currently dispatching Message as bad and closes+removes the + // receiver which received the message. Prefer this over the global + // `mojo::ReportBadMessage()` function, since calling this method promptly + // disconnects the receiver, preventing further (potentially bad) messages + // from being processed. + void ReportBadMessage(const std::string& message); + THREAD_CHECKER(thread_checker_); private:
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index dd848ae4..0f5ad68 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -46,6 +46,7 @@ #include "net/base/upload_file_element_reader.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_inclusion_status.h" +#include "net/cookies/cookie_setting_override.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" #include "net/cookies/site_for_cookies.h" @@ -728,6 +729,11 @@ request.net_log_reference_info.value()); } + if (network::cors::IsCorsEnabledRequestMode(request_mode_)) { + url_request_->set_cookie_setting_overrides(net::CookieSettingOverrides( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible)); + } + #if BUILDFLAG(IS_ANDROID) if (base::FeatureList::IsEnabled(net::features::kRecordRadioWakeupTrigger)) { MaybeRecordURLLoaderCreationForWakeupTrigger(request, traffic_annotation);
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 7c1d147..8ed2cc78 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -56,6 +56,7 @@ #include "net/cookies/cookie_access_result.h" #include "net/cookies/cookie_change_dispatcher.h" #include "net/cookies/cookie_inclusion_status.h" +#include "net/cookies/cookie_setting_override.h" #include "net/cookies/cookie_util.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_network_session.h" @@ -4745,6 +4746,77 @@ EXPECT_TRUE(url_loader->AllowCookies(third_party_url, site_for_cookies)); } +TEST_F(URLLoaderTest, CookieSettingOverrides_NoCors) { + GURL url("http://www.example.com.test/"); + base::RunLoop delete_run_loop; + // No-cors request should not have the `kTopLevelStorageAccessGrantEligible` + // override. + ResourceRequest request = CreateResourceRequest("GET", url); + // Request mode is `no-cors` by default. + ASSERT_EQ(request.mode, network::mojom::RequestMode::kNoCors); + mojo::PendingRemote<mojom::URLLoader> loader; + std::unique_ptr<URLLoader> url_loader; + context().mutable_factory_params().process_id = mojom::kBrowserProcessId; + url_loader = URLLoaderOptions().MakeURLLoader( + context(), DeleteLoaderCallback(&delete_run_loop, &url_loader), + loader.InitWithNewPipeAndPassReceiver(), request, + client()->CreateRemote()); + + client()->RunUntilComplete(); + delete_run_loop.Run(); + + EXPECT_FALSE(test_network_delegate()->cookie_setting_overrides().Has( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible)); +} + +TEST_F(URLLoaderTest, CookieSettingOverrides_Cors) { + GURL url("http://www.example.com.test/"); + base::RunLoop delete_run_loop; + // Cors request should have the `kTopLevelStorageAccessGrantEligible` + // override. + ResourceRequest request = CreateResourceRequest("GET", url); + // Set request mode to `cors`. + request.mode = network::mojom::RequestMode::kCors; + mojo::PendingRemote<mojom::URLLoader> loader; + std::unique_ptr<URLLoader> url_loader; + context().mutable_factory_params().process_id = mojom::kBrowserProcessId; + url_loader = URLLoaderOptions().MakeURLLoader( + context(), DeleteLoaderCallback(&delete_run_loop, &url_loader), + loader.InitWithNewPipeAndPassReceiver(), request, + client()->CreateRemote()); + + client()->RunUntilComplete(); + delete_run_loop.Run(); + + EXPECT_TRUE(test_network_delegate()->cookie_setting_overrides().Has( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible)); +} + +TEST_F(URLLoaderTest, CookieSettingOverrides_Cors_UnchangedOnRedirects) { + GURL dest_url("http://www.example.com.test/"); + GURL redirecting_url = + test_server()->GetURL("/server-redirect?" + dest_url.spec()); + + base::RunLoop delete_run_loop; + // Cors request should have the `kTopLevelStorageAccessGrantEligible` + // override. + ResourceRequest request = CreateResourceRequest("GET", redirecting_url); + // Set request mode to `cors`. + request.mode = network::mojom::RequestMode::kCors; + mojo::Remote<mojom::URLLoader> loader; + std::unique_ptr<URLLoader> url_loader; + context().mutable_factory_params().process_id = mojom::kBrowserProcessId; + url_loader = URLLoaderOptions().MakeURLLoader( + context(), DeleteLoaderCallback(&delete_run_loop, &url_loader), + loader.BindNewPipeAndPassReceiver(), request, client()->CreateRemote()); + + client()->RunUntilRedirectReceived(); + loader->FollowRedirect({}, {}, {}, absl::nullopt); + + EXPECT_TRUE(test_network_delegate()->cookie_setting_overrides().Has( + net::CookieSettingOverride::kTopLevelStorageAccessGrantEligible)); +} + namespace { enum class TestMode {
diff --git a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.cc b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.cc index 54529719..0012fa0 100644 --- a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.cc +++ b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.cc
@@ -31,8 +31,7 @@ void BackgroundTracingAgentImpl::SetUMACallback( const std::string& histogram_name, int32_t histogram_lower_value, - int32_t histogram_upper_value, - bool repeat) { + int32_t histogram_upper_value) { histogram_last_changed_ = base::Time(); base::WeakPtr<BackgroundTracingAgentImpl> weak_self = @@ -45,7 +44,7 @@ histogram_name, base::BindRepeating(&BackgroundTracingAgentImpl::OnHistogramChanged, weak_self, histogram_lower_value, - histogram_upper_value, repeat)); + histogram_upper_value)); histogram_callback_map_.insert( {histogram_name, std::move(histogram_observer)}); @@ -74,10 +73,6 @@ SendTriggerMessage(histogram_name); break; } - if (!repeat) { - SendAbortBackgroundTracingMessage(); - break; - } sample_iterator->Next(); } @@ -94,15 +89,11 @@ base::WeakPtr<BackgroundTracingAgentImpl> weak_self, base::Histogram::Sample histogram_lower_value, base::Histogram::Sample histogram_upper_value, - bool repeat, const char* histogram_name, uint64_t name_hash, base::Histogram::Sample actual_value) { if (actual_value < histogram_lower_value || actual_value > histogram_upper_value) { - if (!repeat && weak_self) - weak_self->SendAbortBackgroundTracingMessage(); - return; } TRACE_EVENT("toplevel", "HistogramSampleTrigger",
diff --git a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h index c9bcb74e..9cc3c95 100644 --- a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h +++ b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl.h
@@ -33,8 +33,7 @@ // mojom::BackgroundTracingAgent methods: void SetUMACallback(const std::string& histogram_name, int32_t histogram_lower_value, - int32_t histogram_upper_value, - bool repeat) override; + int32_t histogram_upper_value) override; void ClearUMACallback(const std::string& histogram_name) override; private: @@ -42,7 +41,6 @@ base::WeakPtr<BackgroundTracingAgentImpl> weak_self, base::Histogram::Sample reference_lower_value, base::Histogram::Sample reference_upper_value, - bool repeat, const char* histogram_name, uint64_t name_hash, base::Histogram::Sample actual_value);
diff --git a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc index 9c50747..91e5ac7 100644 --- a/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc +++ b/services/tracing/public/cpp/background_tracing/background_tracing_agent_impl_unittest.cc
@@ -90,7 +90,7 @@ TEST_F(BackgroundTracingAgentImplTest, TestHistogramDoesNotTrigger) { LOCAL_HISTOGRAM_COUNTS("foo1", 10); - agent()->SetUMACallback("foo1", 20000, 25000, true); + agent()->SetUMACallback("foo1", 20000, 25000); RunUntilIdle(); @@ -103,7 +103,7 @@ // Ensure that a sample exists by the time SetUMACallback is processed. LOCAL_HISTOGRAM_COUNTS("foo2", 2); - agent()->SetUMACallback("foo2", 1, 3, true); + agent()->SetUMACallback("foo2", 1, 3); // RunLoop ensures that SetUMACallback and OnTriggerBackgroundTrace mojo // messages are processed. @@ -116,7 +116,7 @@ } TEST_F(BackgroundTracingAgentImplTest, TestHistogramTriggers_SameThread) { - agent()->SetUMACallback("foo2", 1, 3, true); + agent()->SetUMACallback("foo2", 1, 3); // RunLoop ensures that SetUMACallback mojo message is processed. RunUntilIdle(); @@ -132,7 +132,7 @@ } TEST_F(BackgroundTracingAgentImplTest, TestHistogramTriggers_CrossThread) { - agent()->SetUMACallback("foo2", 1, 3, true); + agent()->SetUMACallback("foo2", 1, 3); // RunLoop ensures that SetUMACallback mojo message is processed. RunUntilIdle(); @@ -149,16 +149,4 @@ EXPECT_EQ("foo2", recorder()->on_trigger_background_trace_histogram_name()); } -TEST_F(BackgroundTracingAgentImplTest, TestHistogramAborts) { - LOCAL_HISTOGRAM_COUNTS("foo3", 10); - - agent()->SetUMACallback("foo3", 1, 3, false); - - RunUntilIdle(); - - EXPECT_EQ(1, recorder()->on_initialized_count()); - EXPECT_EQ(0, recorder()->on_trigger_background_trace_count()); - EXPECT_EQ(1, recorder()->on_abort_background_trace_count()); -} - } // namespace tracing
diff --git a/services/tracing/public/mojom/background_tracing_agent.mojom b/services/tracing/public/mojom/background_tracing_agent.mojom index 9d8cb1f..d1b61d6 100644 --- a/services/tracing/public/mojom/background_tracing_agent.mojom +++ b/services/tracing/public/mojom/background_tracing_agent.mojom
@@ -17,13 +17,10 @@ interface BackgroundTracingAgent { // Call this method to begin reporting metrics corresponding to the named // histogram. Lower and upper bound values constrain what data is reported. - // This results in OnTriggerBackgroundTrace callbacks (multiple if |repeat| - // is set to true). If a histogram event does not match and |repeat| is - // false, then OnAbortBackgroundTrace is called. + // This results in OnTriggerBackgroundTrace callbacks. SetUMACallback(string histogram_name, int32 histogram_lower_value, - int32 histogram_upper_value, - bool repeat); + int32 histogram_upper_value); // Call this method to stop reporting metrics corresponding to the named // histogram.
diff --git a/services/video_capture/device_media_to_mojo_adapter.cc b/services/video_capture/device_media_to_mojo_adapter.cc index bf37fa1..8cecc2b4 100644 --- a/services/video_capture/device_media_to_mojo_adapter.cc +++ b/services/video_capture/device_media_to_mojo_adapter.cc
@@ -218,7 +218,7 @@ void DeviceMediaToMojoAdapter::SetPhotoOptions( media::mojom::PhotoSettingsPtr settings, SetPhotoOptionsCallback callback) { - media::mojom::ImageCapture::SetOptionsCallback scoped_callback = + media::mojom::ImageCapture::SetPhotoOptionsCallback scoped_callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( media::BindToCurrentLoop(std::move(callback)), false); device_->SetPhotoOptions(std::move(settings), std::move(scoped_callback));
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom index ebb40d25..71d79e7 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -58,6 +58,10 @@ CompositorFrameSinkType type; bool is_root; + // Bucket index of the first bucket in `presented_frames` based on the + // timestamp of the first presented frame in the bucket and start time. + uint16 start_bucket; + // Collected number of presented frames for the specified bucket size. array<uint16> presented_frames; }; @@ -190,7 +194,8 @@ UpdateDebugRendererSettings(DebugRendererSettings debug_settings); // Starts frame counting per frame sink on the Viz thread. - StartFrameCountingForTest(mojo_base.mojom.TimeDelta bucket_size); + StartFrameCountingForTest(mojo_base.mojom.TimeTicks start_time, + mojo_base.mojom.TimeDelta bucket_size); // Stops frame counting on the Viz thread and returns all records to the // caller.
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 72b5452..cd122a1a 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -347,10 +347,6 @@ deps += [ "//third_party/wuffs" ] } - if (current_cpu == "arm") { - sources += [ "//third_party/skia/src/core/SkUtilsArm.cpp" ] - } - # Remove unused util sources. sources -= [ "//third_party/skia/src/utils/SkParsePath.cpp" ]
diff --git a/storage/browser/file_system/local_file_stream_reader.cc b/storage/browser/file_system/local_file_stream_reader.cc index f2335f7..4f13360e 100644 --- a/storage/browser/file_system/local_file_stream_reader.cc +++ b/storage/browser/file_system/local_file_stream_reader.cc
@@ -95,21 +95,14 @@ DCHECK(!stream_impl_.get()); has_pending_open_ = true; - if (!file_access::ScopedFileAccessDelegate::Get()) { - OnScopedFileAccessRequested(std::move(callback), - file_access::ScopedFileAccess::Allowed()); - return; - } - base::OnceCallback<void(file_access::ScopedFileAccess)> open_cb = base::BindOnce(&LocalFileStreamReader::OnScopedFileAccessRequested, weak_factory_.GetWeakPtr(), std::move(callback)); - auto current_task_runner = base::SequencedTaskRunner::GetCurrentDefault(); - auto task = base::BindPostTask(current_task_runner, std::move(open_cb)); - // TODO(crbug.com/1354502): Replace this with actual destination URLs. - file_access::ScopedFileAccessDelegate::Get()->RequestFilesAccessForSystem( - {file_path_}, std::move(task)); + // TODO(b/262199707 b/265908846): Replace with getting access through a + // callback. + file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO( + {file_path_}, std::move(open_cb)); } void LocalFileStreamReader::OnScopedFileAccessRequested(
diff --git a/storage/browser/file_system/local_file_stream_reader_unittest.cc b/storage/browser/file_system/local_file_stream_reader_unittest.cc index 255d8863..c218c2c1 100644 --- a/storage/browser/file_system/local_file_stream_reader_unittest.cc +++ b/storage/browser/file_system/local_file_stream_reader_unittest.cc
@@ -19,10 +19,13 @@ #include "base/location.h" #include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "build/build_config.h" +#include "components/file_access/scoped_file_access.h" #include "components/file_access/scoped_file_access_delegate.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -42,20 +45,6 @@ using ::testing::_; -class MockScopedFileAccessDelegate - : public file_access::ScopedFileAccessDelegate { - public: - MOCK_METHOD3( - RequestFilesAccess, - void(const std::vector<base::FilePath>& files, - const GURL& destination_url, - base::OnceCallback<void(file_access::ScopedFileAccess)> callback)); - MOCK_METHOD2( - RequestFilesAccessForSystem, - void(const std::vector<base::FilePath>& files, - base::OnceCallback<void(file_access::ScopedFileAccess)> callback)); -}; - file_access::ScopedFileAccess CreateScopedFileAccess(bool allowed) { #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) return file_access::ScopedFileAccess(allowed, base::ScopedFD()); @@ -135,22 +124,24 @@ FileStreamReaderTypedTest, LocalFileStreamReaderTest); -// TODO(crbug.com/1354502): Use RequestFileAccess() instead of -// RequestFileAccessForSystem() when destionion URLs can be obtained in -// //storage/. +// TODO(b/262199707 b/265908846): Replace direct call to +// file_access::ScopedFileAccessDelegate with getting access through a callback. TEST_F(LocalFileStreamReaderTest, ReadAllowedByDataLeakPrevention) { this->WriteTestFile(); std::unique_ptr<FileStreamReader> reader( this->CreateFileReader(std::string(this->kTestFileName), 0, this->test_file_modification_time())); - MockScopedFileAccessDelegate scoped_file_access_delegate; - EXPECT_CALL(scoped_file_access_delegate, RequestFilesAccessForSystem(_, _)) - .WillOnce([&](const std::vector<base::FilePath>& files, - base::OnceCallback<void(file_access::ScopedFileAccess)> - callback) { - std::move(callback).Run(CreateScopedFileAccess(true)); - }); + base::MockRepeatingCallback<void( + const std::vector<base::FilePath>&, + base::OnceCallback<void(file_access::ScopedFileAccess)>)> + callback; + file_access::ScopedFileAccessDelegate:: + SetRequestFilesAccessForSystemIOCallbackForTesting(callback.Get()); + EXPECT_CALL( + callback, + Run(testing::ElementsAre(test_dir().AppendASCII(kTestFileName)), _)) + .WillOnce(base::test::RunOnceCallback<1>(CreateScopedFileAccess(true))); int result = 0; std::string data; @@ -159,22 +150,24 @@ ASSERT_EQ(this->kTestData, data); } -// TODO(crbug.com/1354502): Use RequestFileAccess() instead of -// RequestFileAccessForSystem() when destionion URLs can be obtained in -// //storage/. +// TODO(b/262199707 b/265908846): Replace direct call to +// file_access::ScopedFileAccessDelegate with getting access through a callback. TEST_F(LocalFileStreamReaderTest, ReadBlockedByDataLeakPrevention) { this->WriteTestFile(); std::unique_ptr<FileStreamReader> reader( this->CreateFileReader(std::string(this->kTestFileName), 0, this->test_file_modification_time())); - MockScopedFileAccessDelegate scoped_file_access_delegate; - EXPECT_CALL(scoped_file_access_delegate, RequestFilesAccessForSystem(_, _)) - .WillOnce([&](const std::vector<base::FilePath>& files, - base::OnceCallback<void(file_access::ScopedFileAccess)> - callback) { - std::move(callback).Run(CreateScopedFileAccess(false)); - }); + base::MockRepeatingCallback<void( + const std::vector<base::FilePath>&, + base::OnceCallback<void(file_access::ScopedFileAccess)>)> + callback; + file_access::ScopedFileAccessDelegate:: + SetRequestFilesAccessForSystemIOCallbackForTesting(callback.Get()); + EXPECT_CALL( + callback, + Run(testing::ElementsAre(test_dir().AppendASCII(kTestFileName)), _)) + .WillOnce(base::test::RunOnceCallback<1>(CreateScopedFileAccess(false))); int result = 0; std::string data;
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 86010f10..7aed124 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -534,7 +534,7 @@ return QuotaError::kNone; } -QuotaErrorOr<mojom::BucketTableEntryPtr> QuotaDatabase::GetBucketInfo( +QuotaErrorOr<mojom::BucketTableEntryPtr> QuotaDatabase::GetBucketInfoForTest( BucketId bucket_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!bucket_id.is_null()); @@ -566,7 +566,8 @@ return entry; } -QuotaError QuotaDatabase::DeleteBucketData(const BucketLocator& bucket) { +QuotaErrorOr<mojom::BucketTableEntryPtr> QuotaDatabase::DeleteBucketData( + const BucketLocator& bucket) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); QuotaError open_error = EnsureOpened(); if (open_error != QuotaError::kNone) @@ -578,12 +579,15 @@ if (storage_directory_ && !storage_directory_->DoomBucket(bucket)) return QuotaError::kFileOperationError; - static constexpr char kSql[] = "DELETE FROM buckets WHERE id = ?"; + static constexpr char kSql[] = + "DELETE FROM buckets WHERE id = ? " + "RETURNING " BUCKET_TABLE_ENTRY_FIELDS_SELECTOR; sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt64(0, bucket.id.value()); - if (!statement.Run()) + if (!statement.Step()) { return QuotaError::kDatabaseError; + } // Scheduling this commit introduces the chance of inconsistencies // between the buckets table and data stored on disk in the file system. @@ -601,7 +605,7 @@ if (storage_directory_) storage_directory_->ClearDoomedBuckets(); - return QuotaError::kNone; + return BucketTableEntryFromSqlStatement(statement); } QuotaErrorOr<BucketLocator> QuotaDatabase::GetLruEvictableBucket(
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h index 5f4c950..69b8e47 100644 --- a/storage/browser/quota/quota_database.h +++ b/storage/browser/quota/quota_database.h
@@ -164,11 +164,13 @@ // Returns the BucketTableEntry for `bucket` if one exists. Returns a // QuotaError if not found or the operation has failed. - QuotaErrorOr<mojom::BucketTableEntryPtr> GetBucketInfo(BucketId bucket_id); + QuotaErrorOr<mojom::BucketTableEntryPtr> GetBucketInfoForTest( + BucketId bucket_id); // Deletes the bucket from the database as well as the bucket directory in the - // storage directory. - QuotaError DeleteBucketData(const BucketLocator& bucket); + // storage directory. Returns the bucket data that was deleted. + QuotaErrorOr<mojom::BucketTableEntryPtr> DeleteBucketData( + const BucketLocator& bucket); // Returns the BucketLocator for the least recently used bucket. Will exclude // buckets with ids in `bucket_exceptions`, buckets marked persistent, and
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index 1527ffe9..85c1d51 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -599,13 +599,15 @@ EXPECT_EQ(db->SetBucketLastAccessTime(bucket_id1, base::Time::Now()), QuotaError::kNone); - BucketLocator bucketLocator = + BucketLocator bucket_locator = BucketLocator(bucket_id3, storage_key3, static_cast<blink::mojom::StorageType>(bucket3->type), bucket3->name == kDefaultBucketName); // Delete storage_key/type last access time information. - EXPECT_EQ(db->DeleteBucketData(bucketLocator), QuotaError::kNone); + auto deleted = db->DeleteBucketData(bucket_locator); + ASSERT_TRUE(deleted.ok()); + EXPECT_EQ(bucket_id3, BucketId::FromUnsafeValue(deleted.value()->bucket_id)); // Querying again to see if the deletion has worked. bucket_exceptions.clear(); @@ -686,7 +688,8 @@ EXPECT_EQ(db->SetStorageKeyLastAccessTime(storage_key, kTemp, now), QuotaError::kNone); - QuotaErrorOr<mojom::BucketTableEntryPtr> info = db->GetBucketInfo(bucket->id); + QuotaErrorOr<mojom::BucketTableEntryPtr> info = + db->GetBucketInfoForTest(bucket->id); EXPECT_TRUE(info.ok()); EXPECT_EQ(now, info.value()->last_accessed); EXPECT_EQ(1, info.value()->use_count); @@ -861,7 +864,7 @@ ASSERT_TRUE(bucket_result.ok()); QuotaErrorOr<mojom::BucketTableEntryPtr> info = - db->GetBucketInfo(bucket_result->id); + db->GetBucketInfoForTest(bucket_result->id); EXPECT_TRUE(info.ok()); EXPECT_EQ(0, info.value()->use_count); @@ -869,14 +872,14 @@ StorageKey::CreateFromStringForTesting("http://a/"), kTemp, base::Time::FromDoubleT(1.0)), QuotaError::kNone); - info = db->GetBucketInfo(bucket_result->id); + info = db->GetBucketInfoForTest(bucket_result->id); EXPECT_TRUE(info.ok()); EXPECT_EQ(1, info.value()->use_count); EXPECT_EQ(db->RegisterInitialStorageKeyInfo(storage_keys_by_type), QuotaError::kNone); - info = db->GetBucketInfo(bucket_result->id); + info = db->GetBucketInfoForTest(bucket_result->id); EXPECT_TRUE(info.ok()); EXPECT_EQ(1, info.value()->use_count); } @@ -915,39 +918,6 @@ EXPECT_TRUE(verifier.table.empty()); } -TEST_P(QuotaDatabaseTest, GetBucketInfo) { - using Entry = mojom::BucketTableEntryPtr; - StorageKey storage_key = StorageKey::CreateFromStringForTesting("http://go/"); - BucketId bucket_id = BucketId(123); - storage::mojom::StorageType type = kStorageTemp; - - Entry kTableEntries[] = {mojom::BucketTableEntry::New( - bucket_id.value(), storage_key.Serialize(), type, "test_bucket", -1, 100, - base::Time(), base::Time())}; - - auto db = CreateDatabase(use_in_memory_db()); - EXPECT_TRUE(EnsureOpened(db.get())); - AssignBucketTable(db.get(), kTableEntries); - - { - QuotaErrorOr<Entry> entry = db->GetBucketInfo(bucket_id); - EXPECT_TRUE(entry.ok()); - EXPECT_EQ(bucket_id.value(), entry.value()->bucket_id); - EXPECT_EQ(type, entry.value()->type); - EXPECT_EQ(storage_key.Serialize(), entry.value()->storage_key); - EXPECT_EQ(kTableEntries[0]->name, entry.value()->name); - EXPECT_EQ(kTableEntries[0]->use_count, entry.value()->use_count); - EXPECT_EQ(kTableEntries[0]->last_accessed, entry.value()->last_accessed); - EXPECT_EQ(kTableEntries[0]->last_modified, entry.value()->last_modified); - } - - { - // BucketId 456 is not in the database. - QuotaErrorOr<Entry> entry = db->GetBucketInfo(BucketId(456)); - EXPECT_FALSE(entry.ok()); - } -} - TEST_F(QuotaDatabaseTest, DeleteBucketData) { StorageKey storage_key = StorageKey::CreateFromStringForTesting("http://google/"); @@ -981,7 +951,7 @@ const base::FilePath bucket_path = CreateBucketPath(ProfilePath(), bucket); ASSERT_TRUE(base::PathExists(bucket_path)); - ASSERT_EQ(db->DeleteBucketData(bucket), QuotaError::kNone); + ASSERT_TRUE(db->DeleteBucketData(bucket).ok()); ASSERT_FALSE(base::PathExists(bucket_path)); } }
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index f687104..73153b81 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -634,7 +634,8 @@ QuotaClientTypes quota_client_types, bool commit_immediately, base::OnceCallback<void(BucketDataDeleter*, - blink::mojom::QuotaStatusCode)> callback) + QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback) : manager_(manager), bucket_(bucket), quota_client_types_(std::move(quota_client_types)), @@ -648,8 +649,7 @@ ~BucketDataDeleter() { // `callback` is non-null if the deleter gets destroyed before completing. if (callback_) { - std::move(callback_).Run(this, - blink::mojom::QuotaStatusCode::kErrorAbort); + std::move(callback_).Run(this, QuotaError::kUnknownError); } } @@ -729,26 +729,24 @@ weak_factory_.GetWeakPtr())); return; } - Complete(/*success=*/error_count_ == 0); + Complete(error_count_ == 0 ? QuotaError::kNone : QuotaError::kUnknownError); } - void DidDeleteBucketFromDatabase(QuotaError result) { + void DidDeleteBucketFromDatabase( + QuotaErrorOr<mojom::BucketTableEntryPtr> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - manager_->DidDatabaseWork(result != QuotaError::kDatabaseError); - Complete(result == QuotaError::kNone); + manager_->DidDatabaseWork(result.ok()); + Complete(std::move(result)); } - void Complete(bool success) { + void Complete(QuotaErrorOr<mojom::BucketTableEntryPtr> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO(crbug/1292216): Convert back into DCHECKs once issue is resolved. CHECK_EQ(remaining_clients_, 0u); CHECK(callback_); // May delete `this`. - std::move(callback_).Run( - this, success - ? blink::mojom::QuotaStatusCode::kOk - : blink::mojom::QuotaStatusCode::kErrorInvalidModification); + std::move(callback_).Run(this, std::move(result)); } SEQUENCE_CHECKER(sequence_checker_); @@ -764,7 +762,8 @@ int skipped_clients_ GUARDED_BY_CONTEXT(sequence_checker_) = 0; // Running the callback may delete this instance. - base::OnceCallback<void(BucketDataDeleter*, blink::mojom::QuotaStatusCode)> + base::OnceCallback<void(BucketDataDeleter*, + QuotaErrorOr<mojom::BucketTableEntryPtr>)> callback_ GUARDED_BY_CONTEXT(sequence_checker_); #if DCHECK_IS_ON() @@ -848,15 +847,16 @@ } void DidDeleteBucketData(BucketDataDeleter* deleter, - blink::mojom::QuotaStatusCode status) { + QuotaErrorOr<mojom::BucketTableEntryPtr> entry) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(deleter->completed()); DCHECK(base::Contains(bucket_deleters_, deleter)); bucket_deleters_.erase(deleter); - if (status != blink::mojom::QuotaStatusCode::kOk) + if (!entry.ok()) { ++error_count_; + } if (bucket_deleters_.empty()) Complete(/*success=*/error_count_ == 0); @@ -1376,8 +1376,17 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); + auto result_callback = base::BindOnce( + [](StatusCallback callback, + QuotaErrorOr<mojom::BucketTableEntryPtr> result) { + std::move(callback).Run( + (result.ok() || result.error() == QuotaError::kNone) + ? blink::mojom::QuotaStatusCode::kOk + : blink::mojom::QuotaStatusCode::kUnknown); + }, + std::move(callback)); DeleteBucketDataInternal(bucket, std::move(quota_client_types), - std::move(callback)); + std::move(result_callback)); } void QuotaManagerImpl::FindAndDeleteBucketData(const StorageKey& storage_key, @@ -2012,7 +2021,8 @@ void QuotaManagerImpl::DeleteBucketFromDatabase( const BucketLocator& bucket, bool commit_immediately, - base::OnceCallback<void(QuotaError)> callback) { + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); EnsureDatabaseOpened(); @@ -2028,8 +2038,9 @@ QuotaDatabase* database) { DCHECK(database); auto result = database->DeleteBucketData(bucket); - if (commit_immediately && result == QuotaError::kNone) + if (commit_immediately && result.ok()) { database->CommitNow(); + } return result; }, @@ -2037,42 +2048,42 @@ std::move(callback)); } -void QuotaManagerImpl::DidBucketDataEvicted( - mojom::BucketTableEntryPtr entry, - blink::mojom::QuotaStatusCode status) { +void QuotaManagerImpl::DidEvictBucketData( + QuotaErrorOr<mojom::BucketTableEntryPtr> entry) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); - // We only try to evict buckets that are not in use, so basically deletion - // attempt for eviction should not fail. Let's record the bucket if we get - // an error and exclude it from future eviction if the error happens - // consistently (> kThresholdOfErrorsToBeDenylisted). - if (status != blink::mojom::QuotaStatusCode::kOk) - buckets_in_error_[eviction_context_.evicted_bucket.id]++; - - if (status == blink::mojom::QuotaStatusCode::kOk) { + if (entry.ok()) { base::Time now = QuotaDatabase::GetNow(); base::UmaHistogramCounts1M( QuotaManagerImpl::kEvictedBucketAccessedCountHistogram, - entry->use_count); + entry.value()->use_count); base::UmaHistogramCounts1000( QuotaManagerImpl::kEvictedBucketDaysSinceAccessHistogram, - (now - entry->last_accessed).InDays()); + (now - entry.value()->last_accessed).InDays()); + std::move(eviction_context_.evict_bucket_data_callback) + .Run(QuotaError::kNone); + } else { + // We only try to evict buckets that are not in use, so basically deletion + // attempt for eviction should not fail. Let's record the bucket if we get + // an error and exclude it from future eviction if the error happens + // consistently (> kThresholdOfErrorsToBeDenylisted). + buckets_in_error_[eviction_context_.evicted_bucket.id]++; + std::move(eviction_context_.evict_bucket_data_callback).Run(entry.error()); } - - std::move(eviction_context_.evict_bucket_data_callback).Run(status); } void QuotaManagerImpl::DeleteBucketDataInternal( const BucketLocator& bucket, QuotaClientTypes quota_client_types, - StatusCallback callback) { + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); EnsureDatabaseOpened(); if (db_disabled_) { - std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess); + std::move(callback).Run(QuotaError::kDatabaseError); return; } auto bucket_deleter = std::make_unique<BucketDataDeleter>( @@ -2087,25 +2098,25 @@ // static void QuotaManagerImpl::DidDeleteBucketData( base::WeakPtr<QuotaManagerImpl> quota_manager, - StatusCallback delete_bucket_data_callback, + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> callback, BucketDataDeleter* deleter, - blink::mojom::QuotaStatusCode status_code) { - DCHECK(delete_bucket_data_callback); + QuotaErrorOr<mojom::BucketTableEntryPtr> result) { + DCHECK(callback); DCHECK(deleter); DCHECK(deleter->completed()); if (quota_manager) quota_manager->bucket_data_deleters_.erase(deleter); - std::move(delete_bucket_data_callback).Run(status_code); + std::move(callback).Run(std::move(result)); } void QuotaManagerImpl::DidDeleteBucketForRecreation( const BucketInitParams& params, base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, BucketInfo bucket_info, - blink::mojom::QuotaStatusCode status_code) { - if (status_code == blink::mojom::QuotaStatusCode::kOk) { + QuotaErrorOr<mojom::BucketTableEntryPtr> result) { + if (result.ok()) { UpdateOrCreateBucket(params, std::move(callback)); } else { std::move(callback).Run(QuotaError::kDatabaseError); @@ -2406,8 +2417,9 @@ buckets_deleter_ptr->GetBucketDeletionCallback()); } -void QuotaManagerImpl::EvictBucketData(const BucketLocator& bucket, - StatusCallback callback) { +void QuotaManagerImpl::EvictBucketData( + const BucketLocator& bucket, + base::OnceCallback<void(QuotaError)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); DCHECK_EQ(bucket.type, StorageType::kTemporary); @@ -2416,32 +2428,9 @@ eviction_context_.evicted_bucket = bucket; eviction_context_.evict_bucket_data_callback = std::move(callback); - PostTaskAndReplyWithResultForDBThread( - base::BindOnce( - [](BucketId bucket_id, QuotaDatabase* database) { - DCHECK(database); - return database->GetBucketInfo(bucket_id); - }, - bucket.id), - base::BindOnce(&QuotaManagerImpl::DidGetBucketInfoForEviction, - weak_factory_.GetWeakPtr(), bucket)); -} - -void QuotaManagerImpl::DidGetBucketInfoForEviction( - const BucketLocator& bucket, - QuotaErrorOr<mojom::BucketTableEntryPtr> result) { - DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); - - if (!result.ok()) { - std::move(eviction_context_.evict_bucket_data_callback) - .Run(blink::mojom::QuotaStatusCode::kErrorInvalidAccess); - return; - } - - DeleteBucketDataInternal( - bucket, AllQuotaClientTypes(), - base::BindOnce(&QuotaManagerImpl::DidBucketDataEvicted, - weak_factory_.GetWeakPtr(), std::move(result.value()))); + DeleteBucketDataInternal(bucket, AllQuotaClientTypes(), + base::BindOnce(&QuotaManagerImpl::DidEvictBucketData, + weak_factory_.GetWeakPtr())); } void QuotaManagerImpl::GetEvictionRoundInfo( @@ -2701,8 +2690,17 @@ return; } + auto result_callback = base::BindOnce( + [](StatusCallback callback, + QuotaErrorOr<mojom::BucketTableEntryPtr> result) { + std::move(callback).Run( + (result.ok() || result.error() == QuotaError::kNone) + ? blink::mojom::QuotaStatusCode::kOk + : blink::mojom::QuotaStatusCode::kUnknown); + }, + std::move(callback)); DeleteBucketDataInternal(result->ToBucketLocator(), AllQuotaClientTypes(), - std::move(callback)); + std::move(result_callback)); return; } @@ -2816,10 +2814,10 @@ base::BarrierClosure(buckets_to_delete.size(), base::BindOnce(std::move(callback), kept_buckets)); for (const BucketInfo& bucket : buckets_to_delete) { - StatusCallback on_delete_done = - base::BindOnce([](base::RepeatingClosure barrier, - blink::mojom::QuotaStatusCode) { barrier.Run(); }, - barrier); + auto on_delete_done = base::BindOnce( + [](base::RepeatingClosure barrier, + QuotaErrorOr<mojom::BucketTableEntryPtr>) { barrier.Run(); }, + barrier); DeleteBucketDataInternal(bucket.ToBucketLocator(), AllQuotaClientTypes(), std::move(on_delete_done)); }
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h index 6acda14..59bb109 100644 --- a/storage/browser/quota/quota_manager_impl.h +++ b/storage/browser/quota/quota_manager_impl.h
@@ -84,8 +84,9 @@ GetBucketCallback callback) = 0; // Called to evict a bucket. - virtual void EvictBucketData(const BucketLocator& bucket, - StatusCallback callback) = 0; + virtual void EvictBucketData( + const BucketLocator& bucket, + base::OnceCallback<void(QuotaError)> callback) = 0; protected: virtual ~QuotaEvictionHandler() = default; @@ -333,6 +334,8 @@ // // `callback` is always called. If this QuotaManager gets destroyed during // deletion, `callback` may be called with a kErrorAbort status. + // TODO(estade): Consider removing the status code from `callback` as it's + // unused outside of tests. void DeleteHostData(const std::string& host, blink::mojom::StorageType type, StatusCallback callback); @@ -378,7 +381,7 @@ void GetEvictionBucket(blink::mojom::StorageType type, GetBucketCallback callback) override; void EvictBucketData(const BucketLocator& bucket, - StatusCallback callback) override; + base::OnceCallback<void(QuotaError)> callback) override; void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override; // Called by UI and internal modules. @@ -524,7 +527,7 @@ EvictionContext(); ~EvictionContext(); BucketLocator evicted_bucket; - StatusCallback evict_bucket_data_callback; + base::OnceCallback<void(QuotaError)> evict_bucket_data_callback; }; // Lazily called on the IO thread when the first quota manager API is called. @@ -577,9 +580,11 @@ // Runs BucketDataDeleter which calls QuotaClients to clear data for the // bucket. Once the task is complete, calls the QuotaDatabase to delete the // bucket from the bucket table. - void DeleteBucketDataInternal(const BucketLocator& bucket, - QuotaClientTypes quota_client_types, - StatusCallback callback); + void DeleteBucketDataInternal( + const BucketLocator& bucket, + QuotaClientTypes quota_client_types, + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback); // Removes the BucketSetDataDeleter that completed its work. // @@ -594,10 +599,12 @@ // // This method is static because it must call `delete_bucket_data_callback` // even if the QuotaManagerImpl was destroyed. - static void DidDeleteBucketData(base::WeakPtr<QuotaManagerImpl> quota_manager, - StatusCallback delete_bucket_data_callback, - BucketDataDeleter* deleter, - blink::mojom::QuotaStatusCode status_code); + static void DidDeleteBucketData( + base::WeakPtr<QuotaManagerImpl> quota_manager, + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback, + BucketDataDeleter* deleter, + QuotaErrorOr<mojom::BucketTableEntryPtr> result); // Called after bucket data has been deleted from clients as well as the // database due to bucket expiration. This will recreate the bucket in the @@ -606,16 +613,17 @@ const BucketInitParams& params, base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, BucketInfo bucket_info, - blink::mojom::QuotaStatusCode status_code); + QuotaErrorOr<mojom::BucketTableEntryPtr> result); // Methods for eviction logic. void StartEviction(); - void DeleteBucketFromDatabase(const BucketLocator& bucket, - bool commit_immediately, - base::OnceCallback<void(QuotaError)> callback); + void DeleteBucketFromDatabase( + const BucketLocator& bucket, + bool commit_immediately, + base::OnceCallback<void(QuotaErrorOr<mojom::BucketTableEntryPtr>)> + callback); - void DidBucketDataEvicted(mojom::BucketTableEntryPtr entry, - blink::mojom::QuotaStatusCode status); + void DidEvictBucketData(QuotaErrorOr<mojom::BucketTableEntryPtr> entry); void ReportHistogram(); void DidGetTemporaryGlobalUsageForHistogram(int64_t usage, @@ -631,10 +639,6 @@ void DidGetEvictionBucket(GetBucketCallback callback, const absl::optional<BucketLocator>& bucket); - void DidGetBucketInfoForEviction( - const BucketLocator& bucket, - QuotaErrorOr<mojom::BucketTableEntryPtr> result); - void DidGetEvictionRoundInfo(); void GetLruEvictableBucket(blink::mojom::StorageType type,
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index a7ab186..c217b892 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -372,8 +372,8 @@ weak_factory_.GetWeakPtr())); } - QuotaStatusCode EvictBucketData(const BucketLocator& bucket) { - base::test::TestFuture<QuotaStatusCode> future; + QuotaError EvictBucketData(const BucketLocator& bucket) { + base::test::TestFuture<QuotaError> future; quota_manager_impl_->EvictBucketData(bucket, future.GetCallback()); return future.Get(); } @@ -2052,7 +2052,7 @@ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp); ASSERT_TRUE(bucket.ok()); - ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk); + ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaError::kNone); bucket = GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp); @@ -2075,7 +2075,7 @@ bucket = GetBucket(ToStorageKey("http://foo.com"), "logs", kTemp); ASSERT_TRUE(bucket.ok()); - ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk); + ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaError::kNone); bucket = GetBucket(ToStorageKey("http://foo.com"), "logs", kTemp); EXPECT_EQ(bucket.error(), QuotaError::kNotFound); @@ -2109,7 +2109,7 @@ GetBucket(ToStorageKey("http://foo.com"), kDefaultBucketName, kTemp); ASSERT_TRUE(bucket.ok()); - ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk); + ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaError::kNone); // Ensure use count and time since access are recorded. histograms.ExpectTotalCount( @@ -2129,7 +2129,7 @@ bucket = GetBucket(ToStorageKey("http://bar.com"), kDefaultBucketName, kTemp); ASSERT_TRUE(bucket.ok()); - ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaStatusCode::kOk); + ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), QuotaError::kNone); // The new use count should be logged. histograms.ExpectTotalCount( @@ -2176,8 +2176,7 @@ for (int i = 0; i < QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted + 1; ++i) { - ASSERT_EQ(EvictBucketData(bucket->ToBucketLocator()), - QuotaStatusCode::kErrorInvalidModification); + ASSERT_NE(EvictBucketData(bucket->ToBucketLocator()), QuotaError::kNone); } // The default bucket for "http://foo.com/" should still be in the database. @@ -2794,9 +2793,9 @@ ASSERT_EQ(QuotaError::kNone, corruption_error); // Deleting the bucket will result in an error. - EXPECT_EQ(FindAndDeleteBucketData(ToStorageKey("http://foo.com"), + EXPECT_NE(FindAndDeleteBucketData(ToStorageKey("http://foo.com"), kDefaultBucketName), - QuotaStatusCode::kErrorInvalidModification); + QuotaStatusCode::kOk); auto global_usage_result = GetGlobalUsage(kTemp); EXPECT_EQ(global_usage_result.usage, 0); @@ -3390,7 +3389,7 @@ bucket->ToBucketLocator(), {QuotaClientType::kIndexedDatabase}, delete_bucket_data_future.GetCallback()); quota_manager_impl_.reset(); - EXPECT_EQ(QuotaStatusCode::kErrorAbort, delete_bucket_data_future.Get()); + EXPECT_NE(QuotaStatusCode::kOk, delete_bucket_data_future.Get()); } TEST_F(QuotaManagerImplTest, DeleteBucketData_CallbackDeletesQuotaManager) {
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc index b4e2a089d..f0b31221 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -258,8 +258,7 @@ weak_factory_.GetWeakPtr())); } -void QuotaTemporaryStorageEvictor::OnEvictionComplete( - blink::mojom::QuotaStatusCode status) { +void QuotaTemporaryStorageEvictor::OnEvictionComplete(QuotaError status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is @@ -268,7 +267,7 @@ // permanently. The evictor skips buckets which had deletion errors a few // times. - if (status == blink::mojom::QuotaStatusCode::kOk) { + if (status == QuotaError::kNone) { ++statistics_.num_evicted_buckets; ++round_statistics_.num_evicted_buckets_in_round; // We many need to get rid of more space so reconsider immediately.
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.h b/storage/browser/quota/quota_temporary_storage_evictor.h index c7d9481..8319506 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/storage/browser/quota/quota_temporary_storage_evictor.h
@@ -24,6 +24,7 @@ namespace storage { class QuotaEvictionHandler; +enum class QuotaError; struct QuotaSettings; class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaTemporaryStorageEvictor { @@ -82,7 +83,7 @@ int64_t current_usage, bool current_usage_is_complete); void OnGotEvictionBucket(const absl::optional<BucketLocator>& bucket); - void OnEvictionComplete(blink::mojom::QuotaStatusCode status); + void OnEvictionComplete(QuotaError status); void OnEvictionRoundStarted(); void OnEvictionRoundFinished();
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 32cd3d7..3596c095 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -43,16 +43,15 @@ } void EvictBucketData(const BucketLocator& bucket, - StatusCallback callback) override { + base::OnceCallback<void(QuotaError)> callback) override { if (error_on_evict_buckets_data_) { - std::move(callback).Run( - blink::mojom::QuotaStatusCode::kErrorInvalidModification); + std::move(callback).Run(QuotaError::kIllegalOperation); return; } int64_t bucket_usage = EnsureBucketRemoved(bucket); if (bucket_usage >= 0) available_space_ += bucket_usage; - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk); + std::move(callback).Run(QuotaError::kNone); } void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override {
diff --git a/testing/buildbot/README.md b/testing/buildbot/README.md index fc8fefd..28ce834b 100644 --- a/testing/buildbot/README.md +++ b/testing/buildbot/README.md
@@ -17,9 +17,9 @@ ## A tour of the directory -* <master_name\>.json -- buildbot configuration json files. These are used to +* <builder_group\>.json -- test configuration json files. These are used to configure what tests are run on what builders, in addition to specifying -builder-specific arguments and parameters. They are now autogenerated, mainly +builder-specific arguments and parameters. They are autogenerated, mainly using the generate_buildbot_json tool in this directory. * [generate_buildbot_json.py](./generate_buildbot_json.py) -- generates most of the buildbot json files in this directory, based on data contained in the @@ -53,34 +53,32 @@ ### Buildbot configuration json Logic in the [Chromium recipe](https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipes/chromium.py) -looks up each builder for each master and test generators in -[chromium_tests/steps.py](https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipe_modules/chromium_tests/steps.py) -parse the data. For example, as of -[a6e11220](https://chromium.googlesource.com/chromium/tools/build/+/a6e11220d97d578d6ba091abd68beba28a004722) -[generate_gtest](https://chromium.googlesource.com/chromium/tools/build/+/a6e11220d97d578d6ba091abd68beba28a004722/scripts/slave/recipe_modules/chromium_tests/steps.py#416) -parses any entry in a builder's -['gtest_tests'](https://chromium.googlesource.com/chromium/src/+/5750756522296b2a9a08009d8d2cc90db3b88f56/testing/buildbot/chromium.android.json#1243) -entry. +looks up each builder for each builder group, and the test generators in +[chromium_tests/generators.py](https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipe_modules/chromium_tests/generators.py) +parse the data into structures defined in +[chromium_tests/steps.py.](https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipe_modules/chromium_tests/steps.py) ## Making changes All of the JSON files in this directory are autogenerated. The "how to use" section below describes the main tool, `generate_buildbot_json.py`, which -manages most of the waterfalls. It's no longer possible to hand-edit the JSON +manages most of the waterfalls. It's not possible to hand-edit the JSON files; presubmit checks forbid doing so. -Note that trybots mirror regular waterfall bots, with the mapping defined in +Note that trybots mirror regular waterfall bots, with the mapping defined either +in [trybots.py](https://chromium.googlesource.com/chromium/tools/build/+/HEAD/recipes/recipe_modules/chromium_tests/trybots.py). +or in the bots' `mirrors = ` attribute in their //infra/config/ definitions. This means that, as of -[81fcc4bc](https://chromium.googlesource.com/chromium/src/+/81fcc4bc6123ace8dd37db74fd2592e3e15ea46a/testing/buildbot/), +[5af7340b](https://chromium.googlesource.com/chromium/src/+/5af7340b4eb721380944ebc70ee28c44f21f0740/testing/buildbot/), if you want to edit -[linux_android_rel_ng](https://chromium.googlesource.com/chromium/tools/build/+/59a2653d5f143213f4f166714657808b0c646bd7/scripts/slave/recipe_modules/chromium_tests/trybots.py#142), +[linux-wayland-rel](https://chromium.googlesource.com/chromium/src/+/5af7340b4eb721380944ebc70ee28c44f21f0740/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star#280), you actually need to edit -[Android Tests](https://chromium.googlesource.com/chromium/src/+/81fcc4bc6123ace8dd37db74fd2592e3e15ea46a/testing/buildbot/chromium.linux.json#23). +[Linux Tests (Wayland)](https://chromium.googlesource.com/chromium/src/+/5af7340b4eb721380944ebc70ee28c44f21f0740/testing/buildbot/waterfalls.pyl#4895). ### Trying the changes on trybots You should be able to try build changes that affect the trybots directly (for -example, adding a test to linux_android_rel_ng should show up immediately in +example, adding a test to linux-rel should show up immediately in your tryjob). Non-trybot changes have to be landed manually :(. ## Capacity considerations when editing the configuration files @@ -89,25 +87,54 @@ for the established [Chromium CQ builders](https://chromium.googlesource.com/chromium/src/+/HEAD/infra/config/generated/cq-builders.md), as they operate under strict execution requirements. Make sure to get a resource -owner or a member of Chrome Browser Core EngProd to sign off that there is both -builder and swarmed test shard capacity available. +owner or a member of Chrome Browser Infra to sign off that there is both builder +and swarmed test shard capacity available. The suggested process for adding new +test suites to the CQ builders is to: +1. File a bug if one isn't already on-file for the addition of the tests, assign + it to yourself and apply the `Infra>Client>Chrome` component. +2. Add the tests in post-submit only mode, meaning the test would run on + post-submit bots, but not in pre-submit bots (a.k.a CQ bots). This can be + achieved by adding the `'ci_only': True` line to the test's definition in + the pyl files here. + ([Example](https://chromium.googlesource.com/chromium/src/+/79ed7956/testing/buildbot/test_suite_exceptions.pyl#934)) +3. After a sufficient amount of time (suggest 2 weeks), examine the results of + the test on the affected post-submit builders to determine the amount of + regressions they're catching. Note: unless the new test is providing unique + info/artifacts (e.g. stack traces, log files) that pre-existing tests lack, + exclude any regressions that _other_ tests also caught. We're only interested + in the regressions that these new tests catch alone. +4. If the new tests aren't excessively flaky (use + [this dashboard](http://shortn/_gP9pAC2IS3) to verify) and if they catch a + sufficient number of regressions over that trial period, then they can be + promoted to the CQ. To do so, see the steps below. + **Note:** The precise number of regressions that need to be caught depends on + the runtime of the tests. A large suite like browser_tests would need to + catch multiple per week, while a much smaller one need not catch as many. If + you're unsure if your tests meet the cutoff, proceed with the following steps + and specify how many regressions were caught in the justification of the + resource request. Depending on resources, the resource owners may not approve + of the request. In which case, see step #5. + 1. Calculate the amount of machine resources needed for the tests. Googlers + can use [this dashboard](http://shortn/_nyyTPgDJtF) to determine the + amount of bots required by comparing it to a similar suite on the same + builder. Do this for each CQ builder and each suite that's being added. + 2. File a [resource request](http://go/file-chrome-resource-bug) for the + required amount of machines. Make sure to specify the correct type of bots + needed (Linux, Windows, Android emulator, Android device, etc). + 3. If/when the request is approved and the resources have been deployed, you + can remove the `'ci_only': True` line for the definitions here to start + running the tests on the CQ. +5. If the new tests _don't_ catch regressions sufficiently frequently, then they + don't provide a high-enough signal to warrant running on the CQ. + Consequently, they should remain in post-submit only with a comment + explaining why. This can be revisited if things change. -In particular, pay attention to the capacity of the builder which compiles and -then triggers and collects swarming task shards. If you're adding a new test -suite to a bot, and know that the test suite adds one hour of testing time to -the swarming shards, and know that you have enough swarmed capacity to handle -that one hour of testing, that's a good start. But if that test *also* happens -to run in shards which take 10 minutes longer than any other shards on that -current bot, that means that the top-level builder will also take 10 minutes -longer to run -- or 20 minutes longer if there are failures and retries. Ensure -that the builder pool has enough capacity to handle that increase as well. - -Additionally, if your change is expected to increase utilization in the testing -pools by any more than 5 VMs or 50 CPU cores, it will need to be approved via -a resource request. (Consult anyone in //infra/OWNERS if you need help -calculating the resource usage of a test change.) See http://go/i-need-hw -for the steps involved in getting the approval. See [go/estimating-bot-capacity](https://goto.google.com/estimating-bot-capacity) -for guidance on how many hosts to request. +If your change doesn't affect the CQ but is expected to increase utilization in +the testing pools by any more than 5 VMs or 50 CPU cores, it will still need to +be approved via a resource request. Consult the +[dashboard](http://shortn/_nyyTPgDJtF) linked above to calculate the resource +usage of a test change. See http://go/i-need-hw for the steps involved in +getting the approval. ## How to use the generate_buildbot_json tool ### Test suites
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 18f9eea..3ad827d 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1876,7 +1876,7 @@ { "args": [], "cros_board": "dedede", - "cros_img": "dedede-release/R111-15326.0.0", + "cros_img": "dedede-release/R111-15327.0.0", "name": "lacros_all_tast_tests DEDEDE_RELEASE_LKGM", "resultdb": { "enable": true, @@ -1892,7 +1892,7 @@ { "args": [], "cros_board": "dedede", - "cros_img": "dedede-release/R111-15320.0.0", + "cros_img": "dedede-release/R111-15324.0.0", "name": "lacros_all_tast_tests DEDEDE_RELEASE_DEV", "resultdb": { "enable": true, @@ -1940,7 +1940,7 @@ { "args": [], "cros_board": "eve", - "cros_img": "eve-release/R111-15326.0.0", + "cros_img": "eve-release/R111-15327.0.0", "name": "lacros_all_tast_tests EVE_RELEASE_LKGM", "resultdb": { "enable": true, @@ -2083,7 +2083,7 @@ { "args": [], "cros_board": "jacuzzi", - "cros_img": "jacuzzi-release/R111-15326.0.0", + "cros_img": "jacuzzi-release/R111-15327.0.0", "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM", "resultdb": { "enable": true, @@ -2099,7 +2099,7 @@ { "args": [], "cros_board": "jacuzzi", - "cros_img": "jacuzzi-release/R111-15320.0.0", + "cros_img": "jacuzzi-release/R111-15324.0.0", "name": "lacros_all_tast_tests JACUZZI_RELEASE_DEV", "resultdb": { "enable": true, @@ -2188,7 +2188,7 @@ { "args": [], "cros_board": "herobrine", - "cros_img": "herobrine-release/R111-15326.0.0", + "cros_img": "herobrine-release/R111-15327.0.0", "name": "lacros_fyi_tast_tests HEROBRINE_RELEASE_LKGM", "resultdb": { "enable": true,
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 7e8096f..12e697c 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -2158,6 +2158,9 @@ ] }, "android-10-arm64-rel": { + "additional_compile_targets": [ + "monochrome_static_initializers" + ], "gtest_tests": [ { "args": [ @@ -14418,6 +14421,4066 @@ } ] }, + "android-13-x64-rel": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "absl_hardening_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "absl_hardening_tests", + "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "android_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "android_browsertests", + "test_id_prefix": "ninja://chrome/test:android_browsertests/" + }, + { + "args": [ + "--test-launcher-batch-limit=1", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "android_sync_integration_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "android_sync_integration_tests", + "test_id_prefix": "ninja://chrome/test:android_sync_integration_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "android_webview_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "android_webview_unittests", + "test_id_prefix": "ninja://android_webview/test:android_webview_unittests/" + }, + { + "args": [ + "-v", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_unittests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "base_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "base_unittests", + "test_id_prefix": "ninja://base:base_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "blink_common_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_common_unittests", + "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "blink_heap_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_heap_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "blink_platform_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_platform_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webkit_unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "webkit_unit_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "blink_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "boringssl_crypto_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "boringssl_crypto_tests", + "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "boringssl_ssl_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "boringssl_ssl_tests", + "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" + }, + { + "args": [ + "--gtest_filter=-*UsingRealWebcam*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "capture_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "capture_unittests", + "test_id_prefix": "ninja://media/capture:capture_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cast_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cast_unittests", + "test_id_prefix": "ninja://media/cast:cast_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "cc_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cc_unittests", + "test_id_prefix": "ninja://cc:cc_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_smoke_test" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "chrome_public_smoke_test", + "test_id_prefix": "ninja://chrome/android:chrome_public_smoke_test/" + }, + { + "args": [ + "--gtest_filter=-org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb", + "--git-revision=${got_revision}" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test": "chrome_public_test_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_test_apk/" + }, + { + "args": [ + "--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb", + "--git-revision=${got_revision}" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_apk_with_playstore" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "chrome_public_test_apk_with_playstore", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "chrome_public_test_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb", + "--git-revision=${got_revision}" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_unit_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_unit_test_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_unit_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "components_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "components_browsertests", + "test_id_prefix": "ninja://components:components_browsertests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "components_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test": "components_unittests", + "test_id_prefix": "ninja://components:components_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 15 + }, + "test": "content_browsertests", + "test_id_prefix": "ninja://content/test:content_browsertests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "content_shell_test_apk", + "test_id_prefix": "ninja://content/shell/android:content_shell_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "content_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "content_unittests", + "test_id_prefix": "ninja://content/test:content_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "crashpad_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "crashpad_tests", + "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "crypto_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "crypto_unittests", + "test_id_prefix": "ninja://crypto:crypto_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "device_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "device_unittests", + "test_id_prefix": "ninja://device:device_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "display_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "display_unittests", + "test_id_prefix": "ninja://ui/display:display_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "events_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "events_unittests", + "test_id_prefix": "ninja://ui/events:events_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gcm_unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gcm_unit_tests", + "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gfx_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gfx_unittests", + "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gin_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gin_unittests", + "test_id_prefix": "ninja://gin:gin_unittests/" + }, + { + "args": [ + "--use-cmd-decoder=validating", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gl_tests_validating" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "gl_tests_validating", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_tests", + "test_id_prefix": "ninja://gpu:gl_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gl_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_unittests", + "test_id_prefix": "ninja://ui/gl:gl_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "google_apis_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "google_apis_unittests", + "test_id_prefix": "ninja://google_apis:google_apis_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gpu_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gpu_unittests", + "test_id_prefix": "ninja://gpu:gpu_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "gwp_asan_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gwp_asan_unittests", + "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ipc_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ipc_tests", + "test_id_prefix": "ninja://ipc:ipc_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "latency_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "latency_unittests", + "test_id_prefix": "ninja://ui/latency:latency_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "libjingle_xmpp_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "libjingle_xmpp_unittests", + "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "liburlpattern_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "liburlpattern_unittests", + "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "media_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "media_unittests", + "test_id_prefix": "ninja://media:media_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "midi_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "midi_unittests", + "test_id_prefix": "ninja://media/midi:midi_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "mojo_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "mojo_test_apk", + "test_id_prefix": "ninja://mojo/public/java/system:mojo_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "mojo_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "mojo_unittests", + "test_id_prefix": "ninja://mojo:mojo_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "monochrome_public_bundle_smoke_test" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "monochrome_public_bundle_smoke_test", + "test_id_prefix": "ninja://chrome/android:monochrome_public_bundle_smoke_test/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "monochrome_public_smoke_test" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "monochrome_public_smoke_test", + "test_id_prefix": "ninja://chrome/android:monochrome_public_smoke_test/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "net_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "net_unittests", + "test_id_prefix": "ninja://net:net_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "perfetto_unittests", + "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "sandbox_linux_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "sandbox_linux_unittests", + "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "services_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "services_unittests", + "test_id_prefix": "ninja://services:services_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "shell_dialogs_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "shell_dialogs_unittests", + "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "skia_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "skia_unittests", + "test_id_prefix": "ninja://skia:skia_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "sql_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "sql_unittests", + "test_id_prefix": "ninja://sql:sql_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "storage_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "storage_unittests", + "test_id_prefix": "ninja://storage:storage_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "system_webview_shell_layout_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "system_webview_shell_layout_test_apk", + "test_id_prefix": "ninja://android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ui_android_unittests", + "test_id_prefix": "ninja://ui/android:ui_android_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_base_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ui_base_unittests", + "test_id_prefix": "ninja://ui/base:ui_base_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "ui_touch_selection_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ui_touch_selection_unittests", + "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "unit_tests", + "test_id_prefix": "ninja://chrome/test:unit_tests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "url_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "url_unittests", + "test_id_prefix": "ninja://url:url_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "viz_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "viz_unittests", + "test_id_prefix": "ninja://components/viz:viz_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webview_instrumentation_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 7 + }, + "test": "webview_instrumentation_test_apk", + "test_id_prefix": "ninja://android_webview/test:webview_instrumentation_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webview_trichrome_64_cts_tests full_mode" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "webview_trichrome_64_cts_tests full_mode", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/android_webview/tools/cts_archive", + "location": "android_webview/tools/cts_archive", + "revision": "C4m9-gZKvvtS0-KQ9cMRi6wEfZH_TeWSiXEgsgtGtsMC" + } + ], + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "webview_trichrome_64_cts_tests", + "test_id_prefix": "ninja://android_webview/test:webview_trichrome_64_cts_tests/", + "variant_id": "full_mode" + }, + { + "args": [ + "--exclude-annotation", + "AppModeFull", + "--test-apk-as-instant", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webview_trichrome_64_cts_tests instant_mode" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "webview_trichrome_64_cts_tests instant_mode", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/android_webview/tools/cts_archive", + "location": "android_webview/tools/cts_archive", + "revision": "C4m9-gZKvvtS0-KQ9cMRi6wEfZH_TeWSiXEgsgtGtsMC" + } + ], + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "webview_trichrome_64_cts_tests", + "test_id_prefix": "ninja://android_webview/test:webview_trichrome_64_cts_tests/", + "variant_id": "instant_mode" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webview_ui_test_app_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "webview_ui_test_app_test_apk", + "test_id_prefix": "ninja://android_webview/tools/automated_ui_tests:webview_ui_test_app_test_apk/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "wtf_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "wtf_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android33.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "zlib_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-18.04", + "pool": "chromium.tests.avd" + } + ], + "named_caches": [ + { + "name": "generic_android33", + "path": ".android_emulator/generic_android33" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android33" + } + ] + }, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "zlib_unittests", + "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" + } + ] + }, "android-arm64-proguard-rel": { "additional_compile_targets": [ "all" @@ -22646,79 +26709,6 @@ }, { "args": [ - "--use-persistent-shell", - "--use-persistent-shell", - "--gs-results-bucket=chromium-result-details", - "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android24.textpb", - "--git-revision=${got_revision}", - "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter" - ], - "ci_only": true, - "experiment_percentage": 100, - "isolate_profile_data": true, - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "chrome_public_persistent_shell_test_apk" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "chrome_public_persistent_shell_test_apk", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cores": "4", - "cpu": "x86-64", - "device_os": null, - "device_type": null, - "os": "Ubuntu-18.04", - "pool": "chromium.tests.avd" - } - ], - "named_caches": [ - { - "name": "generic_android24", - "path": ".android_emulator/generic_android24" - } - ], - "optional_dimensions": { - "60": [ - { - "caches": "generic_android24" - } - ] - }, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test": "chrome_public_test_apk", - "test_id_prefix": "ninja://chrome/android:chrome_public_test_apk/" - }, - { - "args": [ "--gtest_filter=org.chromium.chrome.browser.contextualsearch.ContextualSearchManagerTest.test*ExternalNavigationWithUserGesture*:org.chromium.shape_detection.*", "--use-persistent-shell", "--gs-results-bucket=chromium-result-details", @@ -22857,78 +26847,6 @@ { "args": [ "--use-persistent-shell", - "--use-persistent-shell", - "--gs-results-bucket=chromium-result-details", - "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android24.textpb", - "--git-revision=${got_revision}" - ], - "ci_only": true, - "experiment_percentage": 100, - "isolate_profile_data": true, - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "chrome_public_persistent_shell_unit_test_apk" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "chrome_public_persistent_shell_unit_test_apk", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cores": "4", - "cpu": "x86-64", - "device_os": null, - "device_type": null, - "os": "Ubuntu-18.04", - "pool": "chromium.tests.avd" - } - ], - "named_caches": [ - { - "name": "generic_android24", - "path": ".android_emulator/generic_android24" - } - ], - "optional_dimensions": { - "60": [ - { - "caches": "generic_android24" - } - ] - }, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test": "chrome_public_unit_test_apk", - "test_id_prefix": "ninja://chrome/android:chrome_public_unit_test_apk/" - }, - { - "args": [ - "--use-persistent-shell", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android24.textpb" @@ -23117,73 +27035,6 @@ { "args": [ "--use-persistent-shell", - "--use-persistent-shell", - "--gs-results-bucket=chromium-result-details", - "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android24.textpb", - "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.content_browsertests.filter" - ], - "ci_only": true, - "experiment_percentage": 100, - "isolate_profile_data": true, - "merge": { - "args": [ - "--bucket", - "chromium-result-details", - "--test-name", - "content_browsertests_persistent_shell" - ], - "script": "//build/android/pylib/results/presentation/test_results_presentation.py" - }, - "name": "content_browsertests_persistent_shell", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cores": "8", - "cpu": "x86-64", - "device_os": null, - "device_type": null, - "os": "Ubuntu-18.04", - "pool": "chromium.tests.avd" - } - ], - "named_caches": [ - { - "name": "generic_android24", - "path": ".android_emulator/generic_android24" - } - ], - "optional_dimensions": { - "60": [ - { - "caches": "generic_android24" - } - ] - }, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test": "content_browsertests", - "test_id_prefix": "ninja://content/test:content_browsertests/" - }, - { - "args": [ - "--use-persistent-shell", "--gs-results-bucket=chromium-result-details", "--recover-devices", "--avd-config=../../tools/android/avd/proto/generic_android24.textpb", @@ -27319,9 +31170,6 @@ ] }, "android-pie-arm64-rel": { - "additional_compile_targets": [ - "monochrome_static_initializers" - ], "gtest_tests": [ { "args": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index b6b0a41d..e38c4a965 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -42,7 +42,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_modern_public_bundle_smoke_test", "test_id_prefix": "ninja://chrome/android:chrome_modern_public_bundle_smoke_test/" @@ -86,7 +87,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_public_smoke_test", "test_id_prefix": "ninja://chrome/android:chrome_public_smoke_test/" @@ -137,6 +139,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 19 }, "test": "chrome_public_test_apk", @@ -184,6 +187,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "chrome_public_test_vr_apk", @@ -235,6 +239,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "chrome_public_unit_test_apk", @@ -279,7 +284,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_webapk_integration_tests", "test_id_prefix": "ninja://chrome/test/android:chrome_webapk_integration_tests/" @@ -324,6 +330,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "content_shell_test_apk", @@ -368,7 +375,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_test_apk", "test_id_prefix": "ninja://mojo/public/java/system:mojo_test_apk/" @@ -412,7 +420,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "vr_android_unittests", "test_id_prefix": "ninja://chrome/browser/android/vr:vr_android_unittests/" @@ -457,6 +466,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 7 }, "test": "webview_instrumentation_test_apk", @@ -501,7 +511,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "webview_ui_test_app_test_apk", "test_id_prefix": "ninja://android_webview/tools/automated_ui_tests:webview_ui_test_app_test_apk/" @@ -793,7 +804,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -838,6 +850,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "android_browsertests", @@ -883,7 +896,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "android_sync_integration_tests", "test_id_prefix": "ninja://chrome/test:android_sync_integration_tests/" @@ -927,7 +941,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "android_webview_unittests", "test_id_prefix": "ninja://android_webview/test:android_webview_unittests/" @@ -955,7 +970,8 @@ "device_type": "walleye", "os": "Android" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_unittests", "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", @@ -1000,7 +1016,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -1044,7 +1061,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -1088,7 +1106,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -1132,7 +1151,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -1178,6 +1198,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test": "blink_unittests", @@ -1222,7 +1243,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -1266,7 +1288,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -1311,7 +1334,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -1355,7 +1379,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -1399,7 +1424,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -1443,7 +1469,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_webapk_integration_tests", "test_id_prefix": "ninja://chrome/test/android:chrome_webapk_integration_tests/" @@ -1487,7 +1514,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -1532,6 +1560,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test": "components_unittests", @@ -1577,6 +1606,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 15 }, "test": "content_browsertests", @@ -1622,6 +1652,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "content_unittests", @@ -1666,7 +1697,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -1710,7 +1742,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -1754,7 +1787,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -1798,7 +1832,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -1842,7 +1877,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -1886,7 +1922,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -1930,7 +1967,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -1975,7 +2013,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -2022,7 +2061,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gl_tests", "test_id_prefix": "ninja://gpu:gl_tests/" @@ -2066,7 +2106,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gl_unittests", "test_id_prefix": "ninja://ui/gl:gl_unittests/" @@ -2110,7 +2151,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -2154,7 +2196,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -2198,7 +2241,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -2242,7 +2286,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -2286,7 +2331,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -2330,7 +2376,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -2374,7 +2421,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -2418,7 +2466,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -2462,7 +2511,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -2506,7 +2556,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -2551,6 +2602,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "net_unittests", @@ -2595,7 +2647,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sandbox_linux_unittests", "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" @@ -2639,7 +2692,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -2683,7 +2737,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -2727,7 +2782,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -2771,7 +2827,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -2815,7 +2872,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -2859,7 +2917,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_android_unittests", "test_id_prefix": "ninja://ui/android:ui_android_unittests/" @@ -2903,7 +2962,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -2947,7 +3007,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -2992,6 +3053,7 @@ "name": "shard #${SHARD_INDEX} logcats" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "unit_tests", @@ -3036,7 +3098,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -3080,7 +3143,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -3124,7 +3188,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "vr_android_unittests", "test_id_prefix": "ninja://chrome/browser/android/vr:vr_android_unittests/" @@ -3168,7 +3233,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "vr_common_unittests", "test_id_prefix": "ninja://chrome/browser/vr:vr_common_unittests/" @@ -3212,7 +3278,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -3256,7 +3323,8 @@ ], "name": "shard #${SHARD_INDEX} logcats" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -3285,7 +3353,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -3307,7 +3376,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -3329,7 +3399,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "aura_unittests", "test_id_prefix": "ninja://ui/aura:aura_unittests/" @@ -3352,6 +3423,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 }, "test": "base_unittests", @@ -3374,7 +3446,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -3396,7 +3469,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -3418,7 +3492,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -3441,6 +3516,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 }, "test": "blink_platform_unittests", @@ -3464,6 +3540,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 30 }, "test": "blink_unittests", @@ -3486,7 +3563,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -3508,7 +3586,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -3530,7 +3609,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -3552,7 +3632,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_runner_browsertests", "test_id_prefix": "ninja://fuchsia_web/runners:cast_runner_browsertests/" @@ -3574,7 +3655,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_runner_integration_tests", "test_id_prefix": "ninja://fuchsia_web/runners:cast_runner_integration_tests/" @@ -3596,7 +3678,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_runner_unittests", "test_id_prefix": "ninja://fuchsia_web/runners:cast_runner_unittests/" @@ -3619,6 +3702,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 4 }, "test": "cc_unittests", @@ -3641,7 +3725,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -3663,7 +3748,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -3686,6 +3772,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "components_unittests", @@ -3708,7 +3795,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "compositor_unittests", "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" @@ -3734,6 +3822,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 14 }, "test": "content_browsertests", @@ -3757,6 +3846,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test": "content_unittests", @@ -3779,7 +3869,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "courgette_unittests", "test_id_prefix": "ninja://courgette:courgette_unittests/" @@ -3801,7 +3892,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -3823,7 +3915,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -3845,7 +3938,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -3867,7 +3961,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -3889,7 +3984,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -3911,7 +4007,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -3934,6 +4031,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "gfx_unittests", @@ -3956,7 +4054,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -3978,7 +4077,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -4001,6 +4101,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 }, "test": "gpu_unittests", @@ -4023,7 +4124,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -4046,6 +4148,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test": "headless_browsertests", @@ -4068,7 +4171,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_unittests", "test_id_prefix": "ninja://headless:headless_unittests/" @@ -4090,7 +4194,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -4112,7 +4217,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -4135,6 +4241,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "media_unittests", @@ -4157,7 +4264,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -4179,7 +4287,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -4201,7 +4310,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_core_unittests", "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/" @@ -4224,6 +4334,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "mojo_unittests", @@ -4246,7 +4357,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -4270,6 +4382,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 14 }, "test": "net_unittests", @@ -4293,7 +4406,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_gl_unittests", "test_id_prefix": "ninja://ui/ozone/gl:ozone_gl_unittests/" @@ -4315,7 +4429,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" @@ -4337,7 +4452,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -4359,7 +4475,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -4383,6 +4500,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 7 }, "test": "services_unittests", @@ -4405,7 +4523,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -4427,7 +4546,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -4449,7 +4569,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -4471,7 +4592,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -4493,7 +4615,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -4516,7 +4639,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -4538,7 +4662,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -4560,7 +4685,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -4583,7 +4709,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_examples_unittests", "test_id_prefix": "ninja://ui/views/examples:views_examples_unittests/" @@ -4606,7 +4733,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -4629,7 +4757,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -4652,6 +4781,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 28 }, "test": "web_engine_browsertests", @@ -4675,7 +4805,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "web_engine_integration_tests", "test_id_prefix": "ninja://fuchsia_web/webengine:web_engine_integration_tests/" @@ -4699,6 +4830,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test": "web_engine_integration_tests_cfv1", @@ -4721,7 +4853,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "web_engine_unittests", "test_id_prefix": "ninja://fuchsia_web/webengine:web_engine_unittests/" @@ -4743,7 +4876,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "web_runner_integration_tests", "test_id_prefix": "ninja://fuchsia_web/runners:web_runner_integration_tests/" @@ -4765,7 +4899,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wm_unittests", "test_id_prefix": "ninja://ui/wm:wm_unittests/" @@ -4787,7 +4922,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -4809,7 +4945,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -4837,7 +4974,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/" } @@ -4893,7 +5031,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/", "variant_id": "iPhone 6s 15.5" @@ -4946,7 +5085,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/", "variant_id": "iPhone 8 16.2" @@ -4999,7 +5139,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -5052,7 +5193,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPad Air 2 15.5" @@ -5105,7 +5247,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -5158,7 +5301,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -5211,7 +5355,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone 6s 15.5" @@ -5264,7 +5409,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -5317,7 +5463,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone 8 16.2" @@ -5370,7 +5517,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -5423,7 +5571,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -5476,7 +5625,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://base:base_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -5529,7 +5679,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/", "variant_id": "iPhone 6s 15.5" @@ -5582,7 +5733,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/", "variant_id": "iPhone 8 16.2" @@ -5635,7 +5787,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/", "variant_id": "iPhone 6s 15.5" @@ -5688,7 +5841,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/", "variant_id": "iPhone 8 16.2" @@ -5741,7 +5895,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -5794,7 +5949,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPad Air 2 15.5" @@ -5847,7 +6003,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -5900,7 +6057,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -5953,7 +6111,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone 6s 15.5" @@ -6006,7 +6165,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -6059,7 +6219,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone 8 16.2" @@ -6112,7 +6273,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -6165,7 +6327,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -6218,7 +6381,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://components:components_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -6271,7 +6435,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/", "variant_id": "iPhone 6s 15.5" @@ -6324,7 +6489,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/", "variant_id": "iPhone 8 16.2" @@ -6377,7 +6543,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://crypto:crypto_unittests/", "variant_id": "iPhone 6s 15.5" @@ -6430,7 +6597,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://crypto:crypto_unittests/", "variant_id": "iPhone 8 16.2" @@ -6483,7 +6651,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -6536,7 +6705,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPad Air 2 15.5" @@ -6589,7 +6759,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -6642,7 +6813,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -6695,7 +6867,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone 6s 15.5" @@ -6748,7 +6921,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -6801,7 +6975,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone 8 16.2" @@ -6854,7 +7029,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -6907,7 +7083,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -6960,7 +7137,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/gfx:gfx_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -7013,7 +7191,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://google_apis:google_apis_unittests/", "variant_id": "iPhone 6s 15.5" @@ -7066,7 +7245,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://google_apis:google_apis_unittests/", "variant_id": "iPhone 8 16.2" @@ -7120,7 +7300,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -7174,7 +7355,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPad Air 2 15.5" @@ -7228,7 +7410,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -7282,7 +7465,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -7336,7 +7520,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPhone 7 15.5" @@ -7390,7 +7575,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPhone 8 16.2" @@ -7444,7 +7630,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPhone X 15.5" @@ -7498,7 +7685,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module/", "variant_id": "iPhone X 16.2" @@ -7553,6 +7741,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7608,6 +7797,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7663,6 +7853,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7718,6 +7909,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7773,6 +7965,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7828,6 +8021,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7883,6 +8077,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7938,6 +8133,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module/", @@ -7993,6 +8189,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8048,6 +8245,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8103,6 +8301,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8158,6 +8357,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8213,6 +8413,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8268,6 +8469,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8323,6 +8525,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8378,6 +8581,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module/", @@ -8433,6 +8637,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8488,6 +8693,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8543,6 +8749,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8598,6 +8805,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8653,6 +8861,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8708,6 +8917,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8763,6 +8973,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8818,6 +9029,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", @@ -8872,7 +9084,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -8926,7 +9139,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPad Air 2 15.5" @@ -8980,7 +9194,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -9034,7 +9249,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -9088,7 +9304,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPhone 7 15.5" @@ -9142,7 +9359,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPhone 8 16.2" @@ -9196,7 +9414,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPhone X 15.5" @@ -9250,7 +9469,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module/", "variant_id": "iPhone X 16.2" @@ -9305,6 +9525,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9360,6 +9581,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9415,6 +9637,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9470,6 +9693,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9525,6 +9749,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9580,6 +9805,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9635,6 +9861,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9690,6 +9917,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", @@ -9743,7 +9971,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -9796,7 +10025,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPad Air 2 15.5" @@ -9849,7 +10079,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -9902,7 +10133,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -9955,7 +10187,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone 6s 15.5" @@ -10008,7 +10241,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -10061,7 +10295,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone 8 16.2" @@ -10114,7 +10349,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -10167,7 +10403,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -10220,7 +10457,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test:ios_chrome_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -10274,7 +10512,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -10328,7 +10567,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPad Air 2 15.5" @@ -10382,7 +10622,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -10436,7 +10677,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -10490,7 +10732,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPhone 7 15.5" @@ -10544,7 +10787,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPhone 8 16.2" @@ -10598,7 +10842,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPhone X 15.5" @@ -10652,7 +10897,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module/", "variant_id": "iPhone X 16.2" @@ -10705,7 +10951,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/components:ios_components_unittests/", "variant_id": "iPhone 6s 15.5" @@ -10758,7 +11005,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/components:ios_components_unittests/", "variant_id": "iPhone 8 16.2" @@ -10812,6 +11060,7 @@ "path": "Runtime-ios-15.5" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/net:ios_net_unittests/", @@ -10866,6 +11115,7 @@ "path": "Runtime-ios-16.2" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://ios/net:ios_net_unittests/", @@ -10919,7 +11169,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://remoting/ios:ios_remoting_unittests/", "variant_id": "iPhone 6s 15.5" @@ -10972,7 +11223,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://remoting/ios:ios_remoting_unittests/", "variant_id": "iPhone 8 16.2" @@ -11026,7 +11278,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -11080,7 +11333,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPad Air 2 15.5" @@ -11134,7 +11388,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -11188,7 +11443,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -11242,7 +11498,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPhone 7 15.5" @@ -11296,7 +11553,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPhone 8 16.2" @@ -11350,7 +11608,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPhone X 15.5" @@ -11404,7 +11663,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/showcase:ios_showcase_eg2tests_module/", "variant_id": "iPhone X 16.2" @@ -11457,7 +11717,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/testing:ios_testing_unittests/", "variant_id": "iPhone 6s 15.5" @@ -11510,7 +11771,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/testing:ios_testing_unittests/", "variant_id": "iPhone 8 16.2" @@ -11563,7 +11825,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -11616,7 +11879,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPad Air 2 15.5" @@ -11669,7 +11933,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -11722,7 +11987,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -11775,7 +12041,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone 6s 15.5" @@ -11828,7 +12095,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone 6s Plus 15.5" @@ -11881,7 +12149,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone 8 16.2" @@ -11934,7 +12203,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone 8 Plus 16.2" @@ -11987,7 +12257,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -12040,7 +12311,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_inttests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -12094,7 +12366,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -12148,7 +12421,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPad Air 2 15.5" @@ -12202,7 +12476,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -12256,7 +12531,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -12310,7 +12586,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPhone 6s 15.5" @@ -12364,7 +12641,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPhone 7 15.5" @@ -12418,7 +12696,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPhone 8 16.2" @@ -12472,7 +12751,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web/shell/test:ios_web_shell_eg2tests_module/", "variant_id": "iPhone X 16.2" @@ -12525,7 +12805,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -12578,7 +12859,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPad Air 2 15.5" @@ -12631,7 +12913,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -12684,7 +12967,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -12737,7 +13021,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone 6s 15.5" @@ -12790,7 +13075,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -12843,7 +13129,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone 8 16.2" @@ -12896,7 +13183,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -12949,7 +13237,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -13002,7 +13291,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web:ios_web_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -13055,7 +13345,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -13108,7 +13399,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPad Air 2 15.5" @@ -13161,7 +13453,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -13214,7 +13507,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -13267,7 +13561,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone 6s 15.5" @@ -13320,7 +13615,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone 6s Plus 15.5" @@ -13373,7 +13669,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone 8 16.2" @@ -13426,7 +13723,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone 8 Plus 16.2" @@ -13479,7 +13777,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -13532,7 +13831,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_inttests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -13585,7 +13885,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -13638,7 +13939,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPad Air 2 15.5" @@ -13691,7 +13993,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -13744,7 +14047,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -13797,7 +14101,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone 6s 15.5" @@ -13850,7 +14155,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -13903,7 +14209,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone 8 16.2" @@ -13956,7 +14263,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -14009,7 +14317,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -14062,7 +14371,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ios/web_view:ios_web_view_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -14115,7 +14425,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://net:net_unittests/", "variant_id": "iPhone 6s 15.5" @@ -14168,7 +14479,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://net:net_unittests/", "variant_id": "iPhone 8 16.2" @@ -14221,7 +14533,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://services:services_unittests/", "variant_id": "iPhone 6s 15.5" @@ -14274,7 +14587,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://services:services_unittests/", "variant_id": "iPhone 8 16.2" @@ -14327,7 +14641,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -14380,7 +14695,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPad Air 2 15.5" @@ -14433,7 +14749,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -14486,7 +14803,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -14539,7 +14857,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone 6s 15.5" @@ -14592,7 +14911,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -14645,7 +14965,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone 8 16.2" @@ -14698,7 +15019,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -14751,7 +15073,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -14804,7 +15127,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://skia:skia_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -14857,7 +15181,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://sql:sql_unittests/", "variant_id": "iPhone 6s 15.5" @@ -14910,7 +15235,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://sql:sql_unittests/", "variant_id": "iPhone 8 16.2" @@ -14963,7 +15289,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPad Air (3rd generation) 16.2" @@ -15016,7 +15343,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPad Air 2 15.5" @@ -15069,7 +15397,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 15.5" @@ -15122,7 +15451,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" @@ -15175,7 +15505,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone 6s 15.5" @@ -15228,7 +15559,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone 6s Plus 15.5" @@ -15281,7 +15613,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone 8 16.2" @@ -15334,7 +15667,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone 8 Plus 16.2" @@ -15387,7 +15721,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone SE (1st generation) 15.5" @@ -15440,7 +15775,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/base:ui_base_unittests/", "variant_id": "iPhone SE (3rd generation) 16.2" @@ -15493,7 +15829,8 @@ "name": "runtime_ios_15_5", "path": "Runtime-ios-15.5" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://url:url_unittests/", "variant_id": "iPhone 6s 15.5" @@ -15546,7 +15883,8 @@ "name": "runtime_ios_16_2", "path": "Runtime-ios-16.2" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://url:url_unittests/", "variant_id": "iPhone 8 16.2" @@ -15570,7 +15908,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -15587,7 +15926,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -15604,7 +15944,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_unittests", "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", @@ -15622,7 +15963,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "app_shell_unittests", "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" @@ -15639,7 +15981,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ash_components_unittests", "test_id_prefix": "ninja://ash/components:ash_components_unittests/" @@ -15657,7 +16000,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ash_crosapi_tests", "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" @@ -15675,6 +16019,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 5 }, "test": "ash_unittests", @@ -15692,7 +16037,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ash_webui_unittests", "test_id_prefix": "ninja://ash/webui:ash_webui_unittests/" @@ -15709,7 +16055,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "aura_unittests", "test_id_prefix": "ninja://ui/aura:aura_unittests/" @@ -15726,7 +16073,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -15743,7 +16091,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -15760,7 +16109,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -15777,7 +16127,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -15794,7 +16145,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -15812,7 +16164,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -15829,7 +16182,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -15846,7 +16200,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -15864,6 +16219,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 50 }, "test": "browser_tests", @@ -15884,7 +16240,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -15901,7 +16258,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -15918,7 +16276,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -15935,7 +16294,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_app_unittests", "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" @@ -15952,7 +16312,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromedriver_unittests", "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" @@ -15969,7 +16330,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromeos_components_unittests", "test_id_prefix": "ninja://chromeos/components:chromeos_components_unittests/" @@ -15986,7 +16348,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromeos_unittests", "test_id_prefix": "ninja://chromeos:chromeos_unittests/" @@ -16003,7 +16366,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -16020,7 +16384,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -16037,7 +16402,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -16054,7 +16420,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "compositor_unittests", "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" @@ -16072,6 +16439,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test": "content_browsertests", @@ -16089,7 +16457,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", "test_id_prefix": "ninja://content/test:content_unittests/" @@ -16106,7 +16475,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -16123,7 +16493,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -16140,7 +16511,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "dbus_unittests", "test_id_prefix": "ninja://dbus:dbus_unittests/" @@ -16157,7 +16529,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -16174,7 +16547,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -16191,7 +16565,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -16208,7 +16583,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "exo_unittests", "test_id_prefix": "ninja://components/exo:exo_unittests/" @@ -16225,7 +16601,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_browsertests", "test_id_prefix": "ninja://extensions:extensions_browsertests/" @@ -16242,7 +16619,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -16259,7 +16637,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -16276,7 +16655,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -16293,7 +16673,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -16310,7 +16691,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -16327,7 +16709,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gl_unittests_ozone", "test_id_prefix": "ninja://ui/gl:gl_unittests_ozone/" @@ -16344,7 +16727,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -16361,7 +16745,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -16378,7 +16763,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -16396,6 +16782,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 10 }, "test": "interactive_ui_tests", @@ -16413,7 +16800,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -16430,7 +16818,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "keyboard_unittests", "test_id_prefix": "ninja://ash/keyboard/ui:keyboard_unittests/" @@ -16447,7 +16836,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -16464,7 +16854,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -16481,7 +16872,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -16498,7 +16890,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -16515,7 +16908,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -16532,7 +16926,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -16549,7 +16944,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_core_unittests", "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/" @@ -16566,7 +16962,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -16583,7 +16980,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "nacl_loader_unittests", "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" @@ -16600,7 +16998,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -16617,7 +17016,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -16637,7 +17037,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_gl_unittests", "test_id_prefix": "ninja://ui/ozone/gl:ozone_gl_unittests/" @@ -16654,7 +17055,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" @@ -16671,7 +17073,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_x11_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_x11_unittests/" @@ -16688,7 +17091,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "pdf_unittests", "test_id_prefix": "ninja://pdf:pdf_unittests/" @@ -16705,7 +17109,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -16722,7 +17127,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ppapi_unittests", "test_id_prefix": "ninja://ppapi:ppapi_unittests/" @@ -16739,7 +17145,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "printing_unittests", "test_id_prefix": "ninja://printing:printing_unittests/" @@ -16756,7 +17163,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests", "test_id_prefix": "ninja://remoting:remoting_unittests/" @@ -16773,7 +17181,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sandbox_linux_unittests", "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" @@ -16790,7 +17199,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -16807,7 +17217,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -16824,7 +17235,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -16841,7 +17253,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_encryption_unittests", "test_id_prefix": "ninja://third_party/shell-encryption:shell_encryption_unittests/" @@ -16858,7 +17271,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -16875,7 +17289,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -16892,7 +17307,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -16909,7 +17325,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -16927,6 +17344,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 4 }, "test": "sync_integration_tests", @@ -16944,7 +17362,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -16961,7 +17380,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_chromeos_unittests", "test_id_prefix": "ninja://ui/chromeos:ui_chromeos_unittests/" @@ -16978,7 +17398,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -16995,7 +17416,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/" @@ -17012,7 +17434,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -17030,7 +17453,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "usage_time_limit_unittests", "test_id_prefix": "ninja://chrome/test:usage_time_limit_unittests/" @@ -17047,7 +17471,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -17064,7 +17489,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -17081,7 +17507,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wayland_client_perftests", "test_id_prefix": "ninja://components/exo/wayland:wayland_client_perftests/" @@ -17098,7 +17525,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wayland_client_tests", "test_id_prefix": "ninja://components/exo/wayland:wayland_client_tests/" @@ -17115,7 +17543,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wm_unittests", "test_id_prefix": "ninja://ui/wm:wm_unittests/" @@ -17132,7 +17561,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -17149,7 +17579,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -17170,7 +17601,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -17187,7 +17619,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -17204,7 +17637,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_unittests", "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", @@ -17222,7 +17656,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "app_shell_unittests", "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" @@ -17239,7 +17674,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "aura_unittests", "test_id_prefix": "ninja://ui/aura:aura_unittests/" @@ -17256,7 +17692,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -17273,7 +17710,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -17290,7 +17728,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -17307,7 +17746,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -17324,7 +17764,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -17342,7 +17783,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -17359,7 +17801,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -17376,7 +17819,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -17397,6 +17841,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 50 }, "test": "browser_tests", @@ -17417,7 +17862,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -17434,7 +17880,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -17451,7 +17898,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -17468,7 +17916,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_app_unittests", "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" @@ -17485,7 +17934,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromedriver_unittests", "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" @@ -17502,7 +17952,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -17519,7 +17970,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -17536,7 +17988,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -17553,7 +18006,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "compositor_unittests", "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" @@ -17574,6 +18028,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test": "content_browsertests", @@ -17591,7 +18046,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", "test_id_prefix": "ninja://content/test:content_unittests/" @@ -17608,7 +18064,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -17625,7 +18082,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_tests", "test_id_prefix": "ninja://components/cronet:cronet_tests/" @@ -17642,7 +18100,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_unittests", "test_id_prefix": "ninja://components/cronet:cronet_unittests/" @@ -17659,7 +18118,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -17676,7 +18136,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "dbus_unittests", "test_id_prefix": "ninja://dbus:dbus_unittests/" @@ -17693,7 +18154,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -17710,7 +18172,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -17727,7 +18190,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -17744,7 +18208,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_browsertests", "test_id_prefix": "ninja://extensions:extensions_browsertests/" @@ -17761,7 +18226,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -17778,7 +18244,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -17795,7 +18262,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -17812,7 +18280,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -17829,7 +18298,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -17846,7 +18316,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -17863,7 +18334,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -17880,7 +18352,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -17897,7 +18370,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_browsertests", "test_id_prefix": "ninja://headless:headless_browsertests/" @@ -17914,7 +18388,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_unittests", "test_id_prefix": "ninja://headless:headless_unittests/" @@ -17932,6 +18407,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 10 }, "test": "interactive_ui_tests", @@ -17949,7 +18425,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -17966,7 +18443,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -17983,7 +18461,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -18000,7 +18479,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -18017,7 +18497,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -18034,7 +18515,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -18051,7 +18533,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -18068,7 +18551,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_core_unittests", "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/" @@ -18085,7 +18569,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -18102,7 +18587,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "nacl_loader_unittests", "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" @@ -18119,7 +18605,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -18136,7 +18623,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -18153,7 +18641,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "openscreen_unittests", "test_id_prefix": "ninja://chrome/browser/media/router:openscreen_unittests/" @@ -18170,7 +18659,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" @@ -18187,7 +18677,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_x11_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_x11_unittests/" @@ -18204,7 +18695,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "pdf_unittests", "test_id_prefix": "ninja://pdf:pdf_unittests/" @@ -18221,7 +18713,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -18238,7 +18731,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ppapi_unittests", "test_id_prefix": "ninja://ppapi:ppapi_unittests/" @@ -18255,7 +18749,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "printing_unittests", "test_id_prefix": "ninja://printing:printing_unittests/" @@ -18272,7 +18767,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests", "test_id_prefix": "ninja://remoting:remoting_unittests/" @@ -18289,7 +18785,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sandbox_linux_unittests", "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" @@ -18306,7 +18803,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -18323,7 +18821,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -18340,7 +18839,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -18357,7 +18857,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -18374,7 +18875,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -18391,7 +18893,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -18408,7 +18911,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -18426,6 +18930,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 4 }, "test": "sync_integration_tests", @@ -18443,7 +18948,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -18460,7 +18966,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -18477,7 +18984,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/" @@ -18494,7 +19002,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -18511,7 +19020,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -18528,7 +19038,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -18549,7 +19060,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -18566,7 +19078,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "vr_common_unittests", "test_id_prefix": "ninja://chrome/browser/vr:vr_common_unittests/" @@ -18583,7 +19096,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wm_unittests", "test_id_prefix": "ninja://ui/wm:wm_unittests/" @@ -18600,7 +19114,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -18618,7 +19133,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "xr_browser_tests", "test_id_prefix": "ninja://chrome/test:xr_browser_tests/" @@ -18635,7 +19151,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -18659,7 +19176,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://:blink_python_tests/" }, @@ -18696,6 +19214,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://:blink_web_tests/" @@ -18733,6 +19252,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://:blink_wpt_tests/" @@ -18758,7 +19278,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_py_tests/" }, @@ -18776,7 +19297,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_replay_unittests/" }, @@ -18798,7 +19320,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://content/shell:content_shell_crash_test/" }, @@ -18820,7 +19343,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://third_party/flatbuffers:flatbuffers_unittests/" }, @@ -18842,7 +19366,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://testing:fuchsia_pytype/" }, @@ -18863,7 +19388,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://tools/grit:grit_python_unittests/" }, @@ -18900,7 +19426,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://:blink_web_tests/" }, @@ -18938,6 +19465,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test_id_prefix": "ninja://:blink_wpt_tests/" @@ -18959,7 +19487,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://mojo/public/tools:mojo_python_unittests/" }, @@ -18997,6 +19526,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 20 }, "test_id_prefix": "ninja://:blink_web_tests/" @@ -19034,6 +19564,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 10 }, "test_id_prefix": "ninja://:blink_wpt_tests/" @@ -19056,7 +19587,8 @@ "os": "Ubuntu-18.04" } ], - "idempotent": false + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:telemetry_gpu_unittests/" }, @@ -19082,6 +19614,7 @@ } ], "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 12 }, "test_id_prefix": "ninja://chrome/test:telemetry_perf_unittests/" @@ -19109,6 +19642,7 @@ } ], "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test_id_prefix": "ninja://chrome/test:telemetry_unittests/" @@ -19132,7 +19666,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://ui/views:views_perftests/" }, @@ -19169,7 +19704,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://:blink_web_tests/" }, @@ -19190,6 +19726,7 @@ "os": "Ubuntu-18.04" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 4 }, "test_id_prefix": "ninja://:webdriver_wpt_tests/" @@ -19258,7 +19795,8 @@ { "os": "Ubuntu-18.04" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "browser_tests", "test_id_prefix": "ninja://chrome/test:browser_tests/" @@ -19277,7 +19815,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -19289,7 +19828,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -19301,7 +19841,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "app_shell_unittests", "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" @@ -19313,7 +19854,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "aura_unittests", "test_id_prefix": "ninja://ui/aura:aura_unittests/" @@ -19325,7 +19867,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -19337,7 +19880,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -19349,7 +19893,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -19361,7 +19906,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -19373,7 +19919,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -19386,7 +19933,8 @@ }, "name": "webkit_unit_tests", "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -19398,7 +19946,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -19410,7 +19959,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -19423,6 +19973,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 10 }, "test": "browser_tests", @@ -19438,7 +19989,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -19450,7 +20002,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -19462,7 +20015,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -19474,7 +20028,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_app_unittests", "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" @@ -19486,7 +20041,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromedriver_unittests", "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" @@ -19498,7 +20054,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromeos_unittests", "test_id_prefix": "ninja://chromeos:chromeos_unittests/" @@ -19510,7 +20067,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -19522,7 +20080,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -19534,7 +20093,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -19546,7 +20106,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "compositor_unittests", "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" @@ -19559,6 +20120,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test": "content_browsertests", @@ -19571,7 +20133,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", "test_id_prefix": "ninja://content/test:content_unittests/" @@ -19583,7 +20146,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -19595,7 +20159,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -19607,7 +20172,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "dbus_unittests", "test_id_prefix": "ninja://dbus:dbus_unittests/" @@ -19619,7 +20185,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -19631,7 +20198,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -19643,7 +20211,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -19658,7 +20227,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_browsertests", "test_id_prefix": "ninja://extensions:extensions_browsertests/" @@ -19673,7 +20243,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -19685,7 +20256,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -19697,7 +20269,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -19709,7 +20282,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -19721,7 +20295,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -19733,7 +20308,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -19745,7 +20321,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -19757,7 +20334,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -19770,6 +20348,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -19796,6 +20375,7 @@ "revision": "version:108.0.5359.58" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -19823,6 +20403,7 @@ "revision": "version:111.0.5558.0" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -19850,6 +20431,7 @@ "revision": "version:110.0.5464.0" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -19877,6 +20459,7 @@ "revision": "version:108.0.5359.172" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -19890,7 +20473,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -19906,7 +20490,8 @@ }, "name": "lacros_chrome_browsertests", "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/" @@ -19931,7 +20516,8 @@ "location": "lacros_version_skew_tests_v108.0.5359.58", "revision": "version:108.0.5359.58" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", @@ -19957,7 +20543,8 @@ "location": "lacros_version_skew_tests_v111.0.5558.0", "revision": "version:111.0.5558.0" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", @@ -19983,7 +20570,8 @@ "location": "lacros_version_skew_tests_v110.0.5464.0", "revision": "version:110.0.5464.0" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", @@ -20009,7 +20597,8 @@ "location": "lacros_version_skew_tests_v108.0.5359.172", "revision": "version:108.0.5359.172" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", @@ -20027,6 +20616,7 @@ "name": "lacros_chrome_browsertests_run_in_series", "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "lacros_chrome_browsertests_run_in_series", @@ -20053,6 +20643,7 @@ "revision": "version:108.0.5359.58" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "lacros_chrome_browsertests_run_in_series", @@ -20080,6 +20671,7 @@ "revision": "version:111.0.5558.0" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "lacros_chrome_browsertests_run_in_series", @@ -20107,6 +20699,7 @@ "revision": "version:110.0.5464.0" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "lacros_chrome_browsertests_run_in_series", @@ -20134,6 +20727,7 @@ "revision": "version:108.0.5359.172" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 2 }, "test": "lacros_chrome_browsertests_run_in_series", @@ -20147,7 +20741,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_unittests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_unittests/" @@ -20159,7 +20754,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -20171,7 +20767,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -20183,7 +20780,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -20195,7 +20793,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -20207,7 +20806,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -20219,7 +20819,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -20231,7 +20832,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_core_unittests", "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/" @@ -20243,7 +20845,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -20255,7 +20858,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "nacl_loader_unittests", "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" @@ -20267,7 +20871,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -20279,7 +20884,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -20291,7 +20897,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ozone_unittests", "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" @@ -20303,7 +20910,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "pdf_unittests", "test_id_prefix": "ninja://pdf:pdf_unittests/" @@ -20315,7 +20923,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -20327,7 +20936,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ppapi_unittests", "test_id_prefix": "ninja://ppapi:ppapi_unittests/" @@ -20339,7 +20949,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "printing_unittests", "test_id_prefix": "ninja://printing:printing_unittests/" @@ -20351,7 +20962,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests", "test_id_prefix": "ninja://remoting:remoting_unittests/" @@ -20363,7 +20975,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sandbox_linux_unittests", "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" @@ -20375,7 +20988,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -20387,7 +21001,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -20399,7 +21014,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -20411,7 +21027,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -20423,7 +21040,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -20435,7 +21053,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -20447,7 +21066,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -20459,7 +21079,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sync_integration_tests", "test_id_prefix": "ninja://chrome/test:sync_integration_tests/" @@ -20471,7 +21092,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -20483,7 +21105,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -20495,7 +21118,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/" @@ -20507,7 +21131,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -20522,7 +21147,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -20534,7 +21160,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -20546,7 +21173,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wm_unittests", "test_id_prefix": "ninja://ui/wm:wm_unittests/" @@ -20558,7 +21186,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -20570,7 +21199,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -20592,7 +21222,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -20610,7 +21241,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -20628,7 +21260,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_unittests", "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", @@ -20647,7 +21280,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "app_shell_unittests", "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" @@ -20665,7 +21299,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -20683,7 +21318,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -20701,7 +21337,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -20719,7 +21356,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -20737,7 +21375,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -20756,7 +21395,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -20774,7 +21414,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -20792,7 +21433,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -20813,7 +21455,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -20831,7 +21474,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -20849,7 +21493,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -20867,7 +21512,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_app_unittests", "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" @@ -20885,7 +21531,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromedriver_unittests", "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" @@ -20903,7 +21550,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -20921,7 +21569,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -20939,7 +21588,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -20961,6 +21611,7 @@ "os": "Mac-12" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test": "content_browsertests", @@ -20979,7 +21630,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_nocompile_tests", "test_id_prefix": "ninja://content/test:content_nocompile_tests/" @@ -20997,7 +21649,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", "test_id_prefix": "ninja://content/test:content_unittests/" @@ -21015,7 +21668,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -21033,7 +21687,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_tests", "test_id_prefix": "ninja://components/cronet:cronet_tests/" @@ -21051,7 +21706,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_unittests", "test_id_prefix": "ninja://components/cronet:cronet_unittests/" @@ -21069,7 +21725,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -21087,7 +21744,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -21105,7 +21763,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -21123,7 +21782,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -21141,7 +21801,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_browsertests", "test_id_prefix": "ninja://extensions:extensions_browsertests/" @@ -21159,7 +21820,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -21177,7 +21839,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -21195,7 +21858,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -21213,7 +21877,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -21231,7 +21896,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -21249,7 +21915,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -21267,7 +21934,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -21285,7 +21953,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -21303,7 +21972,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_browsertests", "test_id_prefix": "ninja://headless:headless_browsertests/" @@ -21321,7 +21991,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_unittests", "test_id_prefix": "ninja://headless:headless_unittests/" @@ -21343,6 +22014,7 @@ "os": "Mac-12" } ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -21361,7 +22033,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -21379,7 +22052,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -21397,7 +22071,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -21415,7 +22090,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -21433,7 +22109,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -21451,7 +22128,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -21469,7 +22147,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -21487,7 +22166,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -21505,7 +22185,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "nacl_loader_unittests", "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" @@ -21523,7 +22204,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -21541,7 +22223,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -21559,7 +22242,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "openscreen_unittests", "test_id_prefix": "ninja://chrome/browser/media/router:openscreen_unittests/" @@ -21577,7 +22261,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "pdf_unittests", "test_id_prefix": "ninja://pdf:pdf_unittests/" @@ -21595,7 +22280,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -21613,7 +22299,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "power_sampler_unittests", "test_id_prefix": "ninja://tools/mac/power:power_sampler_unittests/" @@ -21631,7 +22318,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ppapi_unittests", "test_id_prefix": "ninja://ppapi:ppapi_unittests/" @@ -21649,7 +22337,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "printing_unittests", "test_id_prefix": "ninja://printing:printing_unittests/" @@ -21667,7 +22356,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests", "test_id_prefix": "ninja://remoting:remoting_unittests/" @@ -21685,7 +22375,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sandbox_unittests", "test_id_prefix": "ninja://sandbox:sandbox_unittests/" @@ -21703,7 +22394,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -21721,7 +22413,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -21739,7 +22432,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -21757,7 +22451,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -21775,7 +22470,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -21793,7 +22489,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -21811,7 +22508,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -21832,7 +22530,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sync_integration_tests", "test_id_prefix": "ninja://chrome/test:sync_integration_tests/" @@ -21850,7 +22549,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -21868,7 +22568,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -21886,7 +22587,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/" @@ -21904,7 +22606,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "updater_tests", "test_id_prefix": "ninja://chrome/updater:updater_tests/" @@ -21922,7 +22625,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -21940,7 +22644,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -21958,7 +22663,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -21976,7 +22682,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -21995,7 +22702,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "xr_browser_tests", "test_id_prefix": "ninja://chrome/test:xr_browser_tests/" @@ -22013,7 +22721,8 @@ "cpu": "x86-64", "os": "Mac-12" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -22029,7 +22738,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "absl_hardening_tests", "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" @@ -22041,7 +22751,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "accessibility_unittests", "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" @@ -22053,7 +22764,8 @@ "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "angle_unittests", "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", @@ -22066,7 +22778,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "app_shell_unittests", "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" @@ -22078,7 +22791,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "aura_unittests", "test_id_prefix": "ninja://ui/aura:aura_unittests/" @@ -22090,7 +22804,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/" @@ -22102,7 +22817,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_common_unittests", "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" @@ -22114,7 +22830,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_fuzzer_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" @@ -22126,7 +22843,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_heap_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" @@ -22138,7 +22856,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_platform_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" @@ -22151,7 +22870,8 @@ }, "name": "webkit_unit_tests", "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -22163,7 +22883,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_crypto_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" @@ -22175,7 +22896,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "boringssl_ssl_tests", "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" @@ -22188,6 +22910,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 10 }, "test": "browser_tests", @@ -22203,7 +22926,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "capture_unittests", "test_id_prefix": "ninja://media/capture:capture_unittests/" @@ -22215,7 +22939,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cast_unittests", "test_id_prefix": "ninja://media/cast:cast_unittests/" @@ -22227,7 +22952,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -22239,7 +22965,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_app_unittests", "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" @@ -22251,7 +22978,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_cleaner_unittests", "test_id_prefix": "ninja://chrome/chrome_cleaner:chrome_cleaner_unittests/" @@ -22263,7 +22991,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chrome_elf_unittests", "test_id_prefix": "ninja://chrome/chrome_elf:chrome_elf_unittests/" @@ -22275,7 +23004,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "chromedriver_unittests", "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" @@ -22287,7 +23017,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "color_unittests", "test_id_prefix": "ninja://ui/color:color_unittests/" @@ -22299,7 +23030,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -22311,7 +23043,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -22323,7 +23056,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "compositor_unittests", "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" @@ -22336,6 +23070,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 8 }, "test": "content_browsertests", @@ -22348,7 +23083,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "content_unittests", "test_id_prefix": "ninja://content/test:content_unittests/" @@ -22360,7 +23096,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "courgette_unittests", "test_id_prefix": "ninja://courgette:courgette_unittests/" @@ -22372,7 +23109,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crashpad_tests", "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" @@ -22384,7 +23122,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_tests", "test_id_prefix": "ninja://components/cronet:cronet_tests/" @@ -22396,7 +23135,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "cronet_unittests", "test_id_prefix": "ninja://components/cronet:cronet_unittests/" @@ -22408,7 +23148,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "crypto_unittests", "test_id_prefix": "ninja://crypto:crypto_unittests/" @@ -22420,7 +23161,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "delayloads_unittests", "test_id_prefix": "ninja://chrome/test:delayloads_unittests/" @@ -22432,7 +23174,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "device_unittests", "test_id_prefix": "ninja://device:device_unittests/" @@ -22444,7 +23187,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "display_unittests", "test_id_prefix": "ninja://ui/display:display_unittests/" @@ -22456,7 +23200,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "elevation_service_unittests", "test_id_prefix": "ninja://chrome/elevation_service:elevation_service_unittests/" @@ -22468,7 +23213,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "events_unittests", "test_id_prefix": "ninja://ui/events:events_unittests/" @@ -22480,7 +23226,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_browsertests", "test_id_prefix": "ninja://extensions:extensions_browsertests/" @@ -22492,7 +23239,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "extensions_unittests", "test_id_prefix": "ninja://extensions:extensions_unittests/" @@ -22504,7 +23252,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "filesystem_service_unittests", "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" @@ -22516,7 +23265,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcm_unit_tests", "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" @@ -22528,7 +23278,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gcp_unittests", "test_id_prefix": "ninja://chrome/credential_provider/test:gcp_unittests/" @@ -22540,7 +23291,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gfx_unittests", "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" @@ -22552,7 +23304,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gin_unittests", "test_id_prefix": "ninja://gin:gin_unittests/" @@ -22564,7 +23317,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "google_apis_unittests", "test_id_prefix": "ninja://google_apis:google_apis_unittests/" @@ -22576,7 +23330,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gpu_unittests", "test_id_prefix": "ninja://gpu:gpu_unittests/" @@ -22588,7 +23343,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "gwp_asan_unittests", "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" @@ -22600,7 +23356,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_browsertests", "test_id_prefix": "ninja://headless:headless_browsertests/" @@ -22612,7 +23369,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "headless_unittests", "test_id_prefix": "ninja://headless:headless_unittests/" @@ -22624,7 +23382,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "install_static_unittests", "test_id_prefix": "ninja://chrome/install_static:install_static_unittests/" @@ -22641,7 +23400,8 @@ { "integrity": "high" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "installer_util_unittests", "test_id_prefix": "ninja://chrome/installer/util:installer_util_unittests/" @@ -22654,6 +23414,7 @@ }, "swarming": { "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", "shards": 3 }, "test": "interactive_ui_tests", @@ -22666,7 +23427,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ipc_tests", "test_id_prefix": "ninja://ipc:ipc_tests/" @@ -22678,7 +23440,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "latency_unittests", "test_id_prefix": "ninja://ui/latency:latency_unittests/" @@ -22690,7 +23453,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "libjingle_xmpp_unittests", "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" @@ -22702,7 +23466,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "liburlpattern_unittests", "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" @@ -22714,7 +23479,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "media_unittests", "test_id_prefix": "ninja://media:media_unittests/" @@ -22726,7 +23492,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "message_center_unittests", "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" @@ -22738,7 +23505,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "midi_unittests", "test_id_prefix": "ninja://media/midi:midi_unittests/" @@ -22750,7 +23518,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_core_unittests", "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/" @@ -22762,7 +23531,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "mojo_unittests", "test_id_prefix": "ninja://mojo:mojo_unittests/" @@ -22774,7 +23544,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "nacl_loader_unittests", "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" @@ -22786,7 +23557,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" @@ -22798,7 +23570,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -22810,7 +23583,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "notification_helper_unittests", "test_id_prefix": "ninja://chrome/notification_helper:notification_helper_unittests/" @@ -22822,7 +23596,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "pdf_unittests", "test_id_prefix": "ninja://pdf:pdf_unittests/" @@ -22834,7 +23609,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "perfetto_unittests", "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" @@ -22846,7 +23622,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ppapi_unittests", "test_id_prefix": "ninja://ppapi:ppapi_unittests/" @@ -22858,7 +23635,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "printing_unittests", "test_id_prefix": "ninja://printing:printing_unittests/" @@ -22870,7 +23648,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "remoting_unittests", "test_id_prefix": "ninja://remoting:remoting_unittests/" @@ -22887,7 +23666,8 @@ { "integrity": "high" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sbox_integration_tests", "test_id_prefix": "ninja://sandbox/win:sbox_integration_tests/" @@ -22899,7 +23679,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sbox_unittests", "test_id_prefix": "ninja://sandbox/win:sbox_unittests/" @@ -22911,7 +23692,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sbox_validation_tests", "test_id_prefix": "ninja://sandbox/win:sbox_validation_tests/" @@ -22923,7 +23705,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "service_manager_unittests", "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" @@ -22935,7 +23718,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "services_unittests", "test_id_prefix": "ninja://services:services_unittests/" @@ -22952,7 +23736,8 @@ { "integrity": "high" } - ] + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "setup_unittests", "test_id_prefix": "ninja://chrome/installer/setup:setup_unittests/" @@ -22964,7 +23749,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "shell_dialogs_unittests", "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" @@ -22976,7 +23762,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "skia_unittests", "test_id_prefix": "ninja://skia:skia_unittests/" @@ -22988,7 +23775,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "snapshot_unittests", "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" @@ -23000,7 +23788,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sql_unittests", "test_id_prefix": "ninja://sql:sql_unittests/" @@ -23012,7 +23801,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "storage_unittests", "test_id_prefix": "ninja://storage:storage_unittests/" @@ -23024,7 +23814,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "sync_integration_tests", "test_id_prefix": "ninja://chrome/test:sync_integration_tests/" @@ -23036,7 +23827,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_base_unittests", "test_id_prefix": "ninja://ui/base:ui_base_unittests/" @@ -23048,7 +23840,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "ui_touch_selection_unittests", "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" @@ -23060,7 +23853,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/" @@ -23072,7 +23866,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "updater_tests", "test_id_prefix": "ninja://chrome/updater:updater_tests/" @@ -23084,7 +23879,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "updater_tests_system", "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" @@ -23096,7 +23892,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" @@ -23108,7 +23905,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "views_unittests", "test_id_prefix": "ninja://ui/views:views_unittests/" @@ -23120,7 +23918,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "viz_unittests", "test_id_prefix": "ninja://components/viz:viz_unittests/" @@ -23132,7 +23931,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "vr_common_unittests", "test_id_prefix": "ninja://chrome/browser/vr:vr_common_unittests/" @@ -23144,7 +23944,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wm_unittests", "test_id_prefix": "ninja://ui/wm:wm_unittests/" @@ -23156,7 +23957,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "wtf_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" @@ -23168,7 +23970,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zlib_unittests", "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" @@ -23180,7 +23983,8 @@ "script": "//testing/merge_scripts/standard_gtest_merge.py" }, "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "zucchini_unittests", "test_id_prefix": "ninja://components/zucchini:zucchini_unittests/"
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json index 791b6760..f930ba536 100644 --- a/testing/buildbot/internal.chromeos.fyi.json +++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1141,7 +1141,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R111-15326.0.0", + "cros_img": "octopus-release/R111-15327.0.0", "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1153,7 +1153,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R111-15320.0.0", + "cros_img": "octopus-release/R111-15324.0.0", "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1189,7 +1189,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R111-15326.0.0", + "cros_img": "octopus-release/R111-15327.0.0", "name": "ozone_unittests OCTOPUS_RELEASE_LKGM", "swarming": {}, "test": "ozone_unittests", @@ -1200,7 +1200,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R111-15320.0.0", + "cros_img": "octopus-release/R111-15324.0.0", "name": "ozone_unittests OCTOPUS_RELEASE_DEV", "swarming": {}, "test": "ozone_unittests", @@ -1240,7 +1240,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15326.0.0", + "cros_img": "hana-release/R111-15327.0.0", "name": "lacros_all_tast_tests HANA_RELEASE_LKGM", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1252,7 +1252,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15320.0.0", + "cros_img": "hana-release/R111-15324.0.0", "name": "lacros_all_tast_tests HANA_RELEASE_DEV", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1300,7 +1300,7 @@ { "args": [], "cros_board": "strongbad", - "cros_img": "strongbad-release/R111-15320.0.0", + "cros_img": "strongbad-release/R111-15324.0.0", "name": "lacros_all_tast_tests strongbad_RELEASE_DEV", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1336,7 +1336,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15326.0.0", + "cros_img": "hana-release/R111-15327.0.0", "name": "ozone_unittests HANA_RELEASE_LKGM", "swarming": {}, "test": "ozone_unittests", @@ -1347,7 +1347,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15320.0.0", + "cros_img": "hana-release/R111-15324.0.0", "name": "ozone_unittests HANA_RELEASE_DEV", "swarming": {}, "test": "ozone_unittests", @@ -1391,7 +1391,7 @@ { "args": [], "cros_board": "strongbad", - "cros_img": "strongbad-release/R111-15320.0.0", + "cros_img": "strongbad-release/R111-15324.0.0", "name": "ozone_unittests strongbad_RELEASE_DEV", "swarming": {}, "test": "ozone_unittests", @@ -1424,7 +1424,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15326.0.0", + "cros_img": "hana-release/R111-15327.0.0", "name": "viz_unittests HANA_RELEASE_LKGM", "swarming": {}, "test": "viz_unittests", @@ -1435,7 +1435,7 @@ { "args": [], "cros_board": "hana", - "cros_img": "hana-release/R111-15320.0.0", + "cros_img": "hana-release/R111-15324.0.0", "name": "viz_unittests HANA_RELEASE_DEV", "swarming": {}, "test": "viz_unittests", @@ -1479,7 +1479,7 @@ { "args": [], "cros_board": "strongbad", - "cros_img": "strongbad-release/R111-15320.0.0", + "cros_img": "strongbad-release/R111-15324.0.0", "name": "viz_unittests strongbad_RELEASE_DEV", "swarming": {}, "test": "viz_unittests",
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index ad34029..7d12f597f 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -218,6 +218,29 @@ ] }, }, + '13-x64-emulator': { + '$mixin_append': { + 'args': [ + '--avd-config=../../tools/android/avd/proto/generic_android33.textpb', + ], + }, + 'swarming': { + # soft affinity so that bots with caches will be picked first + 'optional_dimensions': { + '60': [ + { + 'caches': 'generic_android33', + } + ], + }, + 'named_caches': [ + { + 'name': 'generic_android33', + 'path': '.android_emulator/generic_android33', + }, + ] + }, + }, 'android_r': { 'swarming': { 'dimensions': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index f79349cb..ac7678eb 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1303,32 +1303,6 @@ }, }, }, - # TODO(crbug/1239300): Remove when experiment is done. - 'chrome_public_persistent_shell_test_apk': { - 'remove_from': [ - 'android-pie-arm64-rel', # crbug/1239300. Experiment is done on this bot. - ], - 'modifications': { - 'android-nougat-x86-rel': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.chrome_public_test_apk.filter', - ], - 'swarming': { - 'shards': 25, - }, - }, - }, - }, - # TODO(crbug/1239300): Remove when experiment is done. - 'chrome_public_persistent_shell_unit_test_apk': { - 'modifications': { - 'android-nougat-x86-rel': { - 'swarming': { - 'shards': 4, - }, - }, - }, - }, 'chrome_public_smoke_test': { 'remove_from': [ 'android-code-coverage-native', # Does not generate profraw data. @@ -1924,25 +1898,6 @@ }, }, }, - # TODO(crbug/1239300): Remove when experiment is done. - 'content_browsertests_persistent_shell': { - 'modifications': { - 'android-nougat-x86-rel': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.content_browsertests.filter', - ], - 'swarming': { - 'shards': 25, - 'dimension_sets': [ - { - # copying android-nougat-x86-rel - 'cores': '8', - }, - ], - }, - }, - }, - }, 'content_shell_crash_test': { 'remove_from': [ 'android-nougat-x86-rel', # crbug.com/1084353
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index d832c4e1..2ee3ae0f 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -484,49 +484,6 @@ }, }, - # TODO(crbug/1239300): Remove when persistent_shell experiment is over. - 'chrome_persistent_shell_tests': { - 'chrome_public_persistent_shell_test_apk': { - 'args': [ - '--use-persistent-shell', - ], - 'ci_only': True, - 'test': 'chrome_public_test_apk', - 'experiment_percentage': 100, - 'swarming': { - 'shards': 19, - }, - 'mixins': [ - 'skia_gold_test', - ], - }, - 'chrome_public_persistent_shell_unit_test_apk': { - 'args': [ - '--use-persistent-shell', - ], - 'ci_only': True, - 'test': 'chrome_public_unit_test_apk', - 'experiment_percentage': 100, - 'swarming': { - 'shards': 2, - }, - 'mixins': [ - 'skia_gold_test', - ], - }, - 'content_browsertests_persistent_shell': { - 'args': [ - '--use-persistent-shell', - ], - 'ci_only': True, - 'test': 'content_browsertests', - 'experiment_percentage': 100, - 'swarming': { - 'shards': 20, - }, - }, - }, - 'chrome_public_tests': { 'chrome_public_test_apk': { 'swarming': { @@ -5619,7 +5576,6 @@ 'android_smoke_tests', 'android_specific_chromium_gtests', # Already includes gl_gtests. 'android_wpr_record_replay_tests', - 'chrome_persistent_shell_tests', 'chromium_gtests', 'chromium_gtests_for_devices_with_graphical_output', 'linux_flavor_specific_chromium_gtests', @@ -6523,11 +6479,7 @@ 'webview_ui_instrumentation_tests': {}, }, - 'android_12_emulator_fyi_gtests': { - 'oop_network_service_tests': {}, - }, - - 'android_12_emulator_gtests': { + 'android_12_13_emulator_gtests': { 'android_emulator_specific_chrome_public_tests': {}, 'android_monochrome_smoke_tests': {}, 'android_smoke_tests': {}, @@ -6545,6 +6497,10 @@ 'webview_ui_instrumentation_tests': {}, }, + 'android_12_emulator_fyi_gtests': { + 'oop_network_service_tests': {}, + }, + 'android_12l_emulator_gtests': { 'android_emulator_specific_chrome_public_tests': {}, 'android_monochrome_smoke_tests': {},
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index f73d95c..0dc33c8 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -470,8 +470,8 @@ 'CROS_DEDEDE_RELEASE_LKGM': { 'skylab': { 'cros_board': 'dedede', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'dedede-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'dedede-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'DEDEDE_RELEASE_LKGM', @@ -479,8 +479,8 @@ 'CROS_DEDEDE_RELEASE_DEV': { 'skylab': { 'cros_board': 'dedede', - 'cros_chrome_version': '111.0.5544.0', - 'cros_img': 'dedede-release/R111-15320.0.0', + 'cros_chrome_version': '111.0.5550.0', + 'cros_img': 'dedede-release/R111-15324.0.0', }, 'enabled': True, 'identifier': 'DEDEDE_RELEASE_DEV', @@ -506,8 +506,8 @@ 'CROS_EVE_RELEASE_LKGM': { 'skylab': { 'cros_board': 'eve', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'eve-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'eve-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'EVE_RELEASE_LKGM', @@ -552,8 +552,8 @@ 'CROS_HANA_RELEASE_LKGM': { 'skylab': { 'cros_board': 'hana', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'hana-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'hana-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'HANA_RELEASE_LKGM', @@ -561,8 +561,8 @@ 'CROS_HANA_RELEASE_DEV': { 'skylab': { 'cros_board': 'hana', - 'cros_chrome_version': '111.0.5544.0', - 'cros_img': 'hana-release/R111-15320.0.0', + 'cros_chrome_version': '111.0.5550.0', + 'cros_img': 'hana-release/R111-15324.0.0', }, 'enabled': True, 'identifier': 'HANA_RELEASE_DEV', @@ -588,8 +588,8 @@ 'CROS_HEROBRINE_RELEASE_LKGM': { 'skylab': { 'cros_board': 'herobrine', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'herobrine-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'herobrine-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'HEROBRINE_RELEASE_LKGM', @@ -597,8 +597,8 @@ 'CROS_JACUZZI_RELEASE_LKGM': { 'skylab': { 'cros_board': 'jacuzzi', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'jacuzzi-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'jacuzzi-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'JACUZZI_RELEASE_LKGM', @@ -606,8 +606,8 @@ 'CROS_JACUZZI_RELEASE_DEV': { 'skylab': { 'cros_board': 'jacuzzi', - 'cros_chrome_version': '111.0.5544.0', - 'cros_img': 'jacuzzi-release/R111-15320.0.0', + 'cros_chrome_version': '111.0.5550.0', + 'cros_img': 'jacuzzi-release/R111-15324.0.0', }, 'enabled': True, 'identifier': 'JACUZZI_RELEASE_DEV', @@ -673,8 +673,8 @@ 'CROS_OCTOPUS_RELEASE_LKGM': { 'skylab': { 'cros_board': 'octopus', - 'cros_chrome_version': '111.0.5550.0', - 'cros_img': 'octopus-release/R111-15326.0.0', + 'cros_chrome_version': '111.0.5557.0', + 'cros_img': 'octopus-release/R111-15327.0.0', }, 'enabled': True, 'identifier': 'OCTOPUS_RELEASE_LKGM', @@ -682,8 +682,8 @@ 'CROS_OCTOPUS_RELEASE_DEV': { 'skylab': { 'cros_board': 'octopus', - 'cros_chrome_version': '111.0.5544.0', - 'cros_img': 'octopus-release/R111-15320.0.0', + 'cros_chrome_version': '111.0.5550.0', + 'cros_img': 'octopus-release/R111-15324.0.0', }, 'enabled': True, 'identifier': 'OCTOPUS_RELEASE_DEV', @@ -718,8 +718,8 @@ 'CROS_STRONGBAD_RELEASE_DEV': { 'skylab': { 'cros_board': 'strongbad', - 'cros_chrome_version': '111.0.5544.0', - 'cros_img': 'strongbad-release/R111-15320.0.0', + 'cros_chrome_version': '111.0.5550.0', + 'cros_img': 'strongbad-release/R111-15324.0.0', }, 'enabled': True, 'identifier': 'strongbad_RELEASE_DEV',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index da1fe5a..b73c9bf 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -670,6 +670,9 @@ }, ], }, + 'additional_compile_targets': [ + 'monochrome_static_initializers', + ], 'test_suites': { 'gtest_tests': 'android_10_rel_gtests', }, @@ -701,7 +704,7 @@ ], 'os_type': 'android', 'test_suites': { - 'gtest_tests': 'android_12_emulator_gtests', + 'gtest_tests': 'android_12_13_emulator_gtests', } }, 'android-12l-x64-dbg-tests': { @@ -717,6 +720,19 @@ 'gtest_tests': 'android_12l_emulator_gtests', } }, + 'android-13-x64-rel': { + 'mixins': [ + '13-x64-emulator', + 'emulator-8-cores', + 'has_native_resultdb_integration', + 'linux-bionic', + 'x86-64', + ], + 'os_type': 'android', + 'test_suites': { + 'gtest_tests': 'android_12_13_emulator_gtests', + } + }, 'android-arm64-proguard-rel': { 'additional_compile_targets': [ 'all', @@ -982,9 +998,6 @@ 'pie_fleet', 'walleye', ], - 'additional_compile_targets': [ - 'monochrome_static_initializers', - ], 'args': [ '--use-persistent-shell', ], @@ -2054,7 +2067,7 @@ }, { 'name': 'chromium.coverage', - 'mixins': [], + 'mixins': ['chromium-tester-service-account'], 'machines': { 'android-code-coverage': { 'mixins': [
diff --git a/testing/test.gni b/testing/test.gni index b9cdf13..854c5112 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -579,7 +579,6 @@ [ "excluded_files", "excluded_dirs", - "excluded_paths", ]) package_name = _output_name deps = _test_component_targets @@ -587,17 +586,11 @@ if (defined(invoker.fuchsia_package_deps)) { deps += invoker.fuchsia_package_deps } - if (!defined(excluded_paths)) { - excluded_paths = [] + if (!defined(excluded_dirs)) { + excluded_dirs = [] } - excluded_paths += [ - "${devtools_root_location}/*", - "*.git/*", - "*.svn/*", - "*.hg/*", - ] if (devtools_root_location != "") { - excluded_paths += [ "${devtools_root_location}/*" ] + excluded_dirs += [ devtools_root_location ] } }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 13f705a..1c828a7 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1,4 +1,19 @@ { + "AboveNormalCompositingBrowserWin": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AboveNormalCompositingBrowserWin" + ] + } + ] + } + ], "AccessibilityPageZoom": [ { "platforms": [ @@ -602,6 +617,22 @@ ] } ], + "ArcHostVpn": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ArcHostVpn" + ] + } + ] + } + ], "ArcLazyWebViewInit": [ { "platforms": [ @@ -1689,7 +1720,6 @@ { "name": "Enabled", "params": { - "TimeToLiveInBackForwardCacheInSeconds": "180", "allowed_websites": "", "cache_size": "6", "check_eligibility_after_pagehide": "true", @@ -1720,7 +1750,6 @@ { "name": "Enabled", "params": { - "TimeToLiveInBackForwardCacheInSeconds": "180", "all_extensions_allowed": "true", "allowed_websites": "", "cache_size": "6", @@ -2538,12 +2567,14 @@ ], "experiments": [ { - "name": "Enabled_20220824", + "name": "Enabled", "params": { - "allow_list": "alhngdkjgnedakdlnamimgfihgkmenbh" + "allow_list": "alhngdkjgnedakdlnamimgfihgkmenbh,gnddkmpjjjcimefninepfmmddpgaaado" }, "enable_features": [ - "ChromeAppsDeprecation", + "ChromeAppsDeprecation" + ], + "disable_features": [ "KeepForceInstalledPreinstalledApps" ] } @@ -2892,6 +2923,21 @@ ] } ], + "CloudApAuth": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "CloudApAuth" + ] + } + ] + } + ], "Collections": [ { "platforms": [ @@ -4098,6 +4144,21 @@ ] } ], + "DestroyProfileOnBrowserClose": [ + { + "platforms": [ + "chromeos_lacros" + ], + "experiments": [ + { + "name": "DestroyProfileOnBrowserClose", + "enable_features": [ + "DestroyProfileOnBrowserClose" + ] + } + ] + } + ], "DestroySystemProfiles": [ { "platforms": [ @@ -4391,28 +4452,6 @@ ] } ], - "DocumentEventNodePathCaching": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "chromeos_lacros", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "DocumentEventNodePathCaching" - ] - } - ] - } - ], "DownloadLater": [ { "platforms": [ @@ -6435,6 +6474,31 @@ ] } ], + "JourneysContentVisibility": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled_20230123", + "params": { + "content_visibility_threshold": "0", + "supported_locales": "en-US,en,en-AU,en-CA,en-GB" + }, + "enable_features": [ + "HistoryClustersOnDeviceClustering", + "PageVisibilityPageContentAnnotations" + ] + } + ] + } + ], "JourneysNonSupportedLocales": [ { "platforms": [ @@ -6717,6 +6781,28 @@ ] } ], + "LayoutNGNoCopyBack": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "LayoutNGNoCopyBack" + ] + } + ] + } + ], "LeakSkiaEventTracerAtExit": [ { "platforms": [ @@ -6954,21 +7040,6 @@ ] } ], - "MediaFoundationD3D11VideoCapture": [ - { - "platforms": [ - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "MediaFoundationD3D11VideoCapture" - ] - } - ] - } - ], "MediaFoundationVP9Encoding": [ { "platforms": [ @@ -10343,6 +10414,41 @@ ] } ], + "SequentialPrerendering": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "Prerender2SequentialPrerendering" + ] + } + ] + } + ], + "ServerBasedTranscriptionForScreencast": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "InternalServerSideSpeechRecognition" + ] + } + ] + } + ], "ServiceWorkerSkipIgnorableFetchHandler": [ { "platforms": [ @@ -12376,38 +12482,6 @@ ] } ], - "V8ScriptAblation": [ - { - "platforms": [ - "android", - "chromeos", - "chromeos_lacros", - "fuchsia", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Control", - "disable_features": [ - "V8ScriptAblation", - "V8SlowHistogramsScriptAblation" - ] - }, - { - "name": "DelayOnce50ms", - "params": { - "V8ScriptDelayOnceMs": "50" - }, - "enable_features": [ - "V8ScriptAblation", - "V8SlowHistogramsScriptAblation" - ] - } - ] - } - ], "V8SlowHistograms": [ { "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore index d2d1b43..24c302f3 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -137,6 +137,7 @@ /javax_inject/lib/ /jdk/current /jdk/extras/java_8 +/jdk11/current /js_code_coverage/*.tar.gz /js_code_coverage/node_modules /jsr-305/src
diff --git a/third_party/android_build_tools/lint/rebuild_baselines.py b/third_party/android_build_tools/lint/rebuild_baselines.py index 56cf2dc..9b7f6b8 100755 --- a/third_party/android_build_tools/lint/rebuild_baselines.py +++ b/third_party/android_build_tools/lint/rebuild_baselines.py
@@ -186,14 +186,12 @@ verbose=args.verbose, built_targets=built_targets) - logging.info('Adding new lint-baseline.xml files to git.') + logging.info('Cleaning up new lint-baseline.xml files.') for git_root, repo_path in repo_file_paths: path = git_root / repo_path if path.name == 'lint-baseline.xml': + logging.info(f'> Removing redundant LintError: {path}') _remove_redundant_lint_error(path) - # Since we are passing -C to git, the relative path is needed - logging.info(f'> Adding to git: {repo_path}') - subprocess.run(['git', '-C', str(git_root), 'add', repo_path]) if __name__ == '__main__':
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn index 2e7b0f6..108b79f 100644 --- a/third_party/blink/common/BUILD.gn +++ b/third_party/blink/common/BUILD.gn
@@ -494,5 +494,6 @@ "//third_party/blink/public/common:storage_key_proto_converter", "//third_party/libprotobuf-mutator", ] + seed_corpus = "//third_party/blink/common/storage_key/storage_key_corpus" } }
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 2c9f3cd..1b32496c 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -723,11 +723,16 @@ "DiscardCodeCacheAfterFirstUse", base::FEATURE_DISABLED_BY_DEFAULT); +// When enabled, code cache is produced asynchronously from the script execution +// (https://crbug.com/1260908). BASE_FEATURE(kCacheCodeOnIdle, "CacheCodeOnIdle", base::FEATURE_DISABLED_BY_DEFAULT); const base::FeatureParam<int> kCacheCodeOnIdleDelayParam{&kCacheCodeOnIdle, "delay-in-ms", 0}; +// Apply CacheCodeOnIdle only for service workers (https://crbug.com/1410082). +const base::FeatureParam<bool> kCacheCodeOnIdleDelayServiceWorkerOnlyParam{ + &kCacheCodeOnIdle, "service-worker-only", false}; // Make all pending 'display: auto' web fonts enter the swap or failure period // immediately before reaching the LCP time limit (~2500ms), so that web fonts @@ -1562,10 +1567,6 @@ "ThreadedBodyLoader", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kDocumentEventNodePathCaching, - "DocumentEventNodePathCaching", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kNewBaseUrlInheritanceBehavior, "NewBaseUrlInheritanceBehavior", base::FEATURE_DISABLED_BY_DEFAULT); @@ -1584,9 +1585,6 @@ switches::kDisableNewBaseUrlInheritanceBehavior); } -const base::FeatureParam<int> kDocumentMaxEventNodePathCachedEntries{ - &kDocumentEventNodePathCaching, "max-cache-entries", 10}; - BASE_FEATURE( kPostMessageFirstPartyToThirdPartyDifferentBucketSameOriginBlocked, "PostMessageFirstPartyToThirdPartyDifferentBucketSameOriginBlocked",
diff --git a/third_party/blink/common/origin_trials/trial_token.cc b/third_party/blink/common/origin_trials/trial_token.cc index 7227fda2..d84ef7f 100644 --- a/third_party/blink/common/origin_trials/trial_token.cc +++ b/third_party/blink/common/origin_trials/trial_token.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "third_party/blink/public/common/origin_trials/trial_token.h" +#include <memory> #include "base/base64.h" #include "base/big_endian.h" @@ -311,10 +312,13 @@ const std::string& feature_name, base::Time expiry_time, bool is_third_party, - UsageRestriction usage_restriction) { - return base::WrapUnique(new TrialToken(origin, match_subdomains, feature_name, - expiry_time, is_third_party, - usage_restriction)); + UsageRestriction usage_restriction, + const std::string& signature) { + std::unique_ptr<TrialToken> token = base::WrapUnique( + new TrialToken(origin, match_subdomains, feature_name, expiry_time, + is_third_party, usage_restriction)); + token->signature_ = signature; + return token; } } // namespace blink
diff --git a/third_party/blink/common/storage_key/storage_key.cc b/third_party/blink/common/storage_key/storage_key.cc index fc3eaf30..919663b 100644 --- a/third_party/blink/common/storage_key/storage_key.cc +++ b/third_party/blink/common/storage_key/storage_key.cc
@@ -142,16 +142,16 @@ return absl::nullopt; ancestor_chain_bit = static_cast<blink::mojom::AncestorChainBit>(raw_bit); - // In addition to checking for opaque-ness, if the AncestorChainBit is - // marked as kSameSite, check to make sure that the origin is not - // same-site with the top-level site (i.e.: A first-party StorageKey). - // This is important because we specifically do not serialize the - // top-level site portion of a 1p StorageKey for backwards compatibility - // reasons, meaning that such an input is malformed. + // In addition to checking for opaque-ness, the AncestorChainBit must be + // marked as kCrossSite as (1) this is an invariant when `key_origin` + // doesn't match `key_top_level_site` and (2) otherwise we specifically do + // not serialize the top-level site portion of a 1p StorageKey for + // backwards compatibility reasons, meaning that such an input is + // malformed. if (key_origin.opaque() || key_top_level_site.opaque() || - (ancestor_chain_bit == blink::mojom::AncestorChainBit::kSameSite && - key_top_level_site == net::SchemefulSite(key_origin))) + ancestor_chain_bit == blink::mojom::AncestorChainBit::kSameSite) { return absl::nullopt; + } return StorageKey(key_origin, key_top_level_site, nullptr, ancestor_chain_bit); @@ -199,7 +199,7 @@ if (!base::StringToUint64(low_digits, &nonce_low)) return absl::nullopt; - nonce = base::UnguessableToken::Deserialize2(nonce_high, nonce_low); + nonce = base::UnguessableToken::Deserialize(nonce_high, nonce_low); if (!nonce.has_value()) { return absl::nullopt; @@ -255,7 +255,7 @@ } const absl::optional<base::UnguessableToken> site_nonce = - base::UnguessableToken::Deserialize2(nonce_high, nonce_low); + base::UnguessableToken::Deserialize(nonce_high, nonce_low); // Make sure we found the final separator, it's valid, that it's the // correct attribute. @@ -351,18 +351,48 @@ StorageKey StorageKey::CreateFromOriginAndIsolationInfo( const url::Origin& origin, const net::IsolationInfo& isolation_info) { - return CreateWithOptionalNonce( - origin, net::SchemefulSite(isolation_info.top_frame_origin().value()), - base::OptionalToPtr(isolation_info.nonce()), - isolation_info.site_for_cookies().IsNull() - ? blink::mojom::AncestorChainBit::kCrossSite - : blink::mojom::AncestorChainBit::kSameSite); + blink::mojom::AncestorChainBit ancestor_chain_bit = + blink::mojom::AncestorChainBit::kSameSite; + net::SchemefulSite top_level_site = + net::SchemefulSite(isolation_info.top_frame_origin().value()); + + if (isolation_info.nonce()) { + // If the nonce is set we have to update the top level site to match origin + // as that's an invariant. + top_level_site = net::SchemefulSite(origin); + } else if (!top_level_site.opaque() && + (net::SchemefulSite(origin) != top_level_site || + isolation_info.site_for_cookies().IsNull())) { + // If the top_level_site is opaque the ancestor chain bit will be SameSite. + // Otherwise if the top level site doesn't match the new origin or the + // site for cookies is empty it must be CrossSite. + ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite; + } + return CreateWithOptionalNonce(origin, top_level_site, + base::OptionalToPtr(isolation_info.nonce()), + ancestor_chain_bit); } StorageKey StorageKey::WithOrigin(const url::Origin& origin) const { - return CreateWithOptionalNonce(origin, top_level_site_, - base::OptionalToPtr(nonce_), - ancestor_chain_bit_); + blink::mojom::AncestorChainBit ancestor_chain_bit = ancestor_chain_bit_; + net::SchemefulSite top_level_site = top_level_site_; + + if (nonce_) { + // If the nonce is set we have to update the top level site to match origin + // as that's an invariant. + top_level_site = net::SchemefulSite(origin); + } else if (!top_level_site_.opaque() && + ancestor_chain_bit_ != + blink::mojom::AncestorChainBit::kCrossSite && + net::SchemefulSite(origin) != top_level_site_) { + // If the top_level_site is opaque the ancestor chain bit doesn't need to be + // recalculated as it will be SameSite. If the ancestor chain bit is already + // CrossSite it should stay that way. Otherwise if the top level site + // doesn't match the new origin it needs to be updated to CrossSite. + ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite; + } + return CreateWithOptionalNonce( + origin, top_level_site, base::OptionalToPtr(nonce_), ancestor_chain_bit); } StorageKey::StorageKey(const url::Origin& origin, @@ -380,20 +410,23 @@ : blink::mojom::AncestorChainBit::kSameSite), ancestor_chain_bit_if_third_party_enabled_(ancestor_chain_bit) { #if DCHECK_IS_ON() - // If we're setting a `nonce`, the `top_level_site` must be the same as - // the `origin` and the `ancestor_chain_bit` must be kSameSite. We don't - // serialize those pieces of information so have to check to prevent - // mistaken reliance on what is supposed to be an invariant. if (nonce) { + // If we're setting a `nonce`, the `top_level_site` must be the same as + // the `origin` and the `ancestor_chain_bit` must be kSameSite. We don't + // serialize those pieces of information so have to check to prevent + // mistaken reliance on what is supposed to be an invariant. DCHECK(!nonce->is_empty()); DCHECK_EQ(top_level_site, net::SchemefulSite(origin)); DCHECK_EQ(ancestor_chain_bit, blink::mojom::AncestorChainBit::kSameSite); - } - // If we're setting an opaque `top_level_site`, the `ancestor_chain_bit` must - // be kSameSite. We don't serialize that information so have to check to - // prevent mistaken reliance on what is supposed to be an invariant. - if (top_level_site.opaque()) { + } else if (top_level_site.opaque()) { + // If we're setting an opaque `top_level_site`, the `ancestor_chain_bit` + // must be kSameSite. We don't serialize that information so have to check + // to prevent mistaken reliance on what is supposed to be an invariant. DCHECK_EQ(ancestor_chain_bit, blink::mojom::AncestorChainBit::kSameSite); + } else if (top_level_site != net::SchemefulSite(origin)) { + // If `top_level_site` doesn't match `origin` then we must be making a + // third-party StorageKey and `ancestor_chain_bit` must be kCrossSite. + DCHECK_EQ(ancestor_chain_bit, blink::mojom::AncestorChainBit::kCrossSite); } #endif }
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/0 b/third_party/blink/common/storage_key/storage_key_corpus/0 new file mode 100644 index 0000000..a364175 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/0
@@ -0,0 +1 @@ +https://example.com/ \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/1 b/third_party/blink/common/storage_key/storage_key_corpus/1 new file mode 100644 index 0000000..097532c --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/1
@@ -0,0 +1 @@ +https://foo.bar/ \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/10 b/third_party/blink/common/storage_key/storage_key_corpus/10 new file mode 100644 index 0000000..37b9cbd2 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/10
@@ -0,0 +1 @@ +https://example.com/^49876^55432^6 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/11 b/third_party/blink/common/storage_key/storage_key_corpus/11 new file mode 100644 index 0000000..276ff49 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/11
@@ -0,0 +1 @@ +https://foo.bar/^49876^55432^6https://example.com \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/12 b/third_party/blink/common/storage_key/storage_key_corpus/12 new file mode 100644 index 0000000..221aa3fb --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/12
@@ -0,0 +1 @@ +https://example.com/^^ \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/13 b/third_party/blink/common/storage_key/storage_key_corpus/13 new file mode 100644 index 0000000..00456fc4 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/13
@@ -0,0 +1 @@ +https://example.com/^2^3 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/2 b/third_party/blink/common/storage_key/storage_key_corpus/2 new file mode 100644 index 0000000..415935d --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/2
@@ -0,0 +1 @@ +https://example.com/^31 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/3 b/third_party/blink/common/storage_key/storage_key_corpus/3 new file mode 100644 index 0000000..7cd52d5 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/3
@@ -0,0 +1 @@ +https://foo.bar/^30 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/4 b/third_party/blink/common/storage_key/storage_key_corpus/4 new file mode 100644 index 0000000..98211ea6 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/4
@@ -0,0 +1 @@ +https://foo.bar/^0https://example.com/ \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/5 b/third_party/blink/common/storage_key/storage_key_corpus/5 new file mode 100644 index 0000000..55c4e34d2 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/5
@@ -0,0 +1 @@ +https://foo.bar/^0https://foo.bar/ \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/6 b/third_party/blink/common/storage_key/storage_key_corpus/6 new file mode 100644 index 0000000..a75864ad --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/6
@@ -0,0 +1 @@ +https://foo.bar/^0https://example.com/^30 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/7 b/third_party/blink/common/storage_key/storage_key_corpus/7 new file mode 100644 index 0000000..5efe0d3 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/7
@@ -0,0 +1 @@ +https://foo.bar/^0https://example.com/^31 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/8 b/third_party/blink/common/storage_key/storage_key_corpus/8 new file mode 100644 index 0000000..0e41138 --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/8
@@ -0,0 +1 @@ +https://foo.bar/^19876^25432 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_corpus/9 b/third_party/blink/common/storage_key/storage_key_corpus/9 new file mode 100644 index 0000000..726709e --- /dev/null +++ b/third_party/blink/common/storage_key/storage_key_corpus/9
@@ -0,0 +1 @@ +https://foo.bar/^19876^25432^30 \ No newline at end of file
diff --git a/third_party/blink/common/storage_key/storage_key_fuzzer.cc b/third_party/blink/common/storage_key/storage_key_fuzzer.cc index e744a19d..cdda4391 100644 --- a/third_party/blink/common/storage_key/storage_key_fuzzer.cc +++ b/third_party/blink/common/storage_key/storage_key_fuzzer.cc
@@ -22,20 +22,19 @@ DEFINE_PROTO_FUZZER( const storage_key_proto::StorageKeyFuzzer& storage_key_fuzzer) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - net::features::kThirdPartyStoragePartitioning); + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); - blink::StorageKey storage_key = Convert(storage_key_fuzzer.storage_key()); + blink::StorageKey storage_key = Convert(storage_key_fuzzer.storage_key()); + std::string result = storage_key.Serialize(); + absl::optional<blink::StorageKey> maybe_storage_key = + blink::StorageKey::Deserialize(result); + if (maybe_storage_key) { + assert(storage_key == maybe_storage_key.value()); + } - std::string result = storage_key.Serialize(); - absl::optional<blink::StorageKey> maybe_storage_key = - blink::StorageKey::Deserialize(result); - if (maybe_storage_key) { - assert(storage_key == maybe_storage_key.value()); + blink::StorageKey::Deserialize(storage_key_fuzzer.deserialize()); } - - // TODO(crbug.com/1270350): This could be a little closer to the serialization - // format - blink::StorageKey::Deserialize(storage_key_fuzzer.deserialize()); }
diff --git a/third_party/blink/common/storage_key/storage_key_unittest.cc b/third_party/blink/common/storage_key/storage_key_unittest.cc index bdc26428..b5ba678 100644 --- a/third_party/blink/common/storage_key/storage_key_unittest.cc +++ b/third_party/blink/common/storage_key/storage_key_unittest.cc
@@ -554,7 +554,7 @@ } } -TEST_F(StorageKeyTest, DeserializeBadNonces) { +TEST_F(StorageKeyTest, DeserializeNonces) { for (const bool toggle : {false, true}) { base::test::ScopedFeatureList scope_feature_list; scope_feature_list.InitWithFeatureState( @@ -616,6 +616,51 @@ } } +TEST_F(StorageKeyTest, DeserializeAncestorChainBits) { + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + struct { + const char* serialization; + absl::optional<blink::StorageKey> expected_key; + } kTestCases[] = { + // A matching origin and top_level_site should not have a SameSite bit. + { + "https://example.com/^0https://example.com^30", + absl::nullopt, + }, + // A matching origin and top_level_site should have a CrossSite bit. + { + "https://example.com/^0https://example.com^31", + StorageKey::CreateWithOptionalNonce( + url::Origin::Create(GURL("https://example.com")), + net::SchemefulSite(GURL("https://example.com")), nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // A mismatched origin and top_level_site should not have a SameSite + // bit. + { + "https://example.com/^0https://notexample.com^30", + absl::nullopt, + }, + // A mismatched origin and top_level_site should have a CrossSite bit. + { + "https://example.com/^0https://notexample.com^31", + StorageKey::CreateWithOptionalNonce( + url::Origin::Create(GURL("https://example.com")), + net::SchemefulSite(GURL("https://notexample.com")), nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + }; + + for (const auto& test : kTestCases) { + SCOPED_TRACE(test.serialization); + EXPECT_EQ(test.expected_key, StorageKey::Deserialize(test.serialization)); + } + } +} + TEST_F(StorageKeyTest, IsThirdPartyStoragePartitioningEnabled) { for (const bool toggle : {false, true}) { base::test::ScopedFeatureList scope_feature_list; @@ -668,21 +713,12 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndDisableFeature( net::features::kThirdPartyStoragePartitioning); - std::string same_site_string = - "https://example.com/^0https://test.example^30"; std::string cross_site_string = "https://example.com/^0https://test.example^31"; - - absl::optional<StorageKey> key_same_site = - StorageKey::Deserialize(same_site_string); absl::optional<StorageKey> key_cross_site = StorageKey::Deserialize(cross_site_string); - - EXPECT_TRUE(key_same_site.has_value()); EXPECT_TRUE(key_cross_site.has_value()); EXPECT_EQ(mojom::AncestorChainBit::kSameSite, - key_same_site->ancestor_chain_bit()); - EXPECT_EQ(mojom::AncestorChainBit::kSameSite, key_cross_site->ancestor_chain_bit()); } @@ -692,20 +728,11 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature( net::features::kThirdPartyStoragePartitioning); - std::string same_site_string = - "https://example.com/^0https://test.example^30"; std::string cross_site_string = "https://example.com/^0https://test.example^31"; - - absl::optional<StorageKey> key_same_site = - StorageKey::Deserialize(same_site_string); absl::optional<StorageKey> key_cross_site = StorageKey::Deserialize(cross_site_string); - - EXPECT_TRUE(key_same_site.has_value()); EXPECT_TRUE(key_cross_site.has_value()); - EXPECT_EQ(mojom::AncestorChainBit::kSameSite, - key_same_site->ancestor_chain_bit()); EXPECT_EQ(mojom::AncestorChainBit::kCrossSite, key_cross_site->ancestor_chain_bit()); } @@ -1036,4 +1063,239 @@ } } } + +TEST_F(StorageKeyTest, OriginAndSiteMismatchRequiresCrossSite) { + const url::Origin origin = url::Origin::Create(GURL("https://foo.com")); + const url::Origin opaque_origin; + const net::SchemefulSite site(origin); + const net::SchemefulSite other_site(GURL("https://notfoo.com")); + + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + + // A matching origin and site can be SameSite or CrossSite. + std::ignore = StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kSameSite); + std::ignore = StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kCrossSite); + + // A mismatched origin and site cannot be SameSite. + EXPECT_DCHECK_DEATH(StorageKey::CreateWithOptionalNonce( + origin, other_site, nullptr, mojom::AncestorChainBit::kSameSite)); + EXPECT_DCHECK_DEATH(StorageKey::CreateWithOptionalNonce( + opaque_origin, other_site, nullptr, + mojom::AncestorChainBit::kSameSite)); + + // A mismatched origin and site must be CrossSite. + std::ignore = StorageKey::CreateWithOptionalNonce( + origin, other_site, nullptr, mojom::AncestorChainBit::kCrossSite); + } +} + +TEST_F(StorageKeyTest, WithOrigin) { + const url::Origin origin = url::Origin::Create(GURL("https://foo.com")); + const url::Origin other_origin = + url::Origin::Create(GURL("https://notfoo.com")); + const net::SchemefulSite site(origin); + const net::SchemefulSite other_site(other_origin); + const net::SchemefulSite opaque_site; + const base::UnguessableToken nonce = base::UnguessableToken::Create(); + + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + + const struct { + blink::StorageKey original_key; + url::Origin new_origin; + absl::optional<blink::StorageKey> expected_key; + } kTestCases[] = { + // No change in first-party key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kSameSite), + origin, + absl::nullopt, + }, + // Change in first-party key updated with new origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kSameSite), + other_origin, + blink::StorageKey::CreateWithOptionalNonce( + other_origin, site, nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // No change in third-party same-site key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kCrossSite), + origin, + absl::nullopt, + }, + // Change in third-party same-site key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kCrossSite), + other_origin, + blink::StorageKey::CreateWithOptionalNonce( + other_origin, site, nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // No change in third-party key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, other_site, nullptr, + mojom::AncestorChainBit::kCrossSite), + origin, + absl::nullopt, + }, + // Change in third-party key updated with new origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, other_site, nullptr, + mojom::AncestorChainBit::kCrossSite), + other_origin, + blink::StorageKey::CreateWithOptionalNonce( + other_origin, other_site, nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // No change in opaque tls key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, opaque_site, nullptr, + mojom::AncestorChainBit::kSameSite), + origin, + absl::nullopt, + }, + // Change in opaque tls key updated with new origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, opaque_site, nullptr, + mojom::AncestorChainBit::kSameSite), + other_origin, + blink::StorageKey::CreateWithOptionalNonce( + other_origin, opaque_site, nullptr, + mojom::AncestorChainBit::kSameSite), + }, + // No change in nonce key updated with same origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, &nonce, mojom::AncestorChainBit::kSameSite), + origin, + absl::nullopt, + }, + // Change in nonce key updated with new origin. + { + blink::StorageKey::CreateWithOptionalNonce( + origin, site, &nonce, mojom::AncestorChainBit::kSameSite), + other_origin, + blink::StorageKey::CreateWithOptionalNonce( + other_origin, other_site, &nonce, + mojom::AncestorChainBit::kSameSite), + }, + }; + + for (const auto& test_case : kTestCases) { + if (test_case.expected_key == absl::nullopt) { + EXPECT_EQ(test_case.original_key, + test_case.original_key.WithOrigin(test_case.new_origin)); + } else { + ASSERT_NE(test_case.expected_key, test_case.original_key); + EXPECT_EQ(test_case.expected_key, + test_case.original_key.WithOrigin(test_case.new_origin)); + } + } + } +} + +TEST_F(StorageKeyTest, CreateFromOriginAndIsolationInfo) { + const url::Origin origin = url::Origin::Create(GURL("https://foo.com")); + const url::Origin other_origin = + url::Origin::Create(GURL("https://notfoo.com")); + const url::Origin opaque_origin; + const net::SchemefulSite site(origin); + const net::SchemefulSite other_site(other_origin); + const net::SchemefulSite opaque_site(opaque_origin); + const base::UnguessableToken nonce = base::UnguessableToken::Create(); + + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + + const struct { + url::Origin new_origin; + const net::IsolationInfo isolation_info; + absl::optional<blink::StorageKey> expected_key; + } kTestCases[] = { + // First party context. + { + origin, + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kMainFrame, origin, origin, + net::SiteForCookies::FromOrigin(origin), absl::nullopt, + nullptr), + blink::StorageKey::CreateWithOptionalNonce( + origin, site, nullptr, mojom::AncestorChainBit::kSameSite), + }, + // Third party same-site context. + { + other_origin, + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kMainFrame, other_origin, + origin, net::SiteForCookies(), absl::nullopt, nullptr), + blink::StorageKey::CreateWithOptionalNonce( + other_origin, other_site, nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // Third party context. + { + other_origin, + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kMainFrame, origin, origin, + net::SiteForCookies::FromOrigin(origin), absl::nullopt, + nullptr), + blink::StorageKey::CreateWithOptionalNonce( + other_origin, site, nullptr, + mojom::AncestorChainBit::kCrossSite), + }, + // Opaque TLS context. + { + origin, + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kMainFrame, opaque_origin, + opaque_origin, net::SiteForCookies::FromOrigin(opaque_origin), + absl::nullopt, nullptr), + blink::StorageKey::CreateWithOptionalNonce( + origin, opaque_site, nullptr, + mojom::AncestorChainBit::kSameSite), + }, + // Nonce context. + { + origin, + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kMainFrame, other_origin, + other_origin, net::SiteForCookies::FromOrigin(other_origin), + absl::nullopt, &nonce), + blink::StorageKey::CreateWithOptionalNonce( + origin, site, &nonce, mojom::AncestorChainBit::kSameSite), + }, + }; + + for (const auto& test_case : kTestCases) { + if (test_case.expected_key == absl::nullopt) { + EXPECT_DCHECK_DEATH(StorageKey::CreateFromOriginAndIsolationInfo( + test_case.new_origin, test_case.isolation_info)); + } else { + EXPECT_EQ(test_case.expected_key, + StorageKey::CreateFromOriginAndIsolationInfo( + test_case.new_origin, test_case.isolation_info)); + } + } + } +} } // namespace blink
diff --git a/third_party/blink/perf_tests/events/EventsDispatchingDifferentEventsOnSameNode.html b/third_party/blink/perf_tests/events/EventsDispatchingDifferentEventsOnSameNode.html deleted file mode 100644 index f35e730d..0000000 --- a/third_party/blink/perf_tests/events/EventsDispatchingDifferentEventsOnSameNode.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script type="text/javascript" src="../resources/runner.js"></script> -</head> -<body> -<script> - -// Repeatedly send different events to the same node. -let node = document.body; -let depth = 50; -while (depth) { - const child = document.createElement('div'); - node.appendChild(child); - node = child; - depth--; -} -const numEvents = 1000; -const customEvents = Array.from(Array(numEvents)).map((_, i) => { - return new Event(`foo-${i}`); -}); - - -function run() { - customEvents.forEach((event) => node.dispatchEvent(event)); -} - -PerfTestRunner.measureRunsPerSecond({ - description: "Measure events dispatching on same node", - run: run, -}); -</script> -</body> -</html>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index d540928..f693e1b 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -287,6 +287,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kCacheCodeOnIdle); BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kCacheCodeOnIdleDelayParam; +BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> + kCacheCodeOnIdleDelayServiceWorkerOnlyParam; BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kAlignFontDisplayAutoTimeoutWithLCPGoal); @@ -831,14 +833,6 @@ // If enabled, reads and decodes navigation body data off the main thread. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kThreadedBodyLoader); -// If enabled, will cache for each node's EventPath::NodePath in document. -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDocumentEventNodePathCaching); - -// Parameter for tuning max entries allowed in EventNodePathCache, which will be -// used to do LRU eviction in document. -BLINK_COMMON_EXPORT extern const base::FeatureParam<int> - kDocumentMaxEventNodePathCachedEntries; - // Whether first-party to third-party different-bucket same-origin post messages // are blocked. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
diff --git a/third_party/blink/public/common/origin_trials/trial_token.h b/third_party/blink/public/common/origin_trials/trial_token.h index 583388ac..f4f6e20 100644 --- a/third_party/blink/public/common/origin_trials/trial_token.h +++ b/third_party/blink/public/common/origin_trials/trial_token.h
@@ -88,7 +88,8 @@ const std::string& feature_name, base::Time expiry_time, bool is_third_party, - UsageRestriction usage_restriction); + UsageRestriction usage_restriction, + const std::string& signature); protected: // Tests can access the Parse method directly to validate it, and so are
diff --git a/third_party/blink/public/common/storage_key/storage_key.h b/third_party/blink/public/common/storage_key/storage_key.h index 81e7721..03f12b9 100644 --- a/third_party/blink/public/common/storage_key/storage_key.h +++ b/third_party/blink/public/common/storage_key/storage_key.h
@@ -43,16 +43,21 @@ // `a.com` frame can be controlled by `b.com`, and is thus considered // third-party. The ancestor chain bit tracks this status. // +// TODO(https://crbug.com/1410254): Use kCrossSite for this case. // Storage keys can also optionally have a nonce. Keys with different nonces are // considered distinct, and distinct from a key with no nonce. This is used to // implement iframe credentialless and other forms of storage partitioning. // Keys with a nonce disregard the top level site and ancestor chain bit. For // consistency we set them to the origin's site and `kSameSite` respectively. // +// TODO(https://crbug.com/1410254): Use kCrossSite for this case. // Storage keys might have an opaque top level site (for example, if an // iframe is embedded in a data url). These storage keys always have a // `kSameSite` ancestor chain bit as it provides no additional distinctiveness. // +// Storage keys might have a top level site and origin that don't match. These +// storage keys always have a `kCrossSite` ancestor chain bit. +// // For more details on the overall design, see // https://docs.google.com/document/d/1xd6MXcUhfnZqIe5dt2CTyCn6gEZ7nOezAEWS0W9hwbQ/edit. class BLINK_COMMON_EXPORT StorageKey { @@ -81,7 +86,8 @@ // Callers may specify an optional `nonce` by passing nullptr. // If the `nonce` isn't null, `top_level_site` must be the same as `origin` // and `ancestor_chain_bit` must be kSameSite. If `top_level_site` is opaque, - // `ancestor_chain_bit` must be `kSameSite`. + // `ancestor_chain_bit` must be `kSameSite`, otherwise if `top_level_site` + // doesn't match `origin` `ancestor_chain_bit` must be `kCrossSite`. static StorageKey CreateWithOptionalNonce( const url::Origin& origin, const net::SchemefulSite& top_level_site,
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 5b8b987..9730aae 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -747,6 +747,7 @@ FormDuplicateIdForInputError FormInputWithNoLabelError FormAutocompleteAttributeEmptyError + FormEmptyIdAndNameAttributesForInputError # Depending on the concrete errorType, different properties are set. type GenericIssueDetails extends object
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 2b520fa8..96f8f99f 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -257,7 +257,6 @@ "//components/schema_org/common:mojom", "//components/services/filesystem/public/mojom", "//mojo/public/mojom/base", - "//services/data_decoder/public/mojom:mojom_resource_snapshot_for_web_bundle", "//services/device/public/mojom", "//services/network/public/mojom", "//services/network/public/mojom:mojom_ip_address", @@ -1223,7 +1222,6 @@ if (is_android) { # Direct deps (instead of transitive deps) are necessary for java targets. public_deps += [ - "//services/data_decoder/public/mojom:mojom_resource_snapshot_for_web_bundle", "//services/network/public/mojom:cookies_mojom", "//services/network/public/mojom:url_loader_base", "//third_party/blink/public/mojom/tokens",
diff --git a/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/third_party/blink/public/mojom/devtools/inspector_issue.mojom index 1f007d6..c388b60 100644 --- a/third_party/blink/public/mojom/devtools/inspector_issue.mojom +++ b/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -224,7 +224,8 @@ kFormLabelForNameError, kFormDuplicateIdForInputError, kFormInputWithNoLabelError, - kFormAutocompleteAttributeEmptyError + kFormAutocompleteAttributeEmptyError, + kFormEmptyIdAndNameAttributesForInputError, }; struct GenericIssueDetails {
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 49be4861..14a1534 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -10,7 +10,6 @@ import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; import "mojo/public/mojom/base/values.mojom"; -import "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom"; import "services/network/public/mojom/content_security_policy.mojom"; import "services/network/public/mojom/cross_origin_opener_policy.mojom"; import "services/network/public/mojom/fetch_api.mojom"; @@ -757,13 +756,6 @@ // Notifies this frame to clear the focused element (if any). ClearFocusedElement(); - // Gets the resource snapshot of the frame for creating Web Bundle. - // The instance of ResourceSnapshotForWebBundle in the renderer process will - // be kept alive as far as the Mojo endpoint is held and the renderer process - // is alive. - GetResourceSnapshotForWebBundle( - pending_receiver<data_decoder.mojom.ResourceSnapshotForWebBundle> receiver); - // Copies the image at |window_point| to the clipboard (if there indeed is an // image at that |window_point|). CopyImageAt(gfx.mojom.Point window_point);
diff --git a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom index 9dda44a..8e3eb688 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
@@ -794,6 +794,7 @@ kAnimationRangeStart = 741, kAnimationRangeEnd = 742, kAnimationComposition = 743, + kTopLayer = 744, // 1. Add new features above this line (don't change the assigned numbers of // the existing items). // 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
diff --git a/third_party/blink/public/platform/web_font_render_style.h b/third_party/blink/public/platform/web_font_render_style.h index a16ae790..b30b4785 100644 --- a/third_party/blink/public/platform/web_font_render_style.h +++ b/third_party/blink/public/platform/web_font_render_style.h
@@ -74,7 +74,7 @@ // kNoPreference in |other|. void OverrideWith(const WebFontRenderStyle& other); - void ApplyToSkFont(SkFont*, bool should_use_subpixel_positioning) const; + void ApplyToSkFont(SkFont*) const; // Each of the use* members below can take one of three values: // 0: off
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc index f3059a3..a77536f 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -266,7 +266,7 @@ if (!ReadUint64(&high) || !ReadUint64(&low)) return false; absl::optional<base::UnguessableToken> token = - base::UnguessableToken::Deserialize2(high, low); + base::UnguessableToken::Deserialize(high, low); if (!token.has_value()) { return false; }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index 05d4b4d9..1ddfdb5 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -537,7 +537,10 @@ } if (produce_cache_options == V8CodeCache::ProduceCacheOptions::kProduceCodeCache && - base::FeatureList::IsEnabled(features::kCacheCodeOnIdle)) { + base::FeatureList::IsEnabled(features::kCacheCodeOnIdle) && + (features::kCacheCodeOnIdleDelayServiceWorkerOnlyParam.Get() + ? execution_context->IsServiceWorkerGlobalScope() + : true)) { auto delay = base::Milliseconds(features::kCacheCodeOnIdleDelayParam.Get()); // Workers don't have a concept of idle tasks, so use a default task for
diff --git a/third_party/blink/renderer/controller/blink_initializer.cc b/third_party/blink/renderer/controller/blink_initializer.cc index 51eed876..15cbe97 100644 --- a/third_party/blink/renderer/controller/blink_initializer.cc +++ b/third_party/blink/renderer/controller/blink_initializer.cc
@@ -250,7 +250,7 @@ HighestPmfReporter::Initialize(main_thread_task_runner); #endif -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) && !defined(ARCH_CPU_64_BITS) // Initialize PrivateMemoryFootprintProvider to start providing the value // for the browser process. PrivateMemoryFootprintProvider::Initialize(main_thread_task_runner);
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index e717dbc..dd03231 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -64,7 +64,6 @@ "+mojo/public/cpp/bindings", "+mojo/public/cpp/system", "+mojo/public/mojom/base", - "+services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h", "+services/device/public/mojom/device_posture_provider.mojom-blink-forward.h", "+services/device/public/mojom/device_posture_provider.mojom-blink.h", "+services/device/public/mojom/wake_lock.mojom-blink.h",
diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn index 2d39f82..4ce94baa 100644 --- a/third_party/blink/renderer/core/animation/BUILD.gn +++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -278,6 +278,8 @@ "svg_transform_list_interpolation_type.h", "svg_value_interpolation_type.cc", "svg_value_interpolation_type.h", + "timeline_offset.cc", + "timeline_offset.h", "timing.cc", "timing.h", "timing_calculations.h",
diff --git a/third_party/blink/renderer/core/animation/animatable.cc b/third_party/blink/renderer/core/animation/animatable.cc index 1b64fd6..565de73 100644 --- a/third_party/blink/renderer/core/animation/animatable.cc +++ b/third_party/blink/renderer/core/animation/animatable.cc
@@ -6,8 +6,11 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_get_animations_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_keyframe_animation_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range_offset.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeanimationoptions_unrestricteddouble.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_keyframeeffectoptions_unrestricteddouble.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_timelinerangeoffset.h" #include "third_party/blink/renderer/core/animation/animation.h" #include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/animation/document_timeline.h" @@ -22,6 +25,7 @@ #include "third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/geometry/calculation_value.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -62,6 +66,71 @@ return nullptr; } +TimelineOffset ConvertRangeOffset( + const V8UnionStringOrTimelineRangeOffset* range_offset, + double default_percent, + ExceptionState& exception_state) { + TimelineOffset result; + if (range_offset->IsString()) { + // TODO(kevers): Implement once we have CSS support for animation-range. + result.name = TimelineOffset::NamedRange::kNone; + result.offset = Length(default_percent, Length::Type::kPercent); + } else { + TimelineRangeOffset* value = range_offset->GetAsTimelineRangeOffset(); + result.name = value->hasRangeName() ? value->rangeName().AsEnum() + : TimelineOffset::NamedRange::kNone; + if (value->hasOffset()) { + CSSNumericValue* offset = value->offset(); + const CSSPrimitiveValue* css_value = + DynamicTo<CSSPrimitiveValue>(offset->ToCSSValue()); + + if (!css_value || (!css_value->IsPx() && !css_value->IsPercentage() && + !css_value->IsCalculatedPercentageWithLength())) { + exception_state.ThrowTypeError( + "CSSNumericValue must be a length or percentage for animation " + "range."); + return result; + } + + if (css_value->IsPx()) { + result.offset = Length::Fixed(css_value->GetDoubleValue()); + } else if (css_value->IsPercentage()) { + result.offset = Length::Percent(css_value->GetDoubleValue()); + } else { + // TODO(kevers): Resolve if we need to handle style-dependent lengths + // such as em. If so, what is the reference element for resolving the + // style? + DCHECK(css_value->IsCalculatedPercentageWithLength()); + CSSLengthArray length_array; + css_value->AccumulateLengthArray(length_array); + double percent = 0; + double px = 0; + for (wtf_size_t i = 0; i < length_array.values.size(); ++i) { + double array_value = length_array.values[i]; + if (array_value == 0) { + continue; + } + if (i == CSSPrimitiveValue::kUnitTypePercentage) { + percent = array_value; + } else if (i == CSSPrimitiveValue::kUnitTypePixels) { + px = array_value; + } else { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + "Unsupported range offset"); + return result; + } + } + result.offset = Length(CalculationValue::Create( + PixelsAndPercent(px, percent), Length::ValueRange::kAll)); + } + } else { + result.offset = Length::Percent(default_percent); + } + } + return result; +} + } // namespace // https://w3.org/TR/web-animations-1/#dom-animatable-animate @@ -107,6 +176,16 @@ return nullptr; animation->setId(options_dict->id()); + + // ViewTimeline options. + if (options_dict->hasRangeStart()) { + animation->SetRangeStart( + ConvertRangeOffset(options_dict->rangeStart(), 0, exception_state)); + } + if (options_dict->hasRangeEnd()) { + animation->SetRangeEnd( + ConvertRangeOffset(options_dict->rangeEnd(), 100, exception_state)); + } return animation; }
diff --git a/third_party/blink/renderer/core/animation/animation.h b/third_party/blink/renderer/core/animation/animation.h index d6c0d10..82e4a05 100644 --- a/third_party/blink/renderer/core/animation/animation.h +++ b/third_party/blink/renderer/core/animation/animation.h
@@ -36,16 +36,18 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_union_string_timelinerangeoffset.h" #include "third_party/blink/renderer/core/animation/animation_effect.h" #include "third_party/blink/renderer/core/animation/animation_effect_owner.h" #include "third_party/blink/renderer/core/animation/compositor_animations.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h" +#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -209,6 +211,28 @@ AnimationTimeline* timeline() { return timeline_; } AnimationTimeline* timeline() const { return timeline_; } virtual void setTimeline(AnimationTimeline* timeline); + + // Animation options for ViewTimelines. + // TODO(kevers): Add web-animation-API methods once specced. + const absl::optional<TimelineOffset>& GetRangeStart() const { + return range_start_; + } + const absl::optional<TimelineOffset>& GetRangeEnd() const { + return range_end_; + } + void SetRangeStart(const absl::optional<TimelineOffset>& range_start) { + range_start_ = range_start; + if (content_) { + content_->InvalidateNormalizedTiming(); + } + } + void SetRangeEnd(const absl::optional<TimelineOffset>& range_end) { + range_end_ = range_end; + if (content_) { + content_->InvalidateNormalizedTiming(); + } + } + Document* GetDocument() const; V8CSSNumberish* startTime() const; @@ -440,6 +464,9 @@ Member<Document> document_; Member<AnimationTimeline> timeline_; + absl::optional<TimelineOffset> range_start_; + absl::optional<TimelineOffset> range_end_; + ReplaceState replace_state_; // Testing flags.
diff --git a/third_party/blink/renderer/core/animation/animation_effect.cc b/third_party/blink/renderer/core/animation/animation_effect.cc index 21fbf6d..1be261de4 100644 --- a/third_party/blink/renderer/core/animation/animation_effect.cc +++ b/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -371,7 +371,8 @@ AnimationEffect::TimeDelayPair AnimationEffect::TimelineOffsetsToTimeDelays() const { if (GetAnimation() && GetAnimation()->timeline()) { - return GetAnimation()->timeline()->TimelineOffsetsToTimeDelays(timing_); + return GetAnimation()->timeline()->TimelineOffsetsToTimeDelays( + owner_->GetAnimation()); } return std::make_pair(AnimationTimeDelta(), AnimationTimeDelta()); }
diff --git a/third_party/blink/renderer/core/animation/animation_effect_test.cc b/third_party/blink/renderer/core/animation/animation_effect_test.cc index c766873..1899ce6 100644 --- a/third_party/blink/renderer/core/animation/animation_effect_test.cc +++ b/third_party/blink/renderer/core/animation/animation_effect_test.cc
@@ -56,30 +56,6 @@ return MakeGarbageCollected<Timing::V8Delay>(delay_in_ms); } -bool TimelineOffsetEquals(const Timing::V8TimelineRangeOffset* value, - String expected_range, - double expected_offset_as_percent) { - if (!value->IsTimelineRangeOffset()) { - return false; - } - - TimelineRangeOffset* timeline_range_offset = - value->GetAsTimelineRangeOffset(); - if (!timeline_range_offset->hasRangeName() || - !timeline_range_offset->hasOffset()) { - return false; - } - - if (timeline_range_offset->rangeName() != expected_range) { - return false; - } - - double percent = timeline_range_offset->offset() - ->to(CSSPrimitiveValue::UnitType::kPercentage) - ->value(); - return std::abs(percent - expected_offset_as_percent) < 1e-6; -} - class MockAnimationEffectOwner : public GarbageCollected<MockAnimationEffectOwner>, public AnimationEffectOwner { @@ -801,24 +777,10 @@ effect->updateTiming(effect_timing); EXPECT_EQ(2, effect->getTiming()->delay()->GetAsDouble()); effect_timing = OptionalEffectTiming::Create(); - - effect_timing->setRangeStart(CreateTimelineOffset("enter", 0)); - effect->updateTiming(effect_timing); - EXPECT_TRUE( - TimelineOffsetEquals(effect->getTiming()->rangeStart(), "enter", 0)); - EXPECT_EQ(0, effect->getTiming()->endDelay()->GetAsDouble()); - - effect_timing = OptionalEffectTiming::Create(); effect_timing->setEndDelay(CreateTimeDelay(0.5)); effect->updateTiming(effect_timing); EXPECT_EQ(0.5, effect->getTiming()->endDelay()->GetAsDouble()); effect_timing = OptionalEffectTiming::Create(); - effect_timing->setRangeEnd(CreateTimelineOffset("exit", 50)); - effect->updateTiming(effect_timing); - EXPECT_TRUE( - TimelineOffsetEquals(effect->getTiming()->rangeEnd(), "exit", 50)); - EXPECT_EQ("auto", effect->getTiming()->fill()); - effect_timing = OptionalEffectTiming::Create(); effect_timing->setFill("backwards"); effect->updateTiming(effect_timing); EXPECT_EQ("backwards", effect->getTiming()->fill());
diff --git a/third_party/blink/renderer/core/animation/animation_timeline.h b/third_party/blink/renderer/core/animation/animation_timeline.h index b5e1752..355cbdd6 100644 --- a/third_party/blink/renderer/core/animation/animation_timeline.h +++ b/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -73,6 +73,7 @@ // consideration here: https://github.com/w3c/csswg-drafts/issues/2075. virtual absl::optional<base::TimeDelta> InitialStartTimeForAnimations() = 0; virtual AnimationTimeDelta CalculateIntrinsicIterationDuration( + const Animation*, const Timing&) { return AnimationTimeDelta(); } @@ -82,7 +83,7 @@ // of a view timeline, the delays are zero. using TimeDelayPair = std::pair<AnimationTimeDelta, AnimationTimeDelta>; virtual TimeDelayPair TimelineOffsetsToTimeDelays( - const Timing& timing) const { + const Animation* animation) const { return std::make_pair(AnimationTimeDelta(), AnimationTimeDelta()); }
diff --git a/third_party/blink/renderer/core/animation/css/css_animation_data.cc b/third_party/blink/renderer/core/animation/css/css_animation_data.cc index 27db687..ee17f6a 100644 --- a/third_party/blink/renderer/core/animation/css/css_animation_data.cc +++ b/third_party/blink/renderer/core/animation/css/css_animation_data.cc
@@ -15,6 +15,8 @@ direction_list_.push_back(InitialDirection()); fill_mode_list_.push_back(InitialFillMode()); play_state_list_.push_back(InitialPlayState()); + range_start_list_.push_back(InitialRangeStart()); + range_end_list_.push_back(InitialRangeEnd()); composition_list_.push_back(InitialComposition()); }
diff --git a/third_party/blink/renderer/core/animation/css/css_animation_data.h b/third_party/blink/renderer/core/animation/css/css_animation_data.h index 36cb50e..13c2eef 100644 --- a/third_party/blink/renderer/core/animation/css/css_animation_data.h +++ b/third_party/blink/renderer/core/animation/css/css_animation_data.h
@@ -49,6 +49,13 @@ const Vector<EAnimPlayState>& PlayStateList() const { return play_state_list_; } + const Vector<absl::optional<TimelineOffset>>& RangeStartList() const { + return range_start_list_; + } + const Vector<absl::optional<TimelineOffset>>& RangeEndList() const { + return range_end_list_; + } + const Vector<EffectModel::CompositeOperation>& CompositionList() const { return composition_list_; } @@ -67,6 +74,13 @@ Vector<Timing::PlaybackDirection>& DirectionList() { return direction_list_; } Vector<Timing::FillMode>& FillModeList() { return fill_mode_list_; } Vector<EAnimPlayState>& PlayStateList() { return play_state_list_; } + + Vector<absl::optional<TimelineOffset>>& RangeStartList() { + return range_start_list_; + } + Vector<absl::optional<TimelineOffset>>& RangeEndList() { + return range_end_list_; + } Vector<EffectModel::CompositeOperation>& CompositionList() { return composition_list_; } @@ -79,6 +93,12 @@ static Timing::FillMode InitialFillMode() { return Timing::FillMode::NONE; } static double InitialIterationCount() { return 1.0; } static EAnimPlayState InitialPlayState() { return EAnimPlayState::kPlaying; } + static absl::optional<TimelineOffset> InitialRangeStart() { + return absl::nullopt; + } + static absl::optional<TimelineOffset> InitialRangeEnd() { + return absl::nullopt; + } static EffectModel::CompositeOperation InitialComposition() { return EffectModel::CompositeOperation::kCompositeReplace; } @@ -86,6 +106,8 @@ private: Vector<AtomicString> name_list_; Vector<StyleTimeline> timeline_list_; + Vector<absl::optional<TimelineOffset>> range_start_list_; + Vector<absl::optional<TimelineOffset>> range_end_list_; Vector<double> iteration_count_list_; Vector<Timing::PlaybackDirection> direction_list_; Vector<Timing::FillMode> fill_mode_list_;
diff --git a/third_party/blink/renderer/core/animation/css/css_animation_update.h b/third_party/blink/renderer/core/animation/css/css_animation_update.h index f253b78..5dc3666ae 100644 --- a/third_party/blink/renderer/core/animation/css/css_animation_update.h +++ b/third_party/blink/renderer/core/animation/css/css_animation_update.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_UPDATE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_ANIMATION_UPDATE_H_ +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/core/animation/animation_timeline.h" #include "third_party/blink/renderer/core/animation/css/css_scroll_timeline.h" #include "third_party/blink/renderer/core/animation/css/css_timeline_map.h" @@ -13,6 +14,7 @@ #include "third_party/blink/renderer/core/animation/inert_effect.h" #include "third_party/blink/renderer/core/animation/interpolation.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_keyframes_rule.h" #include "third_party/blink/renderer/core/css/css_property_equality.h" @@ -39,7 +41,9 @@ Timing timing, StyleRuleKeyframes* style_rule, AnimationTimeline* timeline, - const Vector<EAnimPlayState>& play_state_list) + const Vector<EAnimPlayState>& play_state_list, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end) : name(name), name_index(name_index), position_index(position_index), @@ -48,7 +52,9 @@ style_rule(style_rule), style_rule_version(this->style_rule->Version()), timeline(timeline), - play_state_list(play_state_list) {} + play_state_list(play_state_list), + range_start(range_start), + range_end(range_end) {} void Trace(Visitor* visitor) const { visitor->Trace(effect); @@ -65,6 +71,8 @@ unsigned style_rule_version; Member<AnimationTimeline> timeline; Vector<EAnimPlayState> play_state_list; + absl::optional<TimelineOffset> range_start; + absl::optional<TimelineOffset> range_end; }; class UpdatedCSSAnimation { @@ -77,7 +85,9 @@ Timing specified_timing, StyleRuleKeyframes* style_rule, AnimationTimeline* timeline, - const Vector<EAnimPlayState>& play_state_list) + const Vector<EAnimPlayState>& play_state_list, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end) : specified_timing(specified_timing), index(index), animation(animation), @@ -85,7 +95,9 @@ style_rule(style_rule), style_rule_version(this->style_rule->Version()), timeline(timeline), - play_state_list(play_state_list) {} + play_state_list(play_state_list), + range_start(range_start), + range_end(range_end) {} void Trace(Visitor* visitor) const { visitor->Trace(animation); @@ -102,6 +114,8 @@ unsigned style_rule_version; Member<AnimationTimeline> timeline; Vector<EAnimPlayState> play_state_list; + absl::optional<TimelineOffset> range_start; + absl::optional<TimelineOffset> range_end; }; } // namespace blink @@ -133,10 +147,12 @@ const Timing& timing, StyleRuleKeyframes* style_rule, AnimationTimeline* timeline, - const Vector<EAnimPlayState>& play_state_list) { - new_animations_.push_back( - NewCSSAnimation(animation_name, name_index, position_index, effect, - timing, style_rule, timeline, play_state_list)); + const Vector<EAnimPlayState>& play_state_list, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end) { + new_animations_.push_back(NewCSSAnimation( + animation_name, name_index, position_index, effect, timing, style_rule, + timeline, play_state_list, range_start, range_end)); } void CancelAnimation(wtf_size_t index, const Animation& animation) { cancelled_animation_indices_.push_back(index); @@ -151,10 +167,12 @@ const Timing& specified_timing, StyleRuleKeyframes* style_rule, AnimationTimeline* timeline, - const Vector<EAnimPlayState>& play_state_list) { - animations_with_updates_.push_back( - UpdatedCSSAnimation(index, animation, effect, specified_timing, - style_rule, timeline, play_state_list)); + const Vector<EAnimPlayState>& play_state_list, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end) { + animations_with_updates_.push_back(UpdatedCSSAnimation( + index, animation, effect, specified_timing, style_rule, timeline, + play_state_list, range_start, range_end)); suppressed_animations_.insert(animation); } void UpdateCompositorKeyframes(Animation* animation) {
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index 74efbe1..4e18f0a 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -122,14 +122,14 @@ bool drop_keyframe = false; // If keyframe doesn't have a named range offset, act as before, we don't // care if we have a timeline at this point or not in this case. - if (offsets[0].name == Timing::TimelineNamedRange::kNone) { + if (offsets[0].name == TimelineOffset::NamedRange::kNone) { keyframe->SetOffset(offsets[0].percent); } else { // No matter what the timeline is, we have named range keyframes. has_named_range_keyframes = true; if (timeline && timeline->IsViewTimeline()) { - Timing::TimelineOffset timeline_offset( + TimelineOffset timeline_offset( offsets[0].name, Length::Percent(100 * offsets[0].percent)); double fractional_offset = To<ViewTimeline>(timeline)->ToFractionalOffset(timeline_offset); @@ -188,13 +188,13 @@ } // The last keyframe specified at a given offset is used. for (wtf_size_t j = 1; j < offsets.size(); ++j) { - if (offsets[j].name == Timing::TimelineNamedRange::kNone) { + if (offsets[j].name == TimelineOffset::NamedRange::kNone) { keyframes.push_back( To<StringKeyframe>(keyframe->CloneWithOffset(offsets[j].percent))); } else { has_named_range_keyframes = true; if (timeline && timeline->IsViewTimeline()) { - Timing::TimelineOffset timeline_offset( + TimelineOffset timeline_offset( offsets[j].name, Length::Percent(100 * offsets[j].percent)); double fractional_offset = To<ViewTimeline>(timeline)->ToFractionalOffset(timeline_offset); @@ -1210,6 +1210,10 @@ const StyleTimeline& style_timeline = animation_data->GetTimeline(i); + const absl::optional<TimelineOffset>& range_start = + animation_data->GetRepeated(animation_data->RangeStartList(), i); + const absl::optional<TimelineOffset>& range_end = + animation_data->GetRepeated(animation_data->RangeEndList(), i); const EffectModel::CompositeOperation composite = animation_data->GetComposition(i); @@ -1308,7 +1312,9 @@ existing_animation->style_rule_version || existing_animation->specified_timing != specified_timing || is_paused != was_paused || logical_property_mapping_change || - timeline != existing_animation->Timeline()) { + timeline != existing_animation->Timeline() || + range_start != existing_animation->RangeStart() || + range_end != existing_animation->RangeEnd()) { DCHECK(!is_animation_style_change); absl::optional<AnimationTimeDelta> inherited_time; absl::optional<AnimationTimeDelta> timeline_duration; @@ -1363,7 +1369,7 @@ timing, is_paused, inherited_time, timeline_duration, animation->playbackRate()), specified_timing, keyframes_rule, timeline, - animation_data->PlayStateList()); + animation_data->PlayStateList(), range_start, range_end); if (toggle_pause_state) update.ToggleAnimationIndexPaused(existing_animation_index); } @@ -1390,7 +1396,7 @@ composite, i, timeline), timing, is_paused, inherited_time, timeline_duration, 1.0), specified_timing, keyframes_rule, timeline, - animation_data->PlayStateList()); + animation_data->PlayStateList(), range_start, range_end); } } } @@ -1678,6 +1684,12 @@ entry.animation->setTimeline(entry.timeline); To<CSSAnimation>(*entry.animation).ResetIgnoreCSSTimeline(); } + if (entry.animation->GetRangeStart() != entry.range_start) { + entry.animation->SetRangeStart(entry.range_start); + } + if (entry.animation->GetRangeEnd() != entry.range_end) { + entry.animation->SetRangeEnd(entry.range_end); + } running_animations_[entry.index]->Update(entry); entry.animation->Update(kTimingUpdateOnDemand); @@ -1712,6 +1724,8 @@ if (inert_animation->Paused()) animation->pause(); animation->resetIgnoreCSSPlayState(); + animation->SetRangeStart(entry.range_start); + animation->SetRangeEnd(entry.range_end); animation->Update(kTimingUpdateOnDemand); running_animations_.push_back(
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.h b/third_party/blink/renderer/core/animation/css/css_animations.h index 43e5a95..7d63756 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.h +++ b/third_party/blink/renderer/core/animation/css/css_animations.h
@@ -38,6 +38,7 @@ #include "third_party/blink/renderer/core/animation/css/css_transition_data.h" #include "third_party/blink/renderer/core/animation/inert_effect.h" #include "third_party/blink/renderer/core/animation/interpolation.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_keyframes_rule.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" @@ -154,6 +155,12 @@ } AnimationTimeline* Timeline() const { return animation->timeline(); } + const absl::optional<TimelineOffset>& RangeStart() const { + return animation->GetRangeStart(); + } + const absl::optional<TimelineOffset>& RangeEnd() const { + return animation->GetRangeEnd(); + } void Update(UpdatedCSSAnimation update) { DCHECK_EQ(update.animation, animation); @@ -161,7 +168,6 @@ style_rule_version = update.style_rule_version; play_state_list = update.play_state_list; specified_timing = update.specified_timing; - if (update.animation->timeline() && update.animation->timeline()->IsViewTimeline()) { scroll_offsets = To<ViewTimeline>(update.animation->timeline())
diff --git a/third_party/blink/renderer/core/animation/css/css_timing_data.cc b/third_party/blink/renderer/core/animation/css/css_timing_data.cc index 8d17847..d506f22 100644 --- a/third_party/blink/renderer/core/animation/css/css_timing_data.cc +++ b/third_party/blink/renderer/core/animation/css/css_timing_data.cc
@@ -10,8 +10,6 @@ delay_start_list_.push_back(InitialDelayStart()); delay_end_list_.push_back(InitialDelayEnd()); duration_list_.push_back(InitialDuration()); - range_start_list_.push_back(InitialRangeStart()); - range_end_list_.push_back(InitialRangeEnd()); timing_function_list_.push_back(InitialTimingFunction()); } @@ -28,8 +26,6 @@ ? absl::make_optional( ANIMATION_TIME_DELTA_FROM_SECONDS(duration.value())) : absl::nullopt; - timing.range_start = GetRepeated(range_start_list_, index); - timing.range_end = GetRepeated(range_end_list_, index); timing.timing_function = GetRepeated(timing_function_list_, index); timing.AssertValid(); return timing; @@ -43,12 +39,6 @@ return false; if (duration_list_ != other.duration_list_) return false; - if (range_start_list_ != other.range_start_list_) { - return false; - } - if (range_end_list_ != other.range_end_list_) { - return false; - } if (timing_function_list_.size() != other.timing_function_list_.size()) return false;
diff --git a/third_party/blink/renderer/core/animation/css/css_timing_data.h b/third_party/blink/renderer/core/animation/css/css_timing_data.h index 3d3d2101..65fa20a 100644 --- a/third_party/blink/renderer/core/animation/css/css_timing_data.h +++ b/third_party/blink/renderer/core/animation/css/css_timing_data.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_CSS_TIMING_DATA_H_ #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/animation/timing.h" #include "third_party/blink/renderer/platform/animation/timing_function.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -28,12 +29,6 @@ const Vector<absl::optional<double>>& DurationList() const { return duration_list_; } - const Vector<absl::optional<Timing::TimelineOffset>>& RangeStartList() const { - return range_start_list_; - } - const Vector<absl::optional<Timing::TimelineOffset>>& RangeEndList() const { - return range_end_list_; - } const Vector<scoped_refptr<TimingFunction>>& TimingFunctionList() const { return timing_function_list_; } @@ -41,12 +36,6 @@ Vector<Timing::Delay>& DelayStartList() { return delay_start_list_; } Vector<Timing::Delay>& DelayEndList() { return delay_end_list_; } Vector<absl::optional<double>>& DurationList() { return duration_list_; } - Vector<absl::optional<Timing::TimelineOffset>>& RangeStartList() { - return range_start_list_; - } - Vector<absl::optional<Timing::TimelineOffset>>& RangeEndList() { - return range_end_list_; - } Vector<scoped_refptr<TimingFunction>>& TimingFunctionList() { return timing_function_list_; } @@ -54,12 +43,6 @@ static Timing::Delay InitialDelayStart() { return Timing::Delay(); } static Timing::Delay InitialDelayEnd() { return Timing::Delay(); } static absl::optional<double> InitialDuration() { return 0; } - static absl::optional<Timing::TimelineOffset> InitialRangeStart() { - return absl::nullopt; - } - static absl::optional<Timing::TimelineOffset> InitialRangeEnd() { - return absl::nullopt; - } static scoped_refptr<TimingFunction> InitialTimingFunction() { return CubicBezierTimingFunction::Preset( CubicBezierTimingFunction::EaseType::EASE); @@ -81,8 +64,6 @@ Vector<Timing::Delay> delay_start_list_; Vector<Timing::Delay> delay_end_list_; Vector<absl::optional<double>> duration_list_; - Vector<absl::optional<Timing::TimelineOffset>> range_start_list_; - Vector<absl::optional<Timing::TimelineOffset>> range_end_list_; Vector<scoped_refptr<TimingFunction>> timing_function_list_; };
diff --git a/third_party/blink/renderer/core/animation/effect_timing.idl b/third_party/blink/renderer/core/animation/effect_timing.idl index dc304644..8742513a 100644 --- a/third_party/blink/renderer/core/animation/effect_timing.idl +++ b/third_party/blink/renderer/core/animation/effect_timing.idl
@@ -6,18 +6,10 @@ enum FillMode { "none", "forwards", "backwards", "both", "auto" }; enum PlaybackDirection { "normal", "reverse", "alternate", "alternate-reverse" }; -enum TimelineRange { "none", "cover", "contain", "enter", "exit" }; - -dictionary TimelineRangeOffset { - TimelineRange rangeName; - CSSNumericValue offset; -}; dictionary EffectTiming { (double or CSSNumericValue) delay = 0; (double or CSSNumericValue) endDelay = 0; - (DOMString or TimelineRangeOffset) rangeStart = "auto"; - (DOMString or TimelineRangeOffset) rangeEnd = "auto"; FillMode fill = "auto"; double iterationStart = 0.0; unrestricted double iterations = 1.0;
diff --git a/third_party/blink/renderer/core/animation/keyframe_animation_options.idl b/third_party/blink/renderer/core/animation/keyframe_animation_options.idl index e797ac6c..89e8a74 100644 --- a/third_party/blink/renderer/core/animation/keyframe_animation_options.idl +++ b/third_party/blink/renderer/core/animation/keyframe_animation_options.idl
@@ -4,7 +4,19 @@ // https://w3.org/TR/web-animations-1/#dictdef-keyframeanimationoptions +// TODO(kevers): Add scroll-animations-1 link once range(Start|End) are fully +// speced. + +enum TimelineRange { "none", "cover", "contain", "enter", "exit" }; + +dictionary TimelineRangeOffset { + TimelineRange rangeName; + CSSNumericValue offset; +}; + dictionary KeyframeAnimationOptions : KeyframeEffectOptions { DOMString id = ""; AnimationTimeline? timeline; + (DOMString or TimelineRangeOffset) rangeStart = "auto"; + (DOMString or TimelineRangeOffset) rangeEnd = "auto"; };
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect.cc b/third_party/blink/renderer/core/animation/keyframe_effect.cc index db91d1ff..093a047 100644 --- a/third_party/blink/renderer/core/animation/keyframe_effect.cc +++ b/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -672,9 +672,11 @@ } AnimationTimeDelta KeyframeEffect::IntrinsicIterationDuration() const { - if (GetAnimation() && GetAnimation()->timeline()) { - return GetAnimation()->timeline()->CalculateIntrinsicIterationDuration( - timing_); + if (auto* animation = GetAnimation()) { + auto* timeline = animation->timeline(); + if (timeline) { + return timeline->CalculateIntrinsicIterationDuration(animation, timing_); + } } return AnimationTimeDelta(); }
diff --git a/third_party/blink/renderer/core/animation/optional_effect_timing.idl b/third_party/blink/renderer/core/animation/optional_effect_timing.idl index fa3a1e14..0164badc 100644 --- a/third_party/blink/renderer/core/animation/optional_effect_timing.idl +++ b/third_party/blink/renderer/core/animation/optional_effect_timing.idl
@@ -7,8 +7,6 @@ dictionary OptionalEffectTiming { (double or CSSNumericValue) delay; (double or CSSNumericValue) endDelay; - (DOMString or TimelineRangeOffset) rangeStart; - (DOMString or TimelineRangeOffset) rangeEnd; FillMode fill; double iterationStart; unrestricted double iterations;
diff --git a/third_party/blink/renderer/core/animation/scroll_timeline.cc b/third_party/blink/renderer/core/animation/scroll_timeline.cc index ae715f3..e7a4d1d 100644 --- a/third_party/blink/renderer/core/animation/scroll_timeline.cc +++ b/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -224,6 +224,7 @@ } AnimationTimeDelta ScrollTimeline::CalculateIntrinsicIterationDuration( + const Animation* animation, const Timing& timing) { absl::optional<AnimationTimeDelta> duration = GetDuration();
diff --git a/third_party/blink/renderer/core/animation/scroll_timeline.h b/third_party/blink/renderer/core/animation/scroll_timeline.h index 7212d105..e85d93e 100644 --- a/third_party/blink/renderer/core/animation/scroll_timeline.h +++ b/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -74,6 +74,7 @@ bool IsActive() const override; absl::optional<base::TimeDelta> InitialStartTimeForAnimations() override; AnimationTimeDelta CalculateIntrinsicIterationDuration( + const Animation*, const Timing&) override; AnimationTimeDelta ZeroTime() override { return AnimationTimeDelta(); }
diff --git a/third_party/blink/renderer/core/animation/timeline_offset.cc b/third_party/blink/renderer/core/animation/timeline_offset.cc new file mode 100644 index 0000000..0de42dd --- /dev/null +++ b/third_party/blink/renderer/core/animation/timeline_offset.cc
@@ -0,0 +1,24 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/animation/timeline_offset.h" + +#include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h" +#include "third_party/blink/renderer/core/css/css_value_list.h" + +namespace blink { + +String TimelineOffset::ToString() const { + if (name == NamedRange::kNone) { + return "auto"; + } + + CSSValueList* list = CSSValueList::CreateSpaceSeparated(); + list->Append(*MakeGarbageCollected<CSSIdentifierValue>(name)); + list->Append(*CSSValue::Create(offset, 1)); + return list->CssText(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/animation/timeline_offset.h b/third_party/blink/renderer/core/animation/timeline_offset.h new file mode 100644 index 0000000..347fc03 --- /dev/null +++ b/third_party/blink/renderer/core/animation/timeline_offset.h
@@ -0,0 +1,35 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_OFFSET_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_OFFSET_H_ + +#include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range.h" +#include "third_party/blink/renderer/platform/geometry/length.h" + +namespace blink { + +struct TimelineOffset { + using NamedRange = V8TimelineRange::Enum; + + TimelineOffset() = default; + TimelineOffset(NamedRange name, Length offset) : name(name), offset(offset) {} + + NamedRange name = NamedRange::kNone; + Length offset = Length::Fixed(); + + bool operator==(const TimelineOffset& other) const { + return name == other.name && offset == other.offset; + } + + bool operator!=(const TimelineOffset& other) const { + return !(*this == other); + } + + String ToString() const; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_TIMELINE_OFFSET_H_
diff --git a/third_party/blink/renderer/core/animation/timing.cc b/third_party/blink/renderer/core/animation/timing.cc index acdda5ba..39dbaf38 100644 --- a/third_party/blink/renderer/core/animation/timing.cc +++ b/third_party/blink/renderer/core/animation/timing.cc
@@ -15,14 +15,6 @@ namespace blink { -namespace { - -Timing::V8TimelineRangeOffset* DefaultBoundary() { - return MakeGarbageCollected<Timing::V8TimelineRangeOffset>("auto"); -} - -} // namespace - String Timing::TimelineRangeNameToString( Timing::TimelineNamedRange range_name) { switch (range_name) { @@ -48,17 +40,6 @@ return MakeGarbageCollected<V8Delay>(AsTimeValue().InMillisecondsF()); } -Timing::V8TimelineRangeOffset* Timing::TimelineOffset::ToV8TimelineRangeOffset() - const { - TimelineRangeOffset* timeline_range = - MakeGarbageCollected<TimelineRangeOffset>(); - timeline_range->setRangeName(name); - const CSSPrimitiveValue* primitive_value = - CSSPrimitiveValue::CreateFromLength(offset, 1); - timeline_range->setOffset(CSSNumericValue::FromCSSValue(*primitive_value)); - return MakeGarbageCollected<V8TimelineRangeOffset>(timeline_range); -} - String Timing::FillModeString(FillMode fill_mode) { switch (fill_mode) { case FillMode::NONE: @@ -120,16 +101,6 @@ // Specified values used here so that inputs match outputs for JS API calls effect_timing->setDelay(start_delay.ToV8Delay()); effect_timing->setEndDelay(end_delay.ToV8Delay()); - if (range_start) { - effect_timing->setRangeStart(range_start->ToV8TimelineRangeOffset()); - } else { - effect_timing->setRangeStart(DefaultBoundary()); - } - if (range_end) { - effect_timing->setRangeEnd(range_end->ToV8TimelineRangeOffset()); - } else { - effect_timing->setRangeEnd(DefaultBoundary()); - } effect_timing->setFill(FillModeString(fill_mode)); effect_timing->setIterationStart(iteration_start); effect_timing->setIterations(iteration_count);
diff --git a/third_party/blink/renderer/core/animation/timing.h b/third_party/blink/renderer/core/animation/timing.h index 94dac0f..7bb403e 100644 --- a/third_party/blink/renderer/core/animation/timing.h +++ b/third_party/blink/renderer/core/animation/timing.h
@@ -94,27 +94,6 @@ using V8TimelineRangeOffset = V8UnionStringOrTimelineRangeOffset; using TimelineNamedRange = V8TimelineRange::Enum; - struct TimelineOffset { - TimelineOffset() = default; - TimelineOffset(TimelineNamedRange name, Length offset) - : name(name), offset(offset) {} - - V8TimelineRangeOffset* ToV8TimelineRangeOffset() const; - - void UpdateOffset(); - - TimelineNamedRange name = TimelineNamedRange::kNone; - Length offset = Length::Fixed(); - - bool operator==(const TimelineOffset& other) const { - return name == other.name && offset == other.offset; - } - - bool operator!=(const TimelineOffset& other) const { - return !(*this == other); - } - }; - // Delay can be directly expressed as time delays or calculated based on a // position on a view timeline. As part of the normalization process, a // timeline offsets are converted to time-based delays. @@ -171,7 +150,6 @@ bool operator==(const Timing& other) const { return start_delay == other.start_delay && end_delay == other.end_delay && - range_start == other.range_start && range_end == other.range_end && fill_mode == other.fill_mode && iteration_start == other.iteration_start && iteration_count == other.iteration_count && @@ -201,8 +179,6 @@ // TODO(crbug.com/1216527): Support CSSNumberish delays Delay start_delay; Delay end_delay; - absl::optional<TimelineOffset> range_start; - absl::optional<TimelineOffset> range_end; FillMode fill_mode = FillMode::AUTO; double iteration_start = 0; double iteration_count = 1;
diff --git a/third_party/blink/renderer/core/animation/timing_input.cc b/third_party/blink/renderer/core/animation/timing_input.cc index ee452d5..783c2ca 100644 --- a/third_party/blink/renderer/core/animation/timing_input.cc +++ b/third_party/blink/renderer/core/animation/timing_input.cc
@@ -47,71 +47,6 @@ return absl::nullopt; } -Timing::TimelineOffset ConvertRangeOffset( - const Timing::V8TimelineRangeOffset* range_offset, - double default_percent, - ExceptionState& exception_state) { - Timing::TimelineOffset result; - if (range_offset->IsString()) { - // TODO(kevers): Implement once we have CSS support for animation-range. - result.name = Timing::TimelineNamedRange::kNone; - result.offset = Length(default_percent, Length::Type::kPercent); - } else { - TimelineRangeOffset* value = range_offset->GetAsTimelineRangeOffset(); - result.name = value->hasRangeName() ? value->rangeName().AsEnum() - : Timing::TimelineNamedRange::kNone; - if (value->hasOffset()) { - CSSNumericValue* offset = value->offset(); - const CSSPrimitiveValue* css_value = - DynamicTo<CSSPrimitiveValue>(offset->ToCSSValue()); - - if (!css_value || (!css_value->IsPx() && !css_value->IsPercentage() && - !css_value->IsCalculatedPercentageWithLength())) { - exception_state.ThrowTypeError( - "CSSNumericValue must be a length or percentage for animation " - "range."); - return result; - } - - if (css_value->IsPx()) { - result.offset = Length::Fixed(css_value->GetDoubleValue()); - } else if (css_value->IsPercentage()) { - result.offset = Length::Percent(css_value->GetDoubleValue()); - } else { - // TODO(kevers): Resolve if we need to handle style-dependent lengths - // such as em. If so, what is the reference element for resolving the - // style? - DCHECK(css_value->IsCalculatedPercentageWithLength()); - CSSLengthArray length_array; - css_value->AccumulateLengthArray(length_array); - double percent = 0; - double px = 0; - for (wtf_size_t i = 0; i < length_array.values.size(); ++i) { - double array_value = length_array.values[i]; - if (array_value == 0) { - continue; - } - if (i == CSSPrimitiveValue::kUnitTypePercentage) { - percent = array_value; - } else if (i == CSSPrimitiveValue::kUnitTypePixels) { - px = array_value; - } else { - exception_state.ThrowDOMException( - DOMExceptionCode::kNotSupportedError, - "Unsupported range offset"); - return result; - } - } - result.offset = Length(CalculationValue::Create( - PixelsAndPercent(px, percent), Length::ValueRange::kAll)); - } - } else { - result.offset = Length::Percent(default_percent); - } - } - return result; -} - Timing::Delay ConvertDelay(const Timing::V8Delay* delay, double default_percent, ExceptionState& exception_state) { @@ -290,24 +225,6 @@ ConvertDelay(input->endDelay(), 100, exception_state)); timing.SetTimingOverride(Timing::kOverrideEndDelay); } - if (input->hasRangeStart()) { - Timing::TimelineOffset timeline_offset = - ConvertRangeOffset(input->rangeStart(), 0, exception_state); - if (!timing.range_start || timing.range_start.value() != timeline_offset) { - timing.range_start = timeline_offset; - changed = true; - } - timing.SetTimingOverride(Timing::kOverrideRangeStart); - } - if (input->hasRangeEnd()) { - Timing::TimelineOffset timeline_offset = - ConvertRangeOffset(input->rangeEnd(), 100, exception_state); - if (!timing.range_end || timing.range_end.value() != timeline_offset) { - timing.range_end = timeline_offset; - changed = true; - } - timing.SetTimingOverride(Timing::kOverrideRangeEnd); - } if (input->hasFill()) { changed |= UpdateValueIfChanged(timing.fill_mode, Timing::StringToFillMode(input->fill()));
diff --git a/third_party/blink/renderer/core/animation/timing_input_test.cc b/third_party/blink/renderer/core/animation/timing_input_test.cc index 6a1abf9..d9e6ef8b 100644 --- a/third_party/blink/renderer/core/animation/timing_input_test.cc +++ b/third_party/blink/renderer/core/animation/timing_input_test.cc
@@ -22,19 +22,6 @@ using animation_test_helpers::SetV8ObjectPropertyAsNumber; using animation_test_helpers::SetV8ObjectPropertyAsString; -bool TimelineRangeEquals(const absl::optional<Timing::TimelineOffset>& offset, - Timing::TimelineNamedRange rangeName, - double percent_offset, - double pixel_offset = 0) { - if (!offset) { - return false; - } - PixelsAndPercent pixels_and_percent = offset->offset.GetPixelsAndPercent(); - return offset->name == rangeName && - std::abs(pixels_and_percent.pixels - pixel_offset) < 1e-6 && - std::abs(pixels_and_percent.percent - percent_offset) < 1e-6; -} - class AnimationTimingInputTest : public testing::Test { public: Timing ApplyTimingInputNumber(v8::Isolate*, @@ -47,9 +34,6 @@ String timing_property_value, bool& timing_conversion_success, bool is_keyframeeffectoptions = true); - Timing ApplyTimingInputRange(String timing_property, - absl::optional<String> range, - absl::optional<double> offset); private: void SetUp() override { page_holder_ = std::make_unique<DummyPageHolder>(); } @@ -148,41 +132,6 @@ return result; } -Timing AnimationTimingInputTest::ApplyTimingInputRange( - String timing_property, - absl::optional<String> name, - absl::optional<double> offset) { - KeyframeEffectOptions* keyframe_effect_options = - MakeGarbageCollected<KeyframeEffectOptions>(); - - TimelineRangeOffset* timeline_range_offset = TimelineRangeOffset::Create(); - if (name) { - timeline_range_offset->setRangeName(name.value()); - } - if (offset) { - timeline_range_offset->setOffset(CSSUnitValues::percent(offset.value())); - } - - Timing::V8TimelineRangeOffset* range_offset = - MakeGarbageCollected<Timing::V8TimelineRangeOffset>( - timeline_range_offset); - if (timing_property == "rangeStart") { - keyframe_effect_options->setRangeStart(range_offset); - } else { - keyframe_effect_options->setRangeEnd(range_offset); - } - - auto* options = - MakeGarbageCollected<V8UnionKeyframeEffectOptionsOrUnrestrictedDouble>( - keyframe_effect_options); - - DummyExceptionStateForTesting exception_state; - Timing result = TimingInput::Convert(options, GetDocument(), exception_state); - if (exception_state.HadException()) - return Timing(); - return result; -} - TEST_F(AnimationTimingInputTest, TimingInputStartDelay) { V8TestingScope scope; bool did_success; @@ -228,32 +177,6 @@ EXPECT_FALSE(did_success); } -TEST_F(AnimationTimingInputTest, TimingInputRangeStart) { - V8TestingScope scope; - Timing timing = ApplyTimingInputRange("rangeStart", "enter", 0); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kEnter, 0)); - timing = ApplyTimingInputRange("rangeStart", "exit", -50); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kExit, -50)); - - timing = ApplyTimingInputRange("rangeStart", "cover", 50.5); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kCover, 50.5)); - - timing = ApplyTimingInputRange("rangeStart", "contain", 110); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kContain, 110)); - - timing = ApplyTimingInputRange("rangeStart", "contain", absl::nullopt); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kContain, 0)); - - timing = ApplyTimingInputRange("rangeStart", absl::nullopt, 10); - EXPECT_TRUE(TimelineRangeEquals(timing.range_start, - Timing::TimelineNamedRange::kNone, 10)); -} - TEST_F(AnimationTimingInputTest, TimingInputStartDelayKeyframeAnimationOptions) { V8TestingScope scope; @@ -305,13 +228,6 @@ .InSecondsF()); } -TEST_F(AnimationTimingInputTest, TimingInputRangeEnd) { - V8TestingScope scope; - Timing timing = ApplyTimingInputRange("rangeEnd", "enter", absl::nullopt); - EXPECT_TRUE(TimelineRangeEquals(timing.range_end, - Timing::TimelineNamedRange::kEnter, 100)); -} - TEST_F(AnimationTimingInputTest, TimingInputFillMode) { V8TestingScope scope; Timing::FillMode default_fill_mode = Timing::FillMode::AUTO;
diff --git a/third_party/blink/renderer/core/animation/view_timeline.cc b/third_party/blink/renderer/core/animation/view_timeline.cc index b3b0f9ef..ea993208 100644 --- a/third_party/blink/renderer/core/animation/view_timeline.cc +++ b/third_party/blink/renderer/core/animation/view_timeline.cc
@@ -250,6 +250,7 @@ } AnimationTimeDelta ViewTimeline::CalculateIntrinsicIterationDuration( + const Animation* animation, const Timing& timing) { absl::optional<AnimationTimeDelta> duration = GetDuration(); @@ -257,12 +258,12 @@ if (duration && timing.iteration_count > 0) { double active_interval = 1; - double start = - ToFractionalOffset(timing.range_start.value_or(Timing::TimelineOffset( - Timing::TimelineNamedRange::kCover, Length::Percent(0)))); - double end = - ToFractionalOffset(timing.range_end.value_or(Timing::TimelineOffset( - Timing::TimelineNamedRange::kCover, Length::Percent(100)))); + double start = animation->GetRangeStart() + ? ToFractionalOffset(animation->GetRangeStart().value()) + : 0; + double end = animation->GetRangeEnd() + ? ToFractionalOffset(animation->GetRangeEnd().value()) + : 1; // TODO(crbug.com1216527): Delays will also need to be incorporated once we // support % delays. @@ -342,16 +343,16 @@ if (!IsActive()) return nullptr; - Timing::TimelineOffset range_start; - Timing::TimelineOffset range_end; + TimelineOffset range_start; + TimelineOffset range_end; if (rangeName == "cover") { - range_start.name = Timing::TimelineNamedRange::kCover; + range_start.name = TimelineOffset::NamedRange::kCover; } else if (rangeName == "contain") { - range_start.name = Timing::TimelineNamedRange::kContain; + range_start.name = TimelineOffset::NamedRange::kContain; } else if (rangeName == "enter") { - range_start.name = Timing::TimelineNamedRange::kEnter; + range_start.name = TimelineOffset::NamedRange::kEnter; } else if (rangeName == "exit") { - range_start.name = Timing::TimelineNamedRange::kExit; + range_start.name = TimelineOffset::NamedRange::kExit; } else { return nullptr; } @@ -386,7 +387,7 @@ } double ViewTimeline::ToFractionalOffset( - const Timing::TimelineOffset& timeline_offset) const { + const TimelineOffset& timeline_offset) const { // https://drafts.csswg.org/scroll-animations-1/#view-timelines-ranges double align_subject_start_view_end = target_offset_ - viewport_size_ + end_side_inset_; @@ -404,8 +405,8 @@ double range_start = 0; double range_end = 0; switch (timeline_offset.name) { - case Timing::TimelineNamedRange::kNone: - case Timing::TimelineNamedRange::kCover: + case TimelineOffset::NamedRange::kNone: + case TimelineOffset::NamedRange::kCover: // Represents the full range of the view progress timeline: // 0% progress represents the position at which the start border edge of // the element’s principal box coincides with the end edge of its view @@ -417,7 +418,7 @@ range_end = align_subject_end_view_start; break; - case Timing::TimelineNamedRange::kContain: + case TimelineOffset::NamedRange::kContain: // Represents the range during which the principal box is either fully // contained by, or fully covers, its view progress visibility range // within the scrollport. @@ -437,7 +438,7 @@ std::max(align_subject_start_view_start, align_subject_end_view_end); break; - case Timing::TimelineNamedRange::kEnter: + case TimelineOffset::NamedRange::kEnter: // Represents the range during which the principal box is entering the // view progress visibility range. // 0% is equivalent to 0% of the cover range. @@ -447,7 +448,7 @@ std::min(align_subject_start_view_start, align_subject_end_view_end); break; - case Timing::TimelineNamedRange::kExit: + case TimelineOffset::NamedRange::kExit: // Represents the range during which the principal box is exiting the view // progress visibility range. // 0% is equivalent to 100% of the contain range. @@ -468,17 +469,18 @@ } AnimationTimeline::TimeDelayPair ViewTimeline::TimelineOffsetsToTimeDelays( - const Timing& timing) const { + const Animation* animation) const { absl::optional<AnimationTimeDelta> duration = GetDuration(); if (!duration) return std::make_pair(AnimationTimeDelta(), AnimationTimeDelta()); - double start_fraction = - ToFractionalOffset(timing.range_start.value_or(Timing::TimelineOffset( - Timing::TimelineNamedRange::kCover, Length::Percent(0)))); + animation->GetRangeStart() + ? ToFractionalOffset(animation->GetRangeStart().value()) + : 0; double end_fraction = - ToFractionalOffset(timing.range_end.value_or(Timing::TimelineOffset( - Timing::TimelineNamedRange::kCover, Length::Percent(100)))); + animation->GetRangeEnd() + ? ToFractionalOffset(animation->GetRangeEnd().value()) + : 1; return std::make_pair(start_fraction * duration.value(), (1 - end_fraction) * duration.value()); }
diff --git a/third_party/blink/renderer/core/animation/view_timeline.h b/third_party/blink/renderer/core/animation/view_timeline.h index 2ede83b..23e4da0 100644 --- a/third_party/blink/renderer/core/animation/view_timeline.h +++ b/third_party/blink/renderer/core/animation/view_timeline.h
@@ -53,6 +53,7 @@ CSSNumericValue* getCurrentTime(const String& rangeName) override; AnimationTimeDelta CalculateIntrinsicIterationDuration( + const Animation*, const Timing&) override; // IDL API implementation. @@ -60,11 +61,10 @@ // Converts a delay that is expressed as a (phase,percentage) pair to // a fractional offset. - double ToFractionalOffset( - const Timing::TimelineOffset& timeline_offset) const; + double ToFractionalOffset(const TimelineOffset& timeline_offset) const; AnimationTimeline::TimeDelayPair TimelineOffsetsToTimeDelays( - const Timing& timing) const override; + const Animation* animation) const override; CSSNumericValue* startOffset() const; CSSNumericValue* endOffset() const;
diff --git a/third_party/blink/renderer/core/css/css_counter_value.cc b/third_party/blink/renderer/core/css/css_counter_value.cc index 265211e..7d5e0b6 100644 --- a/third_party/blink/renderer/core/css/css_counter_value.cc +++ b/third_party/blink/renderer/core/css/css_counter_value.cc
@@ -34,6 +34,15 @@ return result.ReleaseString(); } +const CSSCounterValue& CSSCounterValue::PopulateWithTreeScope( + const TreeScope* tree_scope) const { + DCHECK(!IsScopedValue()); + return *MakeGarbageCollected<CSSCounterValue>( + &To<CSSCustomIdentValue>(identifier_->EnsureScopedValue(tree_scope)), + &To<CSSCustomIdentValue>(list_style_->EnsureScopedValue(tree_scope)), + separator_); +} + void CSSCounterValue::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(identifier_); visitor->Trace(list_style_);
diff --git a/third_party/blink/renderer/core/css/css_counter_value.h b/third_party/blink/renderer/core/css/css_counter_value.h index ffd2314..70db3700 100644 --- a/third_party/blink/renderer/core/css/css_counter_value.h +++ b/third_party/blink/renderer/core/css/css_counter_value.h
@@ -33,31 +33,43 @@ class CSSCounterValue : public CSSValue { public: - CSSCounterValue(CSSCustomIdentValue* identifier, - CSSCustomIdentValue* list_style, - CSSStringValue* separator) + CSSCounterValue(const CSSCustomIdentValue* identifier, + const CSSCustomIdentValue* list_style, + const CSSStringValue* separator) : CSSValue(kCounterClass), identifier_(identifier), list_style_(list_style), - separator_(separator) {} + separator_(separator) { + // There's no way to define a counter() function value where the identifiers + // are associated with different tree scopes. + DCHECK_EQ(identifier->IsScopedValue(), list_style->IsScopedValue()); + DCHECK_EQ(identifier->GetTreeScope(), list_style->GetTreeScope()); + needs_tree_scope_population_ = !list_style->IsScopedValue(); + } const String& Identifier() const { return identifier_->Value(); } const AtomicString& ListStyle() const { return list_style_->Value(); } const String& Separator() const { return separator_->Value(); } + const TreeScope* GetTreeScope() const { return list_style_->GetTreeScope(); } bool Equals(const CSSCounterValue& other) const { return Identifier() == other.Identifier() && - ListStyle() == other.ListStyle() && Separator() == other.Separator(); + ListStyle() == other.ListStyle() && + Separator() == other.Separator() && + IsScopedValue() == other.IsScopedValue() && + GetTreeScope() == other.GetTreeScope(); } + const CSSCounterValue& PopulateWithTreeScope(const TreeScope*) const; + String CustomCSSText() const; void TraceAfterDispatch(blink::Visitor*) const; private: - Member<CSSCustomIdentValue> identifier_; // string - Member<CSSCustomIdentValue> list_style_; // ident - Member<CSSStringValue> separator_; // string + Member<const CSSCustomIdentValue> identifier_; // string + Member<const CSSCustomIdentValue> list_style_; // ident + Member<const CSSStringValue> separator_; // string }; } // namespace cssvalue
diff --git a/third_party/blink/renderer/core/css/css_global_rule_set.cc b/third_party/blink/renderer/core/css/css_global_rule_set.cc index e5c2ef0..e318608 100644 --- a/third_party/blink/renderer/core/css/css_global_rule_set.cc +++ b/third_party/blink/renderer/core/css/css_global_rule_set.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/css/rule_set.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" namespace blink { @@ -33,6 +34,23 @@ } } +void CSSGlobalRuleSet::UpdateDocumentRulesSelectorsRuleSet(Document& document) { + MarkDirty(); + document_rules_selectors_rule_set_ = nullptr; + const HeapVector<Member<StyleRule>>& document_rules_selectors = + DocumentSpeculationRules::From(document).selectors(); + if (document_rules_selectors.empty()) { + return; + } + document_rules_selectors_rule_set_ = MakeGarbageCollected<RuleSet>(); + MediaQueryEvaluator* medium = + MakeGarbageCollected<MediaQueryEvaluator>(document.GetFrame()); + for (StyleRule* selector : document_rules_selectors) { + document_rules_selectors_rule_set_->AddStyleRule(selector, *medium, + kRuleHasNoSpecialState); + } +} + void CSSGlobalRuleSet::Update(Document& document) { if (!is_dirty_) { return; @@ -52,18 +70,24 @@ features_.Merge(watched_selectors_rule_set_->Features()); } + if (document_rules_selectors_rule_set_) { + features_.Merge(document_rules_selectors_rule_set_->Features()); + } + document.GetStyleEngine().CollectFeaturesTo(features_); } void CSSGlobalRuleSet::Dispose() { features_.Clear(); watched_selectors_rule_set_ = nullptr; + document_rules_selectors_rule_set_ = nullptr; has_fullscreen_ua_style_ = false; is_dirty_ = true; } void CSSGlobalRuleSet::Trace(Visitor* visitor) const { visitor->Trace(watched_selectors_rule_set_); + visitor->Trace(document_rules_selectors_rule_set_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_global_rule_set.h b/third_party/blink/renderer/core/css/css_global_rule_set.h index e5987cd..14dce33 100644 --- a/third_party/blink/renderer/core/css/css_global_rule_set.h +++ b/third_party/blink/renderer/core/css/css_global_rule_set.h
@@ -29,6 +29,7 @@ void Dispose(); void InitWatchedSelectorsRuleSet(Document&); + void UpdateDocumentRulesSelectorsRuleSet(Document&); void MarkDirty() { is_dirty_ = true; } bool IsDirty() const { return is_dirty_; } void Update(Document&); @@ -37,6 +38,9 @@ RuleSet* WatchedSelectorsRuleSet() const { return watched_selectors_rule_set_; } + RuleSet* DocumentRulesSelectorsRuleSet() const { + return document_rules_selectors_rule_set_; + } bool HasFullscreenUAStyle() const { return has_fullscreen_ua_style_; } void Trace(Visitor*) const; @@ -49,6 +53,10 @@ // Rules injected from extensions. Member<RuleSet> watched_selectors_rule_set_; + // Rules extracted from CSS selector document rule predicates in speculation + // rules. + Member<RuleSet> document_rules_selectors_rule_set_; + bool has_fullscreen_ua_style_ = false; bool is_dirty_ = true; };
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h index ef74bed1..e17e376 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h +++ b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
@@ -33,6 +33,7 @@ #include "base/notreached.h" #include "cc/input/scroll_snap_data.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/animation/timing.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" @@ -1736,19 +1737,19 @@ template <> inline CSSIdentifierValue::CSSIdentifierValue( - Timing::TimelineNamedRange named_range) + TimelineOffset::NamedRange named_range) : CSSValue(kIdentifierClass) { switch (named_range) { - case Timing::TimelineNamedRange::kCover: + case TimelineOffset::NamedRange::kCover: value_id_ = CSSValueID::kCover; break; - case Timing::TimelineNamedRange::kContain: + case TimelineOffset::NamedRange::kContain: value_id_ = CSSValueID::kContain; break; - case Timing::TimelineNamedRange::kEnter: + case TimelineOffset::NamedRange::kEnter: value_id_ = CSSValueID::kEnter; break; - case Timing::TimelineNamedRange::kExit: + case TimelineOffset::NamedRange::kExit: value_id_ = CSSValueID::kExit; break; default: @@ -1759,21 +1760,21 @@ } template <> -inline Timing::TimelineNamedRange CSSIdentifierValue::ConvertTo() const { +inline TimelineOffset::NamedRange CSSIdentifierValue::ConvertTo() const { switch (GetValueID()) { case CSSValueID::kCover: - return Timing::TimelineNamedRange::kCover; + return TimelineOffset::NamedRange::kCover; case CSSValueID::kContain: - return Timing::TimelineNamedRange::kContain; + return TimelineOffset::NamedRange::kContain; case CSSValueID::kEnter: - return Timing::TimelineNamedRange::kEnter; + return TimelineOffset::NamedRange::kEnter; case CSSValueID::kExit: - return Timing::TimelineNamedRange::kExit; + return TimelineOffset::NamedRange::kExit; default: break; } NOTREACHED(); - return Timing::TimelineNamedRange::kCover; + return TimelineOffset::NamedRange::kCover; } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 782b2a1..76c7fbd 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -1082,7 +1082,6 @@ valid_for_first_line: true, valid_for_cue: true, valid_for_marker: true, - tree_scoped_value: true, valid_for_formatted_text: true, valid_for_formatted_text_run: true, }, @@ -1607,7 +1606,6 @@ keywords: ["none"], typedom_types: ["Keyword"], runtime_flag: "CSSAnchorPositioning", - tree_scoped_value: true, }, { name: "anchor-scroll", @@ -1622,7 +1620,6 @@ keywords: ["none"], typedom_types: ["Keyword"], runtime_flag: "CSSAnchorPositioning", - tree_scoped_value: true, }, { name: "aspect-ratio", @@ -2577,7 +2574,6 @@ computed_style_custom_functions: ["getter"], style_builder_custom_functions: ["initial", "inherit", "value"], valid_for_marker: true, - tree_scoped_value: true, supports_incremental_style: true, }, { @@ -3990,7 +3986,6 @@ keywords: ["none"], typedom_types: ["Keyword"], runtime_flag: "CSSAnchorPositioning", - tree_scoped_value: true, }, { name: "quotes", @@ -4971,6 +4966,16 @@ valid_for_position_fallback: true, }, { + name: "top-layer", + runtime_flag: "CSSTopLayerForTransitions", + property_methods: ["CSSValueFromComputedStyleInternal"], + field_group: "*", + field_template: "keyword", + keywords: ["none", "browser"], + default_value: "none", + typedom_types: ["Keyword"], + }, + { name: "touch-action", property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"], field_group: "*",
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc index 92e7c1c..a18ae46 100644 --- a/third_party/blink/renderer/core/css/css_value.cc +++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -462,10 +462,15 @@ const CSSValue& CSSValue::PopulateWithTreeScope( const TreeScope* tree_scope) const { switch (GetClassType()) { + case kCounterClass: + return To<cssvalue::CSSCounterValue>(this)->PopulateWithTreeScope( + tree_scope); case kCustomIdentClass: return To<CSSCustomIdentValue>(this)->PopulateWithTreeScope(tree_scope); case kMathFunctionClass: return To<CSSMathFunctionValue>(this)->PopulateWithTreeScope(tree_scope); + case kValueListClass: + return To<CSSValueList>(this)->PopulateWithTreeScope(tree_scope); default: NOTREACHED(); return *this;
diff --git a/third_party/blink/renderer/core/css/css_value_list.cc b/third_party/blink/renderer/core/css/css_value_list.cc index 73a3e16..a16cb9690 100644 --- a/third_party/blink/renderer/core/css/css_value_list.cc +++ b/third_party/blink/renderer/core/css/css_value_list.cc
@@ -41,6 +41,17 @@ value_list_separator_ = list_separator; } +void CSSValueList::Append(const CSSValue& value) { + values_.push_back(value); + // Note: this will be changed if we need to support tree scoped names and + // references in any subclass. + // TODO(crbug.com/1410362): Make CSSValueList immutable so that we don't need + // to track it here. + if (IsBaseValueList() && !value.IsScopedValue()) { + needs_tree_scope_population_ = true; + } +} + bool CSSValueList::RemoveAll(const CSSValue& val) { bool found = false; for (int index = values_.size() - 1; index >= 0; --index) { @@ -50,6 +61,19 @@ found = true; } } + // Note: this will be changed if we need to support tree scoped names and + // references in any subclass. + // TODO(crbug.com/1410362): Make CSSValueList immutable so that we don't need + // to track it here. + if (IsBaseValueList()) { + needs_tree_scope_population_ = false; + for (const CSSValue* value : values_) { + if (!value->IsScopedValue()) { + needs_tree_scope_population_ = true; + break; + } + } + } return found; } @@ -78,9 +102,38 @@ NOTREACHED(); } new_list->values_ = values_; + new_list->needs_tree_scope_population_ = needs_tree_scope_population_; return new_list; } +const CSSValueList& CSSValueList::PopulateWithTreeScope( + const TreeScope* tree_scope) const { + // Note: this will be changed if any subclass also involves values that need + // TreeScope population, as in that case, we will need to return an instance + // of the subclass. + DCHECK(IsBaseValueList()); + DCHECK(!IsScopedValue()); + CSSValueList* new_list = nullptr; + switch (value_list_separator_) { + case kSpaceSeparator: + new_list = CreateSpaceSeparated(); + break; + case kCommaSeparator: + new_list = CreateCommaSeparated(); + break; + case kSlashSeparator: + new_list = CreateSlashSeparated(); + break; + default: + NOTREACHED(); + } + new_list->values_.ReserveInitialCapacity(values_.size()); + for (const CSSValue* value : values_) { + new_list->values_.push_back(&value->EnsureScopedValue(tree_scope)); + } + return *new_list; +} + String CSSValueList::CustomCSSText() const { StringView separator; switch (value_list_separator_) {
diff --git a/third_party/blink/renderer/core/css/css_value_list.h b/third_party/blink/renderer/core/css/css_value_list.h index dece23b..610eee8 100644 --- a/third_party/blink/renderer/core/css/css_value_list.h +++ b/third_party/blink/renderer/core/css/css_value_list.h
@@ -62,7 +62,7 @@ const CSSValue& Item(wtf_size_t index) const { return *values_[index]; } const CSSValue& Last() const { return *values_.back(); } - void Append(const CSSValue& value) { values_.push_back(value); } + void Append(const CSSValue& value); bool RemoveAll(const CSSValue&); bool HasValue(const CSSValue&) const; CSSValueList* Copy() const; @@ -70,6 +70,8 @@ String CustomCSSText() const; bool Equals(const CSSValueList&) const; + const CSSValueList& PopulateWithTreeScope(const TreeScope*) const; + bool HasFailedOrCanceledSubresources() const; bool MayContainUrl() const;
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc index e4cfdf6e..bd57b75 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -188,15 +188,16 @@ if (vtt_originating_element) { return nullptr; } - if (scope) { - return scope->ContainingTreeScope() - .GetScopedStyleResolver() - ->GetCascadeLayerMap(); - } // Assume there are no UA cascade layers, so we only check user layers. if (!style_sheet) { return nullptr; } + if (scope) { + DCHECK(scope->ContainingTreeScope().GetScopedStyleResolver()); + return scope->ContainingTreeScope() + .GetScopedStyleResolver() + ->GetCascadeLayerMap(); + } Document* document = style_sheet->OwnerDocument(); if (!document) { return nullptr;
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc index c38a453..236c331a 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -1155,6 +1155,8 @@ value_id == CSSValueID::kUpright; case CSSPropertyID::kTextOverflow: return value_id == CSSValueID::kClip || value_id == CSSValueID::kEllipsis; + case CSSPropertyID::kTopLayer: + return value_id == CSSValueID::kNone || value_id == CSSValueID::kBrowser; case CSSPropertyID::kTextRendering: return value_id == CSSValueID::kAuto || value_id == CSSValueID::kOptimizespeed || @@ -1501,6 +1503,7 @@ CSSPropertyID::kScrollbarWidth, CSSPropertyID::kScrollSnapStop, CSSPropertyID::kOriginTrialTestProperty, + CSSPropertyID::kTopLayer, }}; bool CSSParserFastPaths::IsValidSystemFont(CSSValueID value_id) {
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index 0e0c8c5..0453c00 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -2139,7 +2139,7 @@ } CSSValue* ComputedStyleUtils::ValueForAnimationRangeStart( - const absl::optional<Timing::TimelineOffset>& offset, + const absl::optional<TimelineOffset>& offset, const ComputedStyle& style) { if (!offset.has_value()) { return MakeGarbageCollected<CSSIdentifierValue>(CSSValueID::kAuto); @@ -2151,30 +2151,30 @@ } CSSValue* ComputedStyleUtils::ValueForAnimationRangeStartList( - const CSSTimingData* timing_data, + const CSSAnimationData* animation_data, const ComputedStyle& style) { return CreateAnimationValueList( - timing_data - ? timing_data->RangeStartList() - : Vector<absl::optional< - Timing::TimelineOffset>>{CSSTimingData::InitialRangeStart()}, + animation_data + ? animation_data->RangeStartList() + : Vector<absl::optional<TimelineOffset>>{CSSAnimationData:: + InitialRangeStart()}, &ValueForAnimationRangeStart, style); } CSSValue* ComputedStyleUtils::ValueForAnimationRangeEnd( - const absl::optional<Timing::TimelineOffset>& offset, + const absl::optional<TimelineOffset>& offset, const ComputedStyle& style) { return ValueForAnimationRangeStart(offset, style); } CSSValue* ComputedStyleUtils::ValueForAnimationRangeEndList( - const CSSTimingData* timing_data, + const CSSAnimationData* animation_data, const ComputedStyle& style) { return CreateAnimationValueList( - timing_data - ? timing_data->RangeEndList() - : Vector<absl::optional< - Timing::TimelineOffset>>{CSSTimingData::InitialRangeEnd()}, + animation_data + ? animation_data->RangeEndList() + : Vector<absl::optional<TimelineOffset>>{CSSAnimationData:: + InitialRangeEnd()}, &ValueForAnimationRangeEnd, style); }
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.h b/third_party/blink/renderer/core/css/properties/computed_style_utils.h index 84faec90..a754c08 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.h +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.h
@@ -7,6 +7,7 @@ #include "cc/input/scroll_snap_data.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_border_image_slice_value.h" #include "third_party/blink/renderer/core/css/css_function_value.h" @@ -155,10 +156,10 @@ static CSSValue* ValueForAnimationIterationCount(double iteration_count); static CSSValue* ValueForAnimationPlayState(EAnimPlayState); static CSSValue* ValueForAnimationRangeStart( - const absl::optional<Timing::TimelineOffset>&, + const absl::optional<TimelineOffset>&, const ComputedStyle&); static CSSValue* ValueForAnimationRangeEnd( - const absl::optional<Timing::TimelineOffset>&, + const absl::optional<TimelineOffset>&, const ComputedStyle&); static CSSValue* ValueForAnimationTimingFunction( const scoped_refptr<TimingFunction>&); @@ -171,9 +172,9 @@ static CSSValue* ValueForAnimationFillModeList(const CSSAnimationData*); static CSSValue* ValueForAnimationIterationCountList(const CSSAnimationData*); static CSSValue* ValueForAnimationPlayStateList(const CSSAnimationData*); - static CSSValue* ValueForAnimationRangeStartList(const CSSTimingData*, + static CSSValue* ValueForAnimationRangeStartList(const CSSAnimationData*, const ComputedStyle&); - static CSSValue* ValueForAnimationRangeEndList(const CSSTimingData*, + static CSSValue* ValueForAnimationRangeEndList(const CSSAnimationData*, const ComputedStyle&); static CSSValue* ValueForAnimationTimingFunctionList(const CSSTimingData*); static CSSValue* ValueForAnimationTimelineList(const CSSAnimationData*);
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index ea9aa31..7d33e3d4 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2384,13 +2384,8 @@ void Content::ApplyValue(StyleResolverState& state, const CSSValue& value) const { - NOTREACHED(); -} - -void Content::ApplyValue(StyleResolverState& state, - const ScopedCSSValue& scoped_value) const { + DCHECK(value.IsScopedValue()); ComputedStyleBuilder& builder = state.StyleBuilder(); - const CSSValue& value = scoped_value.GetCSSValue(); if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { DCHECK(identifier_value->GetValueID() == CSSValueID::kNormal || identifier_value->GetValueID() == CSSValueID::kNone); @@ -2415,7 +2410,7 @@ next_content = MakeGarbageCollected<CounterContentData>( AtomicString(counter_value->Identifier()), counter_value->ListStyle(), AtomicString(counter_value->Separator()), - scoped_value.GetTreeScope()); + counter_value->GetTreeScope()); } else if (auto* item_identifier_value = DynamicTo<CSSIdentifierValue>(item.Get())) { QuoteType quote_type; @@ -9588,6 +9583,13 @@ return result_list; } +const CSSValue* TopLayer::CSSValueFromComputedStyleInternal( + const ComputedStyle& style, + const LayoutObject*, + bool allow_visited_style) const { + return CSSIdentifierValue::Create(style.TopLayer()); +} + const CSSValue* WebkitTransformOriginY::ParseSingleValue( CSSParserTokenRange& range, const CSSParserContext& context,
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc index b155dbe..7af84ca 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/memory/values_equivalent.h" +#include "third_party/blink/renderer/core/animation/timeline_offset.h" #include "third_party/blink/renderer/core/css/css_content_distribution_value.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_initial_value.h" @@ -429,13 +430,13 @@ const ComputedStyle& style, const LayoutObject*, bool allow_visited_style) const { - const Vector<absl::optional<Timing::TimelineOffset>>& range_start_list = + const Vector<absl::optional<TimelineOffset>>& range_start_list = style.Animations() ? style.Animations()->RangeStartList() - : Vector<absl::optional<Timing::TimelineOffset>>{ + : Vector<absl::optional<TimelineOffset>>{ CSSAnimationData::InitialRangeStart()}; - const Vector<absl::optional<Timing::TimelineOffset>>& range_end_list = + const Vector<absl::optional<TimelineOffset>>& range_end_list = style.Animations() ? style.Animations()->RangeEndList() - : Vector<absl::optional<Timing::TimelineOffset>>{ + : Vector<absl::optional<TimelineOffset>>{ CSSAnimationData::InitialRangeEnd()}; if (range_start_list.size() != range_end_list.size()) { @@ -445,8 +446,8 @@ auto* outer_list = CSSValueList::CreateCommaSeparated(); for (wtf_size_t i = 0; i < range_start_list.size(); ++i) { - const absl::optional<Timing::TimelineOffset>& start = range_start_list[i]; - const absl::optional<Timing::TimelineOffset>& end = range_end_list[i]; + const absl::optional<TimelineOffset>& start = range_start_list[i]; + const absl::optional<TimelineOffset>& end = range_end_list[i]; // E.g. "enter 0% enter 100%" must be shortened to just "enter". if (start.has_value() && end.has_value() && start->name == end->name && @@ -460,7 +461,7 @@ auto* inner_list = CSSValueList::CreateSpaceSeparated(); inner_list->Append(*ComputedStyleUtils::ValueForAnimationRangeStart( range_start_list[i], style)); - if (end != CSSTimingData::InitialRangeEnd()) { + if (end != CSSAnimationData::InitialRangeEnd()) { inner_list->Append(*ComputedStyleUtils::ValueForAnimationRangeEnd( range_end_list[i], style)); } @@ -3242,11 +3243,17 @@ const Vector<TimelineAxis>& axis_vector) { CSSValueList* list = CSSValueList::CreateCommaSeparated(); - if (name_vector.size() == axis_vector.size()) { - for (wtf_size_t i = 0; i < name_vector.size(); ++i) { - list->Append(*ComputedStyleUtils::SingleValueForTimelineShorthand( - name_vector[i].Get(), axis_vector[i])); - } + if (name_vector.size() != axis_vector.size()) { + return list; + } + if (name_vector.empty()) { + list->Append(*ComputedStyleUtils::SingleValueForTimelineShorthand( + /* name */ nullptr, TimelineAxis::kBlock)); + return list; + } + for (wtf_size_t i = 0; i < name_vector.size(); ++i) { + list->Append(*ComputedStyleUtils::SingleValueForTimelineShorthand( + name_vector[i].Get(), axis_vector[i])); } return list;
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc index 8fe1cac..6b7ba4d 100644 --- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc +++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
@@ -479,9 +479,8 @@ namespace { -absl::optional<Timing::TimelineOffset> MapAnimationRange( - StyleResolverState& state, - const CSSValue& value) { +absl::optional<TimelineOffset> MapAnimationRange(StyleResolverState& state, + const CSSValue& value) { if (auto* ident = DynamicTo<CSSIdentifierValue>(value); ident && ident->GetValueID() == CSSValueID::kAuto) { return absl::nullopt; @@ -489,20 +488,20 @@ const auto& list = To<CSSValueList>(value); DCHECK_EQ(list.length(), 2u); const auto& range_name = To<CSSIdentifierValue>(list.Item(0)); - return Timing::TimelineOffset( - range_name.ConvertTo<Timing::TimelineNamedRange>(), + return TimelineOffset( + range_name.ConvertTo<TimelineOffset::NamedRange>(), StyleBuilderConverter::ConvertLength(state, list.Item(1))); } } // namespace -absl::optional<Timing::TimelineOffset> CSSToStyleMap::MapAnimationRangeStart( +absl::optional<TimelineOffset> CSSToStyleMap::MapAnimationRangeStart( StyleResolverState& state, const CSSValue& value) { return MapAnimationRange(state, value); } -absl::optional<Timing::TimelineOffset> CSSToStyleMap::MapAnimationRangeEnd( +absl::optional<TimelineOffset> CSSToStyleMap::MapAnimationRangeEnd( StyleResolverState& state, const CSSValue& value) { return MapAnimationRange(state, value);
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h index cb25cb1..9532b30 100644 --- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h +++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h
@@ -85,10 +85,10 @@ const ScopedCSSValue&); static EAnimPlayState MapAnimationPlayState(StyleResolverState&, const CSSValue&); - static absl::optional<Timing::TimelineOffset> MapAnimationRangeStart( + static absl::optional<TimelineOffset> MapAnimationRangeStart( StyleResolverState&, const CSSValue&); - static absl::optional<Timing::TimelineOffset> MapAnimationRangeEnd( + static absl::optional<TimelineOffset> MapAnimationRangeEnd( StyleResolverState&, const CSSValue&); static EffectModel::CompositeOperation MapAnimationComposition(
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index b8cbf2f..2871bfb2 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -96,7 +96,7 @@ // propagation of overflow is stopped by containment. if (parent_style.IsOverflowVisibleAlongBothAxes()) { if (!parent_style.ShouldApplyAnyContainment(*document_element) && - !builder.InternalStyle()->ShouldApplyAnyContainment(*element)) { + !builder.ShouldApplyAnyContainment(*element)) { scrolls_overflow = false; } } @@ -685,7 +685,7 @@ IsA<HTMLImageElement>(element) || is_replaced_canvas); bool is_table_row_or_column = builder.IsDisplayTableRowOrColumnType(); bool is_layout_object_needed = - element && element->LayoutObjectIsNeeded(*builder.InternalStyle()); + element && element->LayoutObjectIsNeeded(builder.GetDisplayStyle()); TouchAction element_touch_action = TouchAction::kAuto; // Touch actions are only supported by elements that support both the CSS @@ -846,7 +846,7 @@ auto* html_element = DynamicTo<HTMLElement>(element); if (html_element && (builder.Display() != EDisplay::kNone || - element->LayoutObjectIsNeeded(*builder.InternalStyle()))) { + element->LayoutObjectIsNeeded(builder.GetDisplayStyle()))) { AdjustStyleForHTMLElement(builder, *html_element); }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index ca80b65..06aadf936 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -332,10 +332,11 @@ FontDescription::FamilyDescription StyleBuilderConverter::ConvertFontFamily( StyleResolverState& state, - const ScopedCSSValue& scoped_value) { - state.GetFontBuilder().SetFamilyTreeScope(scoped_value.GetTreeScope()); + const CSSValue& value) { + // TODO(crbug.com/336876): Use the correct tree scope. + state.GetFontBuilder().SetFamilyTreeScope(&state.GetDocument()); return StyleBuilderConverterBase::ConvertFontFamily( - scoped_value.GetCSSValue(), + value, state.GetDocument().GetSettings() ? &state.GetFontBuilder() : nullptr, &state.GetDocument()); } @@ -1665,14 +1666,17 @@ return ClampTo<float>(ConvertNumberOrPercentage(state, value), 0, 1); } -AtomicString StyleBuilderConverter::ConvertNoneOrCustomIdent( +ScopedCSSName* StyleBuilderConverter::ConvertNoneOrCustomIdent( StyleResolverState& state, const CSSValue& value) { + DCHECK(value.IsScopedValue()); if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { DCHECK_EQ(identifier_value->GetValueID(), CSSValueID::kNone); - return g_null_atom; + return nullptr; } - return To<CSSCustomIdentValue>(value).Value(); + const CSSCustomIdentValue& custom_ident = To<CSSCustomIdentValue>(value); + return MakeGarbageCollected<ScopedCSSName>(custom_ident.Value(), + custom_ident.GetTreeScope()); } ScopedCSSName* StyleBuilderConverter::ConvertNoneOrCustomIdent( @@ -1690,9 +1694,9 @@ AnchorScrollValue* StyleBuilderConverter::ConvertAnchorScroll( StyleResolverState& state, - const ScopedCSSValue& value) { - if (const auto* identifier_value = - DynamicTo<CSSIdentifierValue>(value.GetCSSValue())) { + const CSSValue& value) { + DCHECK(value.IsScopedValue()); + if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { switch (identifier_value->GetValueID()) { case CSSValueID::kNone: return nullptr; @@ -1703,10 +1707,10 @@ return nullptr; } } + const CSSCustomIdentValue& custom_ident = To<CSSCustomIdentValue>(value); return MakeGarbageCollected<AnchorScrollValue>( - *MakeGarbageCollected<ScopedCSSName>( - To<CSSCustomIdentValue>(value.GetCSSValue()).Value(), - value.GetTreeScope())); + *MakeGarbageCollected<ScopedCSSName>(custom_ident.Value(), + custom_ident.GetTreeScope())); } StyleInitialLetter StyleBuilderConverter::ConvertInitialLetter(
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h index e480d2f..ef1781a 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -129,7 +129,7 @@ static T ConvertFlags(StyleResolverState&, const CSSValue&); static FontDescription::FamilyDescription ConvertFontFamily( StyleResolverState&, - const ScopedCSSValue&); + const CSSValue&); static scoped_refptr<FontFeatureSettings> ConvertFontFeatureSettings( StyleResolverState&, const CSSValue&); @@ -206,12 +206,12 @@ static float ConvertNumberOrPercentage(StyleResolverState&, const CSSValue&); static float ConvertAlpha(StyleResolverState&, const CSSValue&); // clamps to [0,1] - static AtomicString ConvertNoneOrCustomIdent(StyleResolverState&, - const CSSValue&); + static ScopedCSSName* ConvertNoneOrCustomIdent(StyleResolverState&, + const CSSValue&); static ScopedCSSName* ConvertNoneOrCustomIdent(StyleResolverState&, const ScopedCSSValue&); static AnchorScrollValue* ConvertAnchorScroll(StyleResolverState&, - const ScopedCSSValue&); + const CSSValue&); static StyleInitialLetter ConvertInitialLetter(StyleResolverState&, const CSSValue&); static StyleOffsetRotation ConvertOffsetRotate(StyleResolverState&,
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc index 0994c32..aa266bb 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -523,6 +523,17 @@ maybe_skip(GetCSSPropertyWebkitTransformOriginZ(), *priority); } } + + // vertical-align will become a shorthand in the future - in order to + // mitigate the forward compat risk, skip the baseline-source longhand. + const CSSProperty& vertical_align = GetCSSPropertyVerticalAlign(); + if (!resolver.filter_.Rejects(vertical_align)) { + if (const CascadePriority* priority = + map_.Find(vertical_align.GetCSSPropertyName())) { + LookupAndApply(vertical_align, resolver); + maybe_skip(GetCSSPropertyBaselineSource(), *priority); + } + } } // Go through all properties that were found during the analyze phase
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc index d52aaffa..55e0e04 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -2948,6 +2948,26 @@ EXPECT_EQ(nullptr, cascade.ComputedValue("-webkit-transform-origin-z")); } +TEST_F(StyleCascadeTest, VerticalAlignBaselineSource) { + TestCascade cascade(GetDocument()); + cascade.Add("vertical-align", "top"); + cascade.Add("baseline-source", "first"); + cascade.Apply(); + + EXPECT_EQ("top", cascade.ComputedValue("vertical-align")); + EXPECT_EQ("first", cascade.ComputedValue("baseline-source")); +} + +TEST_F(StyleCascadeTest, VerticalAlignBaselineSourceReversed) { + TestCascade cascade(GetDocument()); + cascade.Add("baseline-source", "first"); + cascade.Add("vertical-align", "top"); + cascade.Apply(); + + EXPECT_EQ("top", cascade.ComputedValue("vertical-align")); + EXPECT_EQ("auto", cascade.ComputedValue("baseline-source")); +} + TEST_F(StyleCascadeTest, InitialDirection) { TestCascade cascade(GetDocument()); cascade.Add("margin-inline-start:10px");
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 49676c5..2fa836dc 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -435,6 +435,22 @@ return decl; } +// UA rule: * { top-layer: none !important } +static CSSPropertyValueSet* UniversalTopLayerUserAgentDeclaration() { + DEFINE_STATIC_LOCAL( + Persistent<MutableCSSPropertyValueSet>, decl, + (MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLStandardMode))); + + DCHECK(RuntimeEnabledFeatures::CSSTopLayerForTransitionsEnabled()); + + if (decl->IsEmpty()) { + decl->SetProperty(CSSPropertyID::kTopLayer, + *CSSIdentifierValue::Create(CSSValueID::kNone), + true /* important */); + } + return decl; +} + static void CollectScopedResolversForHostedShadowTrees( const Element& element, HeapVector<Member<ScopedStyleResolver>, 8>& resolvers) { @@ -1324,22 +1340,33 @@ // rules that are relevant for the element exist in the stylesheet. GetDocument().GetStyleEngine().EnsureUAStyleForElement(*element); - if (!style_request.IsPseudoStyleRequest() && IsForcedColorsModeEnabled()) { - cascade.MutableMatchResult().AddMatchedProperties( - ForcedColorsUserAgentDeclarations()); - } + if (!style_request.IsPseudoStyleRequest()) { + if (IsForcedColorsModeEnabled()) { + cascade.MutableMatchResult().AddMatchedProperties( + ForcedColorsUserAgentDeclarations()); + } - // This adds a CSSInitialColorValue to the cascade for the document - // element. The CSSInitialColorValue will resolve to a color-scheme - // sensitive color in Color::ApplyValue. It is added at the start of the - // MatchResult such that subsequent declarations (even from the UA sheet) - // get a higher priority. - // - // TODO(crbug.com/1046753): Remove this when canvastext is supported. - if (!style_request.IsPseudoStyleRequest() && - element == state.GetDocument().documentElement()) { - cascade.MutableMatchResult().AddMatchedProperties( - DocumentElementUserAgentDeclarations()); + // UA rule: * { top-layer: none !important } + // Implemented here because DCHECKs ensures we don't add universal rules to + // the UA sheets. Note that this is a universal rule in any namespace. + // Adding this to the html.css would only do the override in the HTML + // namespace since the sheet has a default namespace. + if (RuntimeEnabledFeatures::CSSTopLayerForTransitionsEnabled()) { + cascade.MutableMatchResult().AddMatchedProperties( + UniversalTopLayerUserAgentDeclaration()); + } + + // This adds a CSSInitialColorValue to the cascade for the document + // element. The CSSInitialColorValue will resolve to a color-scheme + // sensitive color in Color::ApplyValue. It is added at the start of the + // MatchResult such that subsequent declarations (even from the UA sheet) + // get a higher priority. + // + // TODO(crbug.com/1046753): Remove this when canvastext is supported. + if (element == state.GetDocument().documentElement()) { + cascade.MutableMatchResult().AddMatchedProperties( + DocumentElementUserAgentDeclarations()); + } } ElementRuleCollector collector(state.ElementContext(), style_recalc_context, @@ -1432,6 +1459,12 @@ match_result.PseudoElementStyles()); ApplyCallbackSelectors(state); + if (element->IsLink() && (element->HasTagName(html_names::kATag) || + element->HasTagName(html_names::kAreaTag))) { + // TODO(crbug.com/1371522): Revisit scoping root used after + // https://github.com/WICG/nav-speculation/issues/240 is resolved. + ApplyDocumentRulesSelectors(state, &GetDocument()); + } // Cache our original display. state.StyleBuilder().SetOriginalDisplay(state.StyleBuilder().Display()); @@ -2317,33 +2350,51 @@ } void StyleResolver::ApplyCallbackSelectors(StyleResolverState& state) { - RuleSet* watched_selectors_rule_set = - GetDocument().GetStyleEngine().WatchedSelectorsRuleSet(); - if (!watched_selectors_rule_set) { + StyleRuleList* rules = CollectMatchingRulesFromRuleSet( + state, GetDocument().GetStyleEngine().WatchedSelectorsRuleSet(), + /*scope=*/nullptr); + if (!rules) { return; } + for (auto rule : *rules) { + state.StyleBuilder().AddCallbackSelector(rule->SelectorsText()); + } +} + +void StyleResolver::ApplyDocumentRulesSelectors(StyleResolverState& state, + ContainerNode* scope) { + StyleRuleList* rules = CollectMatchingRulesFromRuleSet( + state, GetDocument().GetStyleEngine().DocumentRulesSelectorsRuleSet(), + scope); + if (!rules) { + return; + } + for (auto rule : *rules) { + state.StyleBuilder().AddDocumentRulesSelector(rule); + } +} + +StyleRuleList* StyleResolver::CollectMatchingRulesFromRuleSet( + StyleResolverState& state, + RuleSet* rule_set, + ContainerNode* scope) { + if (!rule_set) { + return nullptr; + } MatchResult match_result; ElementRuleCollector collector(state.ElementContext(), StyleRecalcContext(), selector_filter_, match_result, state.StyleBuilder().InsideLink()); collector.SetMode(SelectorChecker::kCollectingStyleRules); - - MatchRequest match_request(watched_selectors_rule_set); + MatchRequest match_request(rule_set, scope); collector.CollectMatchingRules(match_request); collector.SortAndTransferMatchedRules(); if (tracker_) { AddMatchedRulesToTracker(collector); } - - StyleRuleList* rules = collector.MatchedStyleRuleList(); - if (!rules) { - return; - } - for (auto rule : *rules) { - state.StyleBuilder().AddCallbackSelector(rule->SelectorsText()); - } + return collector.MatchedStyleRuleList(); } // Font properties are also handled by FontStyleResolver outside the main
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h index 65740ba..be4dce0 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -311,6 +311,10 @@ bool ApplyAnimatedStyle(StyleResolverState&, StyleCascade&); void ApplyCallbackSelectors(StyleResolverState&); + void ApplyDocumentRulesSelectors(StyleResolverState&, ContainerNode* scope); + StyleRuleList* CollectMatchingRulesFromRuleSet(StyleResolverState&, + RuleSet*, + ContainerNode* scope); Document& GetDocument() const { return *document_; }
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc index a4485a0..0e75e18 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -169,7 +169,7 @@ if (pseudo_request_type_ == StyleRequest::kForComputedStyle || (ParentStyle() && ParentStyle()->IsEnsuredInDisplayNone()) || (StyleBuilder().Display() == EDisplay::kNone && - !GetElement().LayoutObjectIsNeeded(*style_builder_.InternalStyle())) || + !GetElement().LayoutObjectIsNeeded(style_builder_.GetDisplayStyle())) || StyleBuilder().IsEnsuredOutsideFlatTree()) { return; }
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc index b47361b..bdbe47f 100644 --- a/third_party/blink/renderer/core/css/selector_checker.cc +++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -1333,7 +1333,6 @@ case CSSSelector::kPseudoOnlyChild: { if (IsTransitionPseudoElement(context.pseudo_id)) { DCHECK(element.IsDocumentElement()); - DCHECK_NE(context.pseudo_id, kPseudoIdViewTransition); DCHECK(context.pseudo_argument); auto* transition =
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 10b19c5..de93b9a 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -426,6 +426,28 @@ style_change_reason::kDeclarativeContent)); } +void StyleEngine::DocumentRulesSelectorsChanged() { + DCHECK(global_rule_set_); + Member<RuleSet> old_rule_set = + global_rule_set_->DocumentRulesSelectorsRuleSet(); + global_rule_set_->UpdateDocumentRulesSelectorsRuleSet(GetDocument()); + Member<RuleSet> new_rule_set = + global_rule_set_->DocumentRulesSelectorsRuleSet(); + DCHECK_NE(old_rule_set, new_rule_set); + + const unsigned changed_rule_flags = 0; + HeapHashSet<Member<RuleSet>> changed_rule_sets; + if (old_rule_set) { + changed_rule_sets.insert(old_rule_set); + } + if (new_rule_set) { + changed_rule_sets.insert(new_rule_set); + } + + InvalidateForRuleSetChanges(GetDocument(), changed_rule_sets, + changed_rule_flags, kInvalidateAllScopes); +} + bool StyleEngine::ShouldUpdateDocumentStyleSheetCollection() const { return document_scope_dirty_; }
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 6c9bc09..13562a46 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -227,6 +227,7 @@ void AdoptedStyleSheetRemoved(TreeScope& tree_scope, CSSStyleSheet* sheet); void WatchedSelectorsChanged(); + void DocumentRulesSelectorsChanged(); void InitialStyleChanged(); void ColorSchemeChanged(); void SetOwnerColorScheme(mojom::blink::ColorScheme); @@ -247,6 +248,10 @@ DCHECK(global_rule_set_); return global_rule_set_->WatchedSelectorsRuleSet(); } + RuleSet* DocumentRulesSelectorsRuleSet() { + DCHECK(global_rule_set_); + return global_rule_set_->DocumentRulesSelectorsRuleSet(); + } // Helper class for making sure RuleSets that are ensured when collecting // sheets for a TreeScope are not shared between two equal sheets which
diff --git a/third_party/blink/renderer/core/css/style_rule_keyframe.h b/third_party/blink/renderer/core/css/style_rule_keyframe.h index 9f6f5b4..c3268183 100644 --- a/third_party/blink/renderer/core/css/style_rule_keyframe.h +++ b/third_party/blink/renderer/core/css/style_rule_keyframe.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_RULE_KEYFRAME_H_ #include <memory> +#include "third_party/blink/renderer/core/animation/animation.h" #include "third_party/blink/renderer/core/animation/timing.h" #include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -18,7 +19,7 @@ struct KeyframeOffset { explicit KeyframeOffset( - Timing::TimelineNamedRange name = Timing::TimelineNamedRange::kNone, + TimelineOffset::NamedRange name = TimelineOffset::NamedRange::kNone, double percent = 0) : name(name), percent(percent) {} @@ -28,7 +29,7 @@ bool operator!=(const KeyframeOffset& b) const { return !(*this == b); } - Timing::TimelineNamedRange name; + TimelineOffset::NamedRange name; double percent; };
diff --git a/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc b/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc index 3d6ffe8..93f19ef3 100644 --- a/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc +++ b/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc
@@ -84,14 +84,12 @@ TextRun ahem_above_below_baseline(ahem_above_below_baseline_string, 9); TextRunPaintInfo text_run_paint_info(ahem_above_below_baseline); cc::PaintFlags default_paint; - float device_scale_factor = 1; std::tuple<float, float> below_baseline_bounds = std::make_tuple(2, 4); Vector<Font::TextIntercept> text_intercepts; // 4 intercept ranges for below baseline p glyphs in the test string - font.GetTextIntercepts(text_run_paint_info, device_scale_factor, - default_paint, below_baseline_bounds, - text_intercepts); + font.GetTextIntercepts(text_run_paint_info, default_paint, + below_baseline_bounds, text_intercepts); EXPECT_EQ(text_intercepts.size(), 4u); for (auto text_intercept : text_intercepts) { EXPECT_GT(text_intercept.end_, text_intercept.begin_); @@ -99,9 +97,8 @@ std::tuple<float, float> above_baseline_bounds = std::make_tuple(-4, -2); // 5 intercept ranges for the above baseline E ACUTE glyphs - font.GetTextIntercepts(text_run_paint_info, device_scale_factor, - default_paint, above_baseline_bounds, - text_intercepts); + font.GetTextIntercepts(text_run_paint_info, default_paint, + above_baseline_bounds, text_intercepts); EXPECT_EQ(text_intercepts.size(), 5u); for (auto text_intercept : text_intercepts) { EXPECT_GT(text_intercept.end_, text_intercept.begin_);
diff --git a/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc b/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc index c05fdb7..fec5489 100644 --- a/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc +++ b/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
@@ -93,7 +93,7 @@ EXPECT_CALL(mpc, restoreToCount(17)).WillOnce(Return()); font.DrawBidiText(&mpc, text_run_paint_info, location, - Font::kUseFallbackIfFontNotReady, 1.0, flags, + Font::kUseFallbackIfFontNotReady, flags, Font::DrawType::kGlyphsAndClusters); }); }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 5155cc2b..7eeca95 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3051,7 +3051,18 @@ return ax_mode; } +namespace { + +// Simple count of AXObjectCache objects that are reachable from Documents. The +// count assumes that multiple Documents in a single process can have such +// caches and that the caches will only ever be created from the main rendering +// thread. +size_t g_ax_object_cache_count = 0; + +} // namespace + void Document::AddAXContext(AXContext* context) { + DCHECK(IsMainThread()); // The only case when |&cache_owner| is not |this| is when this is a // popup. We want popups to share the AXObjectCache of their parent // document. However, there's no valid reason to explicitly create an @@ -3073,6 +3084,7 @@ if (!ax_object_cache_) { ax_object_cache_ = AXObjectCache::Create(*this, ComputeAXModeFromAXContexts(ax_contexts_)); + g_ax_object_cache_count++; } } @@ -3095,13 +3107,17 @@ } void Document::ClearAXObjectCache() { + DCHECK(IsMainThread()); DCHECK_EQ(&AXObjectCacheOwner(), this); // Clear the cache member variable before calling delete because attempts // are made to access it during destruction. - if (ax_object_cache_) + if (ax_object_cache_) { ax_object_cache_->Dispose(); - ax_object_cache_.Clear(); + ax_object_cache_.Clear(); + DCHECK_NE(g_ax_object_cache_count, 0u); + g_ax_object_cache_count--; + } // If there's at least one AXContext in scope and there's still a LayoutView // around, recreate an empty AXObjectCache. @@ -3113,10 +3129,16 @@ if (ax_contexts_.size() > 0 && GetLayoutView()) { ax_object_cache_ = AXObjectCache::Create(*this, ComputeAXModeFromAXContexts(ax_contexts_)); + g_ax_object_cache_count++; } } AXObjectCache* Document::ExistingAXObjectCache() const { + DCHECK(IsMainThread()); + if (g_ax_object_cache_count == 0) { + return nullptr; + } + auto& cache_owner = AXObjectCacheOwner(); // If the LayoutView is gone then we are in the process of destruction. @@ -3126,16 +3148,6 @@ return cache_owner.ax_object_cache_.Get(); } -bool Document::HasAXObjectCache() const { - auto& cache_owner = AXObjectCacheOwner(); - - // If the LayoutView is gone then we are in the process of destruction. - if (!cache_owner.layout_view_) - return false; - - return cache_owner.ax_object_cache_; -} - CanvasFontCache* Document::GetCanvasFontCache() { if (!canvas_font_cache_) canvas_font_cache_ = MakeGarbageCollected<CanvasFontCache>(*this); @@ -8560,10 +8572,6 @@ visitor->Trace(anchor_element_interaction_tracker_); visitor->Trace(focused_element_change_observers_); visitor->Trace(pending_link_header_preloads_); - visitor->Trace(event_node_path_cache_); - visitor->Trace(event_node_path_cache_key_list_); - visitor->Trace(latest_cached_event_node_); - visitor->Trace(latest_cached_event_node_path_); Supplementable<Document>::Trace(visitor); TreeScope::Trace(visitor); ContainerNode::Trace(visitor); @@ -8941,76 +8949,6 @@ Document::PendingJavascriptUrl::~PendingJavascriptUrl() = default; -static wtf_size_t MaxEventNodePathCachedEntriesValue() { - // The cache stores N entries/nodes that are receiving events simultaneously - // in a document. The size of this cache will be O(kN) where k is the average - // tree depth of the stored nodes. - static const wtf_size_t kMaxEventNodePathCachedEntriesValue = - features::kDocumentMaxEventNodePathCachedEntries.Get(); - return kMaxEventNodePathCachedEntriesValue; -} - -static bool EventNodePathCachingEnabled() { - // Cache the feature value since checking for each event path regresses - // performance. - static const bool kEnabled = - base::FeatureList::IsEnabled(features::kDocumentEventNodePathCaching); - return kEnabled; -} - -const EventPath::NodePath& Document::GetOrCalculateEventNodePath(Node& node) { - DCHECK(EventNodePathCachingEnabled()); - wtf_size_t max_entries = MaxEventNodePathCachedEntriesValue(); - if (max_entries == 1) { - if (event_node_path_dom_tree_version_ == dom_tree_version_ && - latest_cached_event_node_ == &node) { - return *latest_cached_event_node_path_; - } else { - EventPath::NodePath node_path = EventPath::CalculateNodePath(node); - event_node_path_dom_tree_version_ = dom_tree_version_; - latest_cached_event_node_ = &node; - latest_cached_event_node_path_ = - MakeGarbageCollected<EventPath::NodePath>(std::move(node_path)); - return *latest_cached_event_node_path_; - } - } - - if (event_node_path_dom_tree_version_ != dom_tree_version_) { - if (!event_node_path_cache_.empty()) { - event_node_path_cache_.clear(); - event_node_path_cache_key_list_.clear(); - } else { - DCHECK(event_node_path_cache_key_list_.empty()); - } - event_node_path_dom_tree_version_ = dom_tree_version_; - } - - EventPath::NodePath* event_node_path = nullptr; - { - // Keep `result` within own scope to avoid dangling references into cache, - // because it might get modified during pruning. - auto result = event_node_path_cache_.insert(&node, nullptr); - if (result.is_new_entry) { - EventPath::NodePath node_path = EventPath::CalculateNodePath(node); - result.stored_value->value = - MakeGarbageCollected<EventPath::NodePath>(std::move(node_path)); - } - event_node_path = result.stored_value->value; - } - event_node_path_cache_key_list_.PrependOrMoveToFirst(&node); - - // Prune oldest cached node if size is bigger than max. - if (event_node_path_cache_key_list_.size() > max_entries) { - DCHECK_EQ(event_node_path_cache_key_list_.size(), max_entries + 1); - event_node_path_cache_.erase(event_node_path_cache_key_list_.back()); - event_node_path_cache_key_list_.pop_back(); - } - - DCHECK_EQ(event_node_path_cache_.size(), - event_node_path_cache_key_list_.size()); - return *event_node_path; -} - void Document::ResetAgent(Agent& agent) { agent_ = agent; }
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index f238db7f..4031781c 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -753,7 +753,6 @@ // AXContext associated with this document. When all associated // AXContexts are deleted, the AXObjectCache will be removed. AXObjectCache* ExistingAXObjectCache() const; - bool HasAXObjectCache() const; Document& AXObjectCacheOwner() const; void ClearAXObjectCache(); @@ -1473,8 +1472,6 @@ // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element void DelayLoadEventUntilLayoutTreeUpdate(); - const EventPath::NodePath& GetOrCalculateEventNodePath(Node& node); - const DocumentTiming& GetTiming() const { return document_timing_; } bool ShouldMarkFontPerformance() const { @@ -2474,20 +2471,6 @@ // successful and not successful) by the page. std::unique_ptr<FontMatchingMetrics> font_matching_metrics_; - // For a given node, cache the vector of nodes that defines its EventPath so - // all events dispatched on this node won't get recalculated. This cache uses - // a LRU strategy and gets cleared when the DOM tree version changes. - uint64_t event_node_path_dom_tree_version_; - using EventNodePathCache = - HeapHashMap<Member<Node>, Member<EventPath::NodePath>>; - using EventNodePathCacheKeyList = HeapLinkedHashSet<Member<Node>>; - EventNodePathCache event_node_path_cache_; - EventNodePathCacheKeyList event_node_path_cache_key_list_; - // If we only want to cache one event path, we can avoid using the heap hash - // map and hash set. - Member<Node> latest_cached_event_node_; - Member<EventPath::NodePath> latest_cached_event_node_path_; - #if DCHECK_IS_ON() unsigned slot_assignment_recalc_forbidden_recursion_depth_ = 0; #endif
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index c33133f..dafa834c 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -142,6 +142,8 @@ #include "third_party/blink/renderer/core/html/forms/html_options_collection.h" #include "third_party/blink/renderer/core/html/forms/html_select_element.h" #include "third_party/blink/renderer/core/html/forms/html_select_menu_element.h" +#include "third_party/blink/renderer/core/html/html_anchor_element.h" +#include "third_party/blink/renderer/core/html/html_area_element.h" #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_collection.h" #include "third_party/blink/renderer/core/html/html_document.h" @@ -183,6 +185,7 @@ #include "third_party/blink/renderer/core/scroll/scrollable_area.h" #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h" #include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h" +#include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h" #include "third_party/blink/renderer/core/style/toggle_root_list.h" #include "third_party/blink/renderer/core/svg/svg_a_element.h" @@ -199,6 +202,7 @@ #include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h" #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" +#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" @@ -2640,11 +2644,15 @@ return FastGetAttribute(html_names::kSrcAttr); } -bool Element::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool Element::LayoutObjectIsNeeded(const DisplayStyle& style) const { return style.Display() != EDisplay::kNone && style.Display() != EDisplay::kContents; } +bool Element::LayoutObjectIsNeeded(const ComputedStyle& style) const { + return LayoutObjectIsNeeded(style.GetDisplayStyle()); +} + LayoutObject* Element::CreateLayoutObject(const ComputedStyle& style, LegacyLayout legacy) { return LayoutObject::CreateObject(this, style, legacy); @@ -3764,6 +3772,8 @@ } child_change = ApplyComputedStyleDiff(child_change, diff); UpdateCallbackSelectors(old_style.get(), new_style.get()); + NotifyIfMatchedDocumentRulesSelectorsChanged(old_style.get(), + new_style.get()); } if (auto* context = GetDisplayLockContext()) { @@ -4030,6 +4040,38 @@ } } +void Element::NotifyIfMatchedDocumentRulesSelectorsChanged( + const ComputedStyle* old_style, + const ComputedStyle* new_style) { + if (!IsLink() || + !(HasTagName(html_names::kATag) || HasTagName(html_names::kAreaTag))) { + return; + } + auto get_selectors_from_computed_style = [](const ComputedStyle* style) { + HeapHashSet<WeakMember<StyleRule>> empty_set; + if (!style || !style->DocumentRulesSelectors()) { + return empty_set; + } + return *style->DocumentRulesSelectors(); + }; + + const HeapHashSet<WeakMember<StyleRule>>& old_document_rules_selectors = + get_selectors_from_computed_style(old_style); + const HeapHashSet<WeakMember<StyleRule>>& new_document_rules_selectors = + get_selectors_from_computed_style(new_style); + if (old_document_rules_selectors.empty() && + new_document_rules_selectors.empty()) { + return; + } + if (old_document_rules_selectors != new_document_rules_selectors) { + HTMLAnchorElement* link = nullptr; + link = HasTagName(html_names::kATag) ? To<HTMLAnchorElement>(this) + : To<HTMLAreaElement>(this); + DocumentSpeculationRules::From(GetDocument()) + .LinkMatchedSelectorsUpdated(link); + } +} + ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) { #if DCHECK_IS_ON() NestingLevelIncrementer slot_assignment_recalc_forbidden_scope(
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 5f1916a..27272f0 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -83,6 +83,7 @@ class DOMStringMap; class DOMTokenList; class DisplayLockContext; +class DisplayStyle; class Document; class EditContext; class ElementAnimations; @@ -593,7 +594,8 @@ void DetachLayoutTree(bool performing_reattach = false) override; virtual LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout); - virtual bool LayoutObjectIsNeeded(const ComputedStyle&) const; + virtual bool LayoutObjectIsNeeded(const DisplayStyle&) const; + bool LayoutObjectIsNeeded(const ComputedStyle&) const; const ComputedStyle* ParentComputedStyle() const; @@ -1499,6 +1501,9 @@ inline void UpdateCallbackSelectors(const ComputedStyle* old_style, const ComputedStyle* new_style); + inline void NotifyIfMatchedDocumentRulesSelectorsChanged( + const ComputedStyle* old_style, + const ComputedStyle* new_style); // Clone is private so that non-virtual CloneElementWithChildren and // CloneElementWithoutChildren are used instead.
diff --git a/third_party/blink/renderer/core/dom/events/event_path.cc b/third_party/blink/renderer/core/dom/events/event_path.cc index 8eeb091..0503bf6 100644 --- a/third_party/blink/renderer/core/dom/events/event_path.cc +++ b/third_party/blink/renderer/core/dom/events/event_path.cc
@@ -26,7 +26,6 @@ #include "third_party/blink/renderer/core/dom/events/event_path.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/window_event_context.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" @@ -85,74 +84,10 @@ CalculateTreeOrderAndSetNearestAncestorClosedTree(); } -EventPath::NodePath EventPath::CalculateNodePath(Node& node) { - // Given a node, find all the nodes the event path might traverse. - NodePath node_path; - Node* current = &node; - - node_path.push_back(current); - while (current) { - if (current->IsChildOfShadowHost() && !current->IsPseudoElement()) { - if (HTMLSlotElement* slot = current->AssignedSlot()) { - current = slot; - node_path.push_back(current); - continue; - } - } - if (auto* shadow_root = DynamicTo<ShadowRoot>(current)) { - current = current->OwnerShadowHost(); - node_path.push_back(current); - } else { - current = current->parentNode(); - if (current) - node_path.push_back(current); - } - } - return node_path; -} - -static bool EventNodePathCachingEnabled() { - // Cache the feature value since checking for each event path regresses - // performance. - static const bool kEnabled = - base::FeatureList::IsEnabled(features::kDocumentEventNodePathCaching); - return kEnabled; -} - void EventPath::CalculatePath() { DCHECK(node_); DCHECK(node_event_contexts_.empty()); - if (EventNodePathCachingEnabled()) - CalculatePathCachingEnabled(); - else - CalculatePathCachingDisabled(); -} - -void EventPath::CalculatePathCachingEnabled() { - // Find the cached CalculateNodePath result - const NodePath& node_path = - node_->GetDocument().GetOrCalculateEventNodePath(*node_); - // We need to do the KeepEventInNode and ShouldStopAtShadowRoot checks - // outside of CalculateNodePath as they depend on the dispatched event. - for (Node* node_in_path : node_path) { - DCHECK(node_in_path); - node_event_contexts_.push_back(NodeEventContext( - *node_in_path, EventTargetRespectingTargetRules(*node_in_path))); - if (!event_) - continue; - if (node_in_path->KeepEventInNode(*event_)) - break; - if (auto* shadow_root = DynamicTo<ShadowRoot>(node_in_path)) { - if (ShouldStopAtShadowRoot(*event_, *shadow_root, *node_)) - break; - } - } -} - -// TODO(crbug.com/329788): This function should be removed once the -// kDocumentEventNodePathCaching experiment is fully enabled. -void EventPath::CalculatePathCachingDisabled() { // For performance and memory usage reasons we want to store the // path using as few bytes as possible and with as few allocations // as possible which is why we gather the data on the stack before
diff --git a/third_party/blink/renderer/core/dom/events/event_path.h b/third_party/blink/renderer/core/dom/events/event_path.h index 39a8da7..8229177 100644 --- a/third_party/blink/renderer/core/dom/events/event_path.h +++ b/third_party/blink/renderer/core/dom/events/event_path.h
@@ -46,8 +46,6 @@ class CORE_EXPORT EventPath final : public GarbageCollected<EventPath> { public: - using NodePath = HeapVector<Member<Node>, 64>; - explicit EventPath(Node&, Event* = nullptr); EventPath(const EventPath&) = delete; EventPath& operator=(const EventPath&) = delete; @@ -90,7 +88,6 @@ NodeEventContext& TopNodeEventContext(); static EventTarget& EventTargetRespectingTargetRules(Node&); - static NodePath CalculateNodePath(Node&); void Trace(Visitor*) const; void Clear() { @@ -103,8 +100,6 @@ void Initialize(); void CalculatePath(); - void CalculatePathCachingEnabled(); - void CalculatePathCachingDisabled(); void CalculateAdjustedTargets(); void CalculateTreeOrderAndSetNearestAncestorClosedTree();
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index b694465..5579253d 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -2229,8 +2229,8 @@ } if (ParentOrShadowHostNode()->IsInShadowTree()) SetFlag(kIsInShadowTreeFlag); - if (GetDocument().HasAXObjectCache()) { - GetDocument().ExistingAXObjectCache()->ChildrenChanged(&insertion_point); + if (auto* cache = GetDocument().ExistingAXObjectCache()) { + cache->ChildrenChanged(&insertion_point); } return kInsertionDone; } @@ -2248,8 +2248,8 @@ } if (IsInShadowTree() && !ContainingTreeScope().RootNode().IsShadowRoot()) ClearFlag(kIsInShadowTreeFlag); - if (GetDocument().HasAXObjectCache()) { - GetDocument().ExistingAXObjectCache()->Remove(this); + if (auto* cache = GetDocument().ExistingAXObjectCache()) { + cache->Remove(this); } } @@ -3384,8 +3384,9 @@ GetDocument().GetStyleEngine().RemovedFromFlatTree(*this); // Ensure removal from accessibility cache even if it doesn't have layout. - if (GetDocument().HasAXObjectCache()) - GetDocument().ExistingAXObjectCache()->Remove(this); + if (auto* cache = GetDocument().ExistingAXObjectCache()) { + cache->Remove(this); + } } void Node::RegisterScrollTimeline(ScrollTimeline* timeline) {
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc index d8f37f4..d815726 100644 --- a/third_party/blink/renderer/core/dom/pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -48,6 +48,9 @@ namespace blink { +bool PseudoElementLayoutObjectIsNeeded(const DisplayStyle& pseudo_style, + const Element* originating_element); + PseudoElement* PseudoElement::Create(Element* parent, PseudoId pseudo_id, const AtomicString& view_transition_name) { @@ -313,8 +316,8 @@ } } -bool PseudoElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { - return PseudoElementLayoutObjectIsNeeded(&style, parentElement()); +bool PseudoElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { + return PseudoElementLayoutObjectIsNeeded(style, parentElement()); } bool PseudoElement::CanGeneratePseudoElement(PseudoId pseudo_id) const { @@ -350,9 +353,16 @@ const Element* originating_element) { if (!pseudo_style) return false; - if (pseudo_style->Display() == EDisplay::kNone) + return PseudoElementLayoutObjectIsNeeded(pseudo_style->GetDisplayStyle(), + originating_element); +} + +bool PseudoElementLayoutObjectIsNeeded(const DisplayStyle& pseudo_style, + const Element* originating_element) { + if (pseudo_style.Display() == EDisplay::kNone) { return false; - switch (pseudo_style->StyleType()) { + } + switch (pseudo_style.StyleType()) { case kPseudoIdFirstLetter: case kPseudoIdBackdrop: case kPseudoIdViewTransition: @@ -363,10 +373,11 @@ return true; case kPseudoIdBefore: case kPseudoIdAfter: - return !pseudo_style->ContentPreventsBoxGeneration(); + return !pseudo_style.ContentPreventsBoxGeneration(); case kPseudoIdMarker: { - if (!pseudo_style->ContentBehavesAsNormal()) - return !pseudo_style->ContentPreventsBoxGeneration(); + if (!pseudo_style.ContentBehavesAsNormal()) { + return !pseudo_style.ContentPreventsBoxGeneration(); + } const ComputedStyle* parent_style = originating_element->GetComputedStyle(); return parent_style && (parent_style->ListStyleType() ||
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.h b/third_party/blink/renderer/core/dom/pseudo_element.h index 62a0fba..3820ee4 100644 --- a/third_party/blink/renderer/core/dom/pseudo_element.h +++ b/third_party/blink/renderer/core/dom/pseudo_element.h
@@ -57,7 +57,7 @@ scoped_refptr<ComputedStyle> CustomStyleForLayoutObject( const StyleRecalcContext&) override; void AttachLayoutTree(AttachContext&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; bool CanGeneratePseudoElement(PseudoId) const override; bool CanStartSelection() const override { return false; }
diff --git a/third_party/blink/renderer/core/exported/DEPS b/third_party/blink/renderer/core/exported/DEPS index 8c06cfa..efec1e1 100644 --- a/third_party/blink/renderer/core/exported/DEPS +++ b/third_party/blink/renderer/core/exported/DEPS
@@ -26,6 +26,7 @@ "+components/viz/test", "+media/base", "+media/filters", + "+media/cdm/clear_key_cdm_common.h", "+media/mojo/services", "+media/renderers", "+gin/v8_initializer.h",
diff --git a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc index a92ce4af..b3fcaaa 100644 --- a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc +++ b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
@@ -43,6 +43,7 @@ #include "media/base/mock_media_log.h" #include "media/base/test_data_util.h" #include "media/base/test_helpers.h" +#include "media/cdm/clear_key_cdm_common.h" #include "media/filters/pipeline_controller.h" #include "media/mojo/services/media_metrics_provider.h" #include "media/mojo/services/video_decode_stats_recorder.h" @@ -852,7 +853,8 @@ void CreateCdm() { // Must use a supported key system on a secure context. - media::CdmConfig cdm_config = {"org.w3.clearkey", false, false, false}; + media::CdmConfig cdm_config = {media::kClearKeyKeySystem, false, false, + false}; auto test_origin = WebSecurityOrigin::CreateFromString( WebString::FromUTF8("https://test.origin"));
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 2e8500a..9ce7b0b 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -396,7 +396,6 @@ case kNavigationPolicyNewPopup: return ui::mojom::blink::WindowOpenDisposition::NEW_POPUP; case kNavigationPolicyPictureInPicture: - DCHECK(RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled()); return ui::mojom::blink::WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; } NOTREACHED() << "Unexpected NavigationPolicy";
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 34cb438..68f05f53 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -41,7 +41,6 @@ #include "build/build_config.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/system/message_pipe.h" -#include "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h" #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/content_security_policy.mojom-blink.h" #include "services/network/public/mojom/source_location.mojom-blink.h"
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index b2af7a2..a9437500 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -10,8 +10,6 @@ #include "build/build_config.h" #include "components/power_scheduler/power_mode.h" #include "components/power_scheduler/power_mode_arbiter.h" -#include "mojo/public/cpp/bindings/self_owned_receiver.h" -#include "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/chrome_debug_urls.h" @@ -24,7 +22,6 @@ #include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink-forward.h" #include "third_party/blink/public/platform/interface_registry.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/web/web_frame_serializer.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_plugin.h" @@ -39,7 +36,6 @@ #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/frame_console.h" -#include "third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h" #include "third_party/blink/renderer/core/frame/intervention.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -71,7 +67,6 @@ #include "third_party/blink/renderer/core/script/classic_script.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/view_transition/view_transition_supplement.h" -#include "third_party/blink/renderer/platform/mhtml/serialized_resource.h" #include "third_party/blink/renderer/platform/widget/frame_widget.h" #if BUILDFLAG(IS_MAC) @@ -102,73 +97,6 @@ return RemoteFrame::FromFrameToken(source_frame_token.value()); } -class WebBundleGenerationDelegate - : public WebFrameSerializer::MHTMLPartsGenerationDelegate { - STACK_ALLOCATED(); - - public: - WebBundleGenerationDelegate() = default; - ~WebBundleGenerationDelegate() = default; - - WebBundleGenerationDelegate(const WebBundleGenerationDelegate&) = delete; - WebBundleGenerationDelegate& operator=(const WebBundleGenerationDelegate&) = - delete; - - bool ShouldSkipResource(const WebURL& url) override { return false; } - bool UseBinaryEncoding() override { return false; } - bool RemovePopupOverlay() override { return false; } -}; - -class ResourceSnapshotForWebBundleImpl - : public data_decoder::mojom::blink::ResourceSnapshotForWebBundle { - public: - explicit ResourceSnapshotForWebBundleImpl(Deque<SerializedResource> resources) - : resources_(std::move(resources)) {} - ~ResourceSnapshotForWebBundleImpl() override = default; - - ResourceSnapshotForWebBundleImpl(const ResourceSnapshotForWebBundleImpl&) = - delete; - ResourceSnapshotForWebBundleImpl& operator=( - const ResourceSnapshotForWebBundleImpl&) = delete; - - // data_decoder::mojom::blink::ResourceSnapshotForWebBundle: - void GetResourceCount(GetResourceCountCallback callback) override { - std::move(callback).Run(resources_.size()); - } - void GetResourceInfo(uint64_t index, - GetResourceInfoCallback callback) override { - if (index >= resources_.size()) { - std::move(callback).Run(nullptr); - return; - } - const auto& resource = - resources_.at(base::checked_cast<WTF::wtf_size_t>(index)); - auto info = data_decoder::mojom::blink::SerializedResourceInfo::New(); - info->url = resource.url; - info->mime_type = resource.mime_type; - info->size = resource.data ? resource.data->size() : 0; - std::move(callback).Run(std::move(info)); - } - void GetResourceBody(uint64_t index, - GetResourceBodyCallback callback) override { - if (index >= resources_.size()) { - std::move(callback).Run(absl::nullopt); - return; - } - const auto& resource = - resources_.at(base::checked_cast<WTF::wtf_size_t>(index)); - if (!resource.data) { - std::move(callback).Run(absl::nullopt); - return; - } - std::move(callback).Run( - mojo_base::BigBuffer(resource.data->CopyAs<std::vector<uint8_t>>())); - } - - private: - const Deque<SerializedResource> resources_; -}; - v8::Local<v8::Context> MainWorldScriptContext(LocalFrame* local_frame) { ScriptState* script_state = ToScriptStateForMainWorld(local_frame); DCHECK(script_state); @@ -714,23 +642,6 @@ } } -void LocalFrameMojoHandler::GetResourceSnapshotForWebBundle( - mojo::PendingReceiver< - data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver) { - Deque<SerializedResource> resources; - - HeapHashSet<WeakMember<const Element>> shadow_template_elements; - WebBundleGenerationDelegate web_delegate; - FrameSerializerDelegateImpl core_delegate(web_delegate, - shadow_template_elements); - FrameSerializer serializer(resources, core_delegate); - serializer.SerializeFrame(*frame_); - - mojo::MakeSelfOwnedReceiver( - std::make_unique<ResourceSnapshotForWebBundleImpl>(std::move(resources)), - std::move(receiver)); -} - void LocalFrameMojoHandler::CopyImageAt(const gfx::Point& window_point) { gfx::Point viewport_position = frame_->GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h index 8e473710..9e4185a5 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -114,10 +114,6 @@ void EnableViewSourceMode() final; void Focus() final; void ClearFocusedElement() final; - void GetResourceSnapshotForWebBundle( - mojo::PendingReceiver< - data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver) - final; void CopyImageAt(const gfx::Point& window_point) final; void SaveImageAt(const gfx::Point& window_point) final; void ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature>&) final;
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index 0496574..a376799 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -375,7 +375,8 @@ // Fullscreen is not currently supported in document pip. // TODO(crbug.com/1402928): Figure out the correct way of handling fullscreen // element in picture-in-picture window. - if (RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled() && + if (RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled( + document.GetExecutionContext()) && frame->LocalFrameRoot().DomWindow() && frame->LocalFrameRoot().DomWindow()->IsPictureInPictureWindow()) { return false;
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc index 9a4c9e9..9c83de7 100644 --- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc +++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.cc
@@ -610,7 +610,7 @@ } bool HTMLFencedFrameElement::LayoutObjectIsNeeded( - const ComputedStyle& style) const { + const DisplayStyle& style) const { return !collapsed_by_client_ && HTMLFrameOwnerElement::LayoutObjectIsNeeded(style); }
diff --git a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h index 06d8a74..baf4d6a 100644 --- a/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h +++ b/third_party/blink/renderer/core/html/fenced_frame/html_fenced_frame_element.h
@@ -145,7 +145,7 @@ const QualifiedName&, const AtomicString&, MutableCSSPropertyValueSet*) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void AttachLayoutTree(AttachContext& context) override; bool SupportsFocus() const override;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index 1a94f225..98efc1f0 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -158,6 +158,8 @@ // Replace |CheckedStateChanged| with a generic tree changed event. if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) cache->CheckedStateChanged(this); + + CheckAndPossiblyClosePopoverStack(); } void HTMLFormControlElement::RequiredAttributeChanged() { @@ -244,6 +246,7 @@ void HTMLFormControlElement::RemovedFrom(ContainerNode& insertion_point) { HTMLElement::RemovedFrom(insertion_point); ListedElement::RemovedFrom(insertion_point); + CheckAndPossiblyClosePopoverStack(); } void HTMLFormControlElement::WillChangeForm() { @@ -256,6 +259,7 @@ ListedElement::DidChangeForm(); if (formOwner() && isConnected() && CanBeSuccessfulSubmitButton()) formOwner()->InvalidateDefaultButtonStyle(); + CheckAndPossiblyClosePopoverStack(); } HTMLFormElement* HTMLFormControlElement::formOwner() const { @@ -338,7 +342,8 @@ if (!RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( GetDocument().GetExecutionContext()) || !IsInTreeScope() || - SupportsPopoverTriggering() == PopoverTriggerSupport::kNone) { + SupportsPopoverTriggering() == PopoverTriggerSupport::kNone || + IsDisabledFormControl() || (Form() && IsSuccessfulSubmitButton())) { return no_element; }
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 0b1cc0a8..475a7a5 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
@@ -603,6 +603,8 @@ formOwner() && isConnected()) formOwner()->InvalidateDefaultButtonStyle(); NotifyFormStateChanged(); + + CheckAndPossiblyClosePopoverStack(); } void HTMLInputElement::SubtreeHasChanged() { @@ -939,7 +941,7 @@ } } -bool HTMLInputElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool HTMLInputElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { return input_type_->LayoutObjectIsNeeded() && TextControlElement::LayoutObjectIsNeeded(style); }
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 b11a2ca4..dde17e7 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
@@ -217,7 +217,7 @@ unsigned end, ExceptionState&); - bool LayoutObjectIsNeeded(const ComputedStyle&) const final; + bool LayoutObjectIsNeeded(const DisplayStyle&) const final; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void DetachLayoutTree(bool performing_reattach) final; void UpdateSelectionOnFocus(SelectionBehaviorOnFocus,
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 3cff5fc1..bf96527 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1775,7 +1775,7 @@ // popover=auto popovers are considered. const HTMLElement* HTMLElement::FindTopmostPopoverAncestor( const HTMLElement& new_popover) { - DCHECK(new_popover.HasPopoverAttribute() && !new_popover.popoverOpen()); + DCHECK(new_popover.HasPopoverAttribute()); auto& document = new_popover.GetDocument(); DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( document.GetExecutionContext())); @@ -1948,6 +1948,36 @@ } } +void HTMLElement::CheckAndPossiblyClosePopoverStack() { + if (LIKELY(!GetDocument().PopoverAutoShowing())) { + return; + } + // TODO(crbug.com/1307772): We could add more early returns by checking to see + // if the modified element is really a form control that contributed to the + // linking of the popover stack. For example, we could keep track of the set + // of elements which contributed to the current popover stack. + auto& stack = GetDocument().PopoverStack(); + for (int i = stack.size() - 1; i > 0; i--) { + if (FindTopmostPopoverAncestor(*stack[i]) != stack[i - 1]) { + auto* console_message = MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kOther, + mojom::blink::ConsoleMessageLevel::kWarning, + "The ancestral popover relationship was changed due to a " + "modification to a button with a popover target attribute such as " + "adding the disabled attribute, adding the form attribute, or " + "disconnecting it from the document. All open popovers will be " + "closed."); + console_message->SetNodes(GetDocument().GetFrame(), + {DOMNodeIds::IdForNode(this)}); + GetDocument().AddConsoleMessage(console_message); + HTMLElement::HideAllPopoversUntil( + nullptr, GetDocument(), HidePopoverFocusBehavior::kNone, + HidePopoverForcingLevel::kHideImmediately); + return; + } + } +} + void HTMLElement::SetOwnerSelectMenuElement(HTMLSelectMenuElement* element) { DCHECK(RuntimeEnabledFeatures::HTMLSelectMenuElementEnabled()); DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled(
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h index e4f37e88..d311a02 100644 --- a/third_party/blink/renderer/core/html/html_element.h +++ b/third_party/blink/renderer/core/html/html_element.h
@@ -244,6 +244,12 @@ Document&, HidePopoverFocusBehavior, HidePopoverForcingLevel); + // This function checks that the ancestor relationships are still valid for + // the entire popover stack. These can change in various ways, such as a + // triggering element changing its `disabled` attribute. If any relationships + // are invalid, the entire popover stack is closed, and a console warning is + // emitted. + void CheckAndPossiblyClosePopoverStack(); void SetOwnerSelectMenuElement(HTMLSelectMenuElement* element); HTMLSelectMenuElement* ownerSelectMenuElement() const;
diff --git a/third_party/blink/renderer/core/html/html_embed_element.cc b/third_party/blink/renderer/core/html/html_embed_element.cc index 8db538d5..2453e1a4 100644 --- a/third_party/blink/renderer/core/html/html_embed_element.cc +++ b/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -173,7 +173,7 @@ RequestObject(plugin_params); } -bool HTMLEmbedElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool HTMLEmbedElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { if (IsImageType()) return HTMLPlugInElement::LayoutObjectIsNeeded(style);
diff --git a/third_party/blink/renderer/core/html/html_embed_element.h b/third_party/blink/renderer/core/html/html_embed_element.h index a31783f..13fc41a 100644 --- a/third_party/blink/renderer/core/html/html_embed_element.h +++ b/third_party/blink/renderer/core/html/html_embed_element.h
@@ -51,7 +51,7 @@ const AtomicString&, MutableCSSPropertyValueSet*) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; bool IsURLAttribute(const Attribute&) const override; const QualifiedName& SubResourceAttributeName() const override;
diff --git a/third_party/blink/renderer/core/html/html_frame_element.cc b/third_party/blink/renderer/core/html/html_frame_element.cc index 75751c5..2d6abc5 100644 --- a/third_party/blink/renderer/core/html/html_frame_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_element.cc
@@ -37,7 +37,7 @@ frame_border_(true), frame_border_set_(false) {} -bool HTMLFrameElement::LayoutObjectIsNeeded(const ComputedStyle&) const { +bool HTMLFrameElement::LayoutObjectIsNeeded(const DisplayStyle&) const { // For compatibility, frames render even when display: none is set. return ContentFrame(); }
diff --git a/third_party/blink/renderer/core/html/html_frame_element.h b/third_party/blink/renderer/core/html/html_frame_element.h index 73693343..f2ae16c 100644 --- a/third_party/blink/renderer/core/html/html_frame_element.h +++ b/third_party/blink/renderer/core/html/html_frame_element.h
@@ -49,7 +49,7 @@ } private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void ParseAttribute(const AttributeModificationParams&) override;
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.cc b/third_party/blink/renderer/core/html/html_frame_set_element.cc index 3d8a4c3..a14c4d45 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_set_element.cc
@@ -408,7 +408,7 @@ } bool HTMLFrameSetElement::LayoutObjectIsNeeded( - const ComputedStyle& style) const { + const DisplayStyle& style) const { // For compatibility, frames layoutObject even when display: none is set. return true; }
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.h b/third_party/blink/renderer/core/html/html_frame_set_element.h index 25f4876..4b4a3ac4 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.h +++ b/third_party/blink/renderer/core/html/html_frame_set_element.h
@@ -89,7 +89,7 @@ MutableCSSPropertyValueSet*) override; void AttachLayoutTree(AttachContext&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void DefaultEventHandler(Event&) override;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index daabe3e5..1c3a152 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -443,7 +443,7 @@ return container_policy; } -bool HTMLIFrameElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool HTMLIFrameElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { return ContentFrame() && !collapsed_by_client_ && HTMLElement::LayoutObjectIsNeeded(style); }
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.h b/third_party/blink/renderer/core/html/html_iframe_element.h index d3b5499..70d8212 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.h +++ b/third_party/blink/renderer/core/html/html_iframe_element.h
@@ -76,7 +76,7 @@ InsertionNotificationRequest InsertedInto(ContainerNode&) override; void RemovedFrom(ContainerNode&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; bool IsInteractiveContent() const override;
diff --git a/third_party/blink/renderer/core/html/html_no_embed_element.cc b/third_party/blink/renderer/core/html/html_no_embed_element.cc index 691a6d3..0206514 100644 --- a/third_party/blink/renderer/core/html/html_no_embed_element.cc +++ b/third_party/blink/renderer/core/html/html_no_embed_element.cc
@@ -40,8 +40,7 @@ HTMLNoEmbedElement::HTMLNoEmbedElement(Document& document) : HTMLElement(html_names::kNoembedTag, document) {} -bool HTMLNoEmbedElement::LayoutObjectIsNeeded( - const ComputedStyle& style) const { +bool HTMLNoEmbedElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { if (GetDocument().GetFrame()->Loader().AllowPlugins()) return false; return Element::LayoutObjectIsNeeded(style);
diff --git a/third_party/blink/renderer/core/html/html_no_embed_element.h b/third_party/blink/renderer/core/html/html_no_embed_element.h index 83cdb25..dee69abe 100644 --- a/third_party/blink/renderer/core/html/html_no_embed_element.h +++ b/third_party/blink/renderer/core/html/html_no_embed_element.h
@@ -42,7 +42,7 @@ explicit HTMLNoEmbedElement(Document&); private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_no_script_element.cc b/third_party/blink/renderer/core/html/html_no_script_element.cc index e2d87dc..a1ef05d38 100644 --- a/third_party/blink/renderer/core/html/html_no_script_element.cc +++ b/third_party/blink/renderer/core/html/html_no_script_element.cc
@@ -41,7 +41,7 @@ : HTMLElement(html_names::kNoscriptTag, document) {} bool HTMLNoScriptElement::LayoutObjectIsNeeded( - const ComputedStyle& style) const { + const DisplayStyle& style) const { if (GetExecutionContext()->CanExecuteScripts(kNotAboutToExecuteScript)) return false; return Element::LayoutObjectIsNeeded(style);
diff --git a/third_party/blink/renderer/core/html/html_no_script_element.h b/third_party/blink/renderer/core/html/html_no_script_element.h index eadb0a66..99bc5e03 100644 --- a/third_party/blink/renderer/core/html/html_no_script_element.h +++ b/third_party/blink/renderer/core/html/html_no_script_element.h
@@ -42,7 +42,7 @@ explicit HTMLNoScriptElement(Document&); private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index c94e295..7bfbdddb 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -647,7 +647,8 @@ bool HTMLMediaElement::ShouldReusePlayer(Document& old_document, Document& new_document) const { - if (!RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled()) { + if (!RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled( + GetExecutionContext())) { return false; } @@ -800,7 +801,7 @@ ScheduleTextTrackResourceLoad(); } -bool HTMLMediaElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool HTMLMediaElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { return ShouldShowControls() && HTMLElement::LayoutObjectIsNeeded(style); }
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index 138170ce..53f8fad 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -494,7 +494,7 @@ bool SupportsFocus() const final; bool IsMouseFocusable() const final; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void DidNotifySubtreeInsertionsToDocument() override; void DidRecalcStyle(const StyleRecalcChange) final;
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index 8c53b16..c1ed86c 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -144,7 +144,7 @@ HTMLMediaElement::ContextDestroyed(); } -bool HTMLVideoElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool HTMLVideoElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { return HTMLElement::LayoutObjectIsNeeded(style); }
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.h b/third_party/blink/renderer/core/html/media/html_video_element.h index a91b6c4d..e6fc388 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.h +++ b/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -178,7 +178,7 @@ // ExecutionContextLifecycleStateObserver functions. void ContextDestroyed() final; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; void AttachLayoutTree(AttachContext&) override; void UpdatePosterImage();
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc index 3b79082e..59e2ff7 100644 --- a/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc +++ b/third_party/blink/renderer/core/html/parser/html_document_parser_fastpath.cc
@@ -477,14 +477,41 @@ } } + struct ScanTextResult { + // HTML strings of the form '\n<space>*' are widespread on the web. Caching + // them saves us allocations, which improves the runtime. + String TryCanonicalizeString() const { + DCHECK(!text.empty()); + if (is_newline_then_whitespace_string && + text.size() < WTF::NewlineThenWhitespaceStringsTable::kTableSize) { +#if DCHECK_IS_ON() + DCHECK(WTF::NewlineThenWhitespaceStringsTable::IsNewlineThenWhitespaces( + String(text.data(), static_cast<unsigned>(text.size())))); +#endif // DCHECK_IS_ON() + return WTF::NewlineThenWhitespaceStringsTable::GetStringForLength( + text.size()); + } + return String(text.data(), static_cast<unsigned>(text.size())); + } + + Span text; + USpan escaped_text; + bool is_newline_then_whitespace_string = false; + }; + // We first try to scan text as an unmodified subsequence of the input. // However, if there are escape sequences, we have to copy the text to a // separate buffer and we might go outside of `Char` range if we are in an // `LChar` parser. Therefore, this function returns either a `Span` or a // `USpan`. Callers distinguish the two cases by checking if the `Span` is // empty, as only one of them can be non-empty. - std::pair<Span, USpan> ScanText() { + ScanTextResult ScanText() { const Char* start = pos_; + bool is_newline_then_whitespace_string = false; + if (pos_ != end_ && *pos_ == '\n') { + is_newline_then_whitespace_string = true; + ++pos_; + } while (pos_ != end_ && *pos_ != '<') { // '&' indicates escape sequences, '\r' might require // https://infra.spec.whatwg.org/#normalize-newlines @@ -493,11 +520,16 @@ return {Span{}, ScanEscapedText()}; } else if (UNLIKELY(*pos_ == '\0')) { return Fail(HtmlFastPathResult::kFailedContainsNull, - std::pair{Span{}, USpan{}}); + ScanTextResult{Span{}, USpan{}}); + } + if (*pos_ != ' ') { + is_newline_then_whitespace_string = false; } ++pos_; } - return {{start, static_cast<size_t>(pos_ - start)}, USpan{}}; + return {{start, static_cast<size_t>(pos_ - start)}, + USpan{}, + is_newline_then_whitespace_string}; } // Slow-path of `ScanText()`, which supports escape sequences by copying to a @@ -795,25 +827,26 @@ template <class ParentTag> void ParseChildren(ContainerNode* parent) { while (true) { - std::pair<Span, USpan> text = ScanText(); + ScanTextResult scanned_text = ScanText(); if (failed_) { return; } - DCHECK(text.first.empty() || text.second.empty()); - if (!text.first.empty()) { - if (text.first.size() >= Text::kDefaultLengthLimit) { + DCHECK(scanned_text.text.empty() || scanned_text.escaped_text.empty()); + if (!scanned_text.text.empty()) { + const auto text = scanned_text.text; + if (text.size() >= Text::kDefaultLengthLimit) { + return Fail(HtmlFastPathResult::kFailedBigText); + } + parent->ParserAppendChild( + Text::Create(document_, scanned_text.TryCanonicalizeString())); + } else if (!scanned_text.escaped_text.empty()) { + if (scanned_text.escaped_text.size() >= Text::kDefaultLengthLimit) { return Fail(HtmlFastPathResult::kFailedBigText); } parent->ParserAppendChild(Text::Create( - document_, String(text.first.data(), - static_cast<unsigned>(text.first.size())))); - } else if (!text.second.empty()) { - if (text.second.size() >= Text::kDefaultLengthLimit) { - return Fail(HtmlFastPathResult::kFailedBigText); - } - parent->ParserAppendChild(Text::Create( - document_, String(text.second.data(), - static_cast<unsigned>(text.second.size())))); + document_, + String(scanned_text.escaped_text.data(), + static_cast<unsigned>(scanned_text.escaped_text.size())))); } if (pos_ == end_) { return;
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc index a7ee65b..c6cfcfec 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -96,6 +96,10 @@ kFormAutocompleteAttributeEmptyError: return protocol::Audits::GenericIssueErrorTypeEnum:: FormAutocompleteAttributeEmptyError; + case mojom::blink::GenericIssueErrorType:: + kFormEmptyIdAndNameAttributesForInputError: + return protocol::Audits::GenericIssueErrorTypeEnum:: + FormEmptyIdAndNameAttributesForInputError; } }
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc index 939d4b4..29a1679 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -609,7 +609,6 @@ // The result->append()'ed types should be exactly the same as in // collectFlatRules(). switch (data->type) { - case StyleRule::kStyle: case StyleRule::kImport: case StyleRule::kPage: case StyleRule::kFontFace: @@ -617,6 +616,7 @@ case StyleRule::kFontFeature: result->push_back(data); break; + case StyleRule::kStyle: case StyleRule::kMedia: case StyleRule::kScope: case StyleRule::kSupports: @@ -637,6 +637,10 @@ if (!rule) return nullptr; + if (auto* style_rule = DynamicTo<CSSStyleRule>(rule)) { + return style_rule->cssRules(); + } + if (auto* media_rule = DynamicTo<CSSMediaRule>(rule)) return media_rule->cssRules(); @@ -669,7 +673,6 @@ // The result->append()'ed types should be exactly the same as in // flattenSourceData(). switch (rule->GetType()) { - case CSSRule::kStyleRule: case CSSRule::kImportRule: case CSSRule::kCharsetRule: case CSSRule::kPageRule: @@ -679,6 +682,7 @@ case CSSRule::kFontFeatureRule: result->push_back(rule); break; + case CSSRule::kStyleRule: case CSSRule::kMediaRule: case CSSRule::kScopeRule: case CSSRule::kSupportsRule:
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 12f0fc4b..860aba7 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -3400,6 +3400,7 @@ // |layout_results_| is particularly critical when side effects are disabled. DCHECK(!NGDisableSideEffectsScope::IsDisabled()); layout_results_.push_back(std::move(result)); + SetHasValidCachedGeometry(false); CheckDidAddFragment(*this, fragment); if (layout_results_.size() > 1) @@ -3430,6 +3431,7 @@ // |layout_results_| is particularly critical when side effects are disabled. DCHECK(!NGDisableSideEffectsScope::IsDisabled()); layout_results_[index] = std::move(result); + SetHasValidCachedGeometry(false); CheckDidAddFragment(*this, fragment, index); if (got_new_fragment && !fragment.BreakToken()) { @@ -3507,6 +3509,7 @@ if (layout_results_.size() > 1) FragmentCountOrSizeDidChange(); layout_results_.Shrink(results_to_keep); + SetHasValidCachedGeometry(false); } void LayoutBox::InvalidateItems(const NGLayoutResult& result) { @@ -7676,9 +7679,17 @@ LayoutSize LayoutBox::Size() const { NOT_DESTROYED(); - if (!RuntimeEnabledFeatures::LayoutNGNoCopyBackEnabled()) { - return frame_size_; + if (RuntimeEnabledFeatures::LayoutNGNoCopyBackEnabled() && + !HasValidCachedGeometry()) { + // const_cast in order to update the cached value. + const_cast<LayoutBox*>(this)->SetHasValidCachedGeometry(true); + const_cast<LayoutBox*>(this)->frame_size_ = ComputeSize(); } + return frame_size_; +} + +LayoutSize LayoutBox::ComputeSize() const { + NOT_DESTROYED(); const auto& results = GetLayoutResults(); if (results.size() == 0) { return LayoutSize();
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 158f869..26be2516 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -2405,6 +2405,9 @@ bool BackgroundClipBorderBoxIsEquivalentToPaddingBox() const; + // Compute the border-box size from physical fragments. + LayoutSize ComputeSize() const; + // The CSS border box rect for this box. // // The rectangle is in LocationContainer's physical coordinates in flipped
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content_test.cc b/third_party/blink/renderer/core/layout/layout_embedded_content_test.cc index 5e0275d..95582b0 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content_test.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_content_test.cc
@@ -43,9 +43,7 @@ } private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { - return true; - } + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return true; } LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override { return MakeGarbageCollected<LayoutFreezableIFrame>(this);
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 02faebf..53a34f3 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -3973,6 +3973,17 @@ bitfields_.SetMightTraversePhysicalFragments(b); } + // See LayoutObjectBitfields::has_valid_cached_geometry_. + void SetHasValidCachedGeometry(bool b) { + NOT_DESTROYED(); + bitfields_.SetHasValidCachedGeometry(b); + } + // See LayoutObjectBitfields::has_valid_cached_geometry_. + bool HasValidCachedGeometry() const { + NOT_DESTROYED(); + return bitfields_.HasValidCachedGeometry(); + } + private: gfx::QuadF LocalToAncestorQuadInternal(const gfx::QuadF&, const LayoutBoxModelObject* ancestor, @@ -4194,7 +4205,8 @@ whitespace_children_may_change_(false), needs_devtools_info_(false), may_have_anchor_query_(false), - has_broken_spine_(false) {} + has_broken_spine_(false), + has_valid_cached_geometry_(false) {} // Self needs layout for style means that this layout object is marked for a // full layout. This is the default layout but it is expensive as it @@ -4556,6 +4568,11 @@ // the vertebra for this object at that point - i.e. update the associated // layout results, by reading out the post-layout results from the children. ADD_BOOLEAN_BITFIELD(has_broken_spine_, HasBrokenSpine); + + // True if LayoutBox::frame_size_ has the latest value computed from its + // physical fragments. + // This is set to false when LayoutBox::layout_results_ is updated. + ADD_BOOLEAN_BITFIELD(has_valid_cached_geometry_, HasValidCachedGeometry); }; #undef ADD_BOOLEAN_BITFIELD
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 247afc9..8d8a9ee 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -2353,18 +2353,28 @@ // origin and the ancestor chain bit is kSameSite. The ancestor chain bit // should be fine as it's from the same StorageKey that already had a nonce, // but it's possible `security_origin` doesn't match the StorageKey's site. - // TODO(https://crbug.com/888079): Just use the origin in the storage key. + // TODO(https://crbug.com/1410254): Cleanup this logic. BlinkSchemefulSite top_level_site(security_origin); if (!storage_key_.GetNonce()) { top_level_site = storage_key_with_3psp.GetTopLevelSite(); } + // If `security_origin` does not match `top_level_site` we must ensure + // `ancestor_chain_bit` is kCrossSite as long as the top level site isn't + // opaque. + // TODO(https://crbug.com/1410254): Cleanup this logic. + mojom::blink::AncestorChainBit ancestor_chain_bit = + storage_key_with_3psp.GetAncestorChainBit(); + if (!top_level_site.IsOpaque() && + BlinkSchemefulSite(security_origin) != top_level_site) { + ancestor_chain_bit = mojom::blink::AncestorChainBit::kCrossSite; + } + // TODO(https://crbug.com/888079): Just use the storage key sent by the // browser once the browser will be able to compute the origin in all cases. - frame_->DomWindow()->SetStorageKey( - BlinkStorageKey(security_origin, top_level_site, - base::OptionalToPtr(storage_key_.GetNonce()), - storage_key_with_3psp.GetAncestorChainBit())); + frame_->DomWindow()->SetStorageKey(BlinkStorageKey( + security_origin, top_level_site, + base::OptionalToPtr(storage_key_.GetNonce()), ancestor_chain_bit)); if (storage_key_ == session_storage_key_ || storage_key_.GetSecurityOrigin()->IsOpaque() || session_storage_key_.GetSecurityOrigin()->IsOpaque()) {
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc index 8184d7f..1222881 100644 --- a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc +++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
@@ -103,7 +103,7 @@ response_.status, TrialToken::CreateTrialTokenForTesting( origin.origin, false, response_.feature, response_.expiry, false, - TrialToken::UsageRestriction::kNone)); + TrialToken::UsageRestriction::kNone, "")); } }
diff --git a/third_party/blink/renderer/core/page/drag_image.cc b/third_party/blink/renderer/core/page/drag_image.cc index b80081f..d4be264 100644 --- a/third_party/blink/renderer/core/page/drag_image.cc +++ b/third_party/blink/renderer/core/page/drag_image.cc
@@ -258,8 +258,7 @@ } label_font.DrawBidiText(resource_provider->Canvas(), TextRunPaintInfo(text_run), gfx::PointF(text_pos), - Font::kDoNotPaintIfFontNotReady, device_scale_factor, - text_paint); + Font::kDoNotPaintIfFontNotReady, text_paint); scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot(); return DragImage::Create(image.get(), kRespectImageOrientation);
diff --git a/third_party/blink/renderer/core/paint/document_marker_painter.cc b/third_party/blink/renderer/core/paint/document_marker_painter.cc index f9645802..fe8e0083 100644 --- a/third_party/blink/renderer/core/paint/document_marker_painter.cc +++ b/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -108,8 +108,8 @@ cc::PaintFlags flags; flags.setAntiAlias(true); flags.setShader(PaintShader::MakePaintRecord( - marker, SkRect::MakeWH(kMarkerWidth, kMarkerHeight), SkTileMode::kRepeat, - SkTileMode::kClamp, &local_matrix)); + std::move(marker), SkRect::MakeWH(kMarkerWidth, kMarkerHeight), + SkTileMode::kRepeat, SkTileMode::kClamp, &local_matrix)); // Apply the origin translation as a global transform. This ensures that the // shader local matrix depends solely on zoom => Skia can reuse the same
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc index 9b29196f..d2c9cba 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
@@ -392,10 +392,9 @@ return; Vector<Font::TextIntercept> text_intercepts; - font_.GetTextIntercepts( - fragment_paint_info, graphics_context_.DeviceScaleFactor(), - graphics_context_.FillFlags(), - std::make_tuple(upper, upper + stripe_width), text_intercepts); + font_.GetTextIntercepts(fragment_paint_info, graphics_context_.FillFlags(), + std::make_tuple(upper, upper + stripe_width), + text_intercepts); DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts); }
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc index 6c53009..e27fdaa 100644 --- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc +++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -298,9 +298,7 @@ if (scrollable_area_->ShouldDirectlyCompositeScrollbar(scrollbar)) scroll_translation = properties->ScrollTranslation(); - auto delegate = base::MakeRefCounted<ScrollbarLayerDelegate>( - scrollbar, context.DeviceScaleFactor()); - + auto delegate = base::MakeRefCounted<ScrollbarLayerDelegate>(scrollbar); ScrollbarDisplayItem::Record(context, scrollbar, type, delegate, visual_rect, scroll_translation, scrollbar.GetElementId()); }
diff --git a/third_party/blink/renderer/core/paint/text_painter.cc b/third_party/blink/renderer/core/paint/text_painter.cc index 408ab02..c61fbb2 100644 --- a/third_party/blink/renderer/core/paint/text_painter.cc +++ b/third_party/blink/renderer/core/paint/text_painter.cc
@@ -209,10 +209,9 @@ return; Vector<Font::TextIntercept> text_intercepts; - font_.GetTextIntercepts( - text_run_paint_info, graphics_context_.DeviceScaleFactor(), - graphics_context_.FillFlags(), - std::make_tuple(upper, upper + stripe_width), text_intercepts); + font_.GetTextIntercepts(text_run_paint_info, graphics_context_.FillFlags(), + std::make_tuple(upper, upper + stripe_width), + text_intercepts); DecorationsStripeIntercepts(upper, stripe_width, dilation, text_intercepts); }
diff --git a/third_party/blink/renderer/core/script/modulator.cc b/third_party/blink/renderer/core/script/modulator.cc index 8dd65c5..146c0af 100644 --- a/third_party/blink/renderer/core/script/modulator.cc +++ b/third_party/blink/renderer/core/script/modulator.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/workers/worklet_global_scope.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" +#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h" namespace blink {
diff --git a/third_party/blink/renderer/core/script/modulator.h b/third_party/blink/renderer/core/script/modulator.h index 3904fff6..8ef3392 100644 --- a/third_party/blink/renderer/core/script/modulator.h +++ b/third_party/blink/renderer/core/script/modulator.h
@@ -21,7 +21,6 @@ #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -36,6 +35,7 @@ class ReferrerScriptInfo; class ResourceFetcher; class ModuleRecordResolver; +class ScriptFetchOptions; class ScriptPromiseResolver; class ScriptState; enum class ModuleType;
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc index d40e471..0b7feb5 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc +++ b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
@@ -22,10 +22,7 @@ STACK_ALLOCATED(); public: - ScopedScrollbarPainter(cc::PaintCanvas& canvas, float device_scale_factor) - : canvas_(canvas) { - builder_->Context().SetDeviceScaleFactor(device_scale_factor); - } + explicit ScopedScrollbarPainter(cc::PaintCanvas& canvas) : canvas_(canvas) {} ~ScopedScrollbarPainter() { canvas_.drawPicture(builder_->EndRecording()); } GraphicsContext& Context() { return builder_->Context(); } @@ -37,9 +34,8 @@ } // namespace -ScrollbarLayerDelegate::ScrollbarLayerDelegate(blink::Scrollbar& scrollbar, - float device_scale_factor) - : scrollbar_(&scrollbar), device_scale_factor_(device_scale_factor) { +ScrollbarLayerDelegate::ScrollbarLayerDelegate(blink::Scrollbar& scrollbar) + : scrollbar_(&scrollbar) { // Custom scrollbars are either non-composited or use cc::PictureLayers // which don't need ScrollbarLayerDelegate. DCHECK(!scrollbar.IsCustomScrollbar()); @@ -160,7 +156,7 @@ return; auto& theme = scrollbar_->GetTheme(); - ScopedScrollbarPainter painter(*canvas, device_scale_factor_); + ScopedScrollbarPainter painter(*canvas); // The canvas coordinate space is relative to the part's origin. switch (part) { case cc::ScrollbarPart::THUMB:
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h index 11f2b321..b2ecf0f 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h +++ b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
@@ -17,8 +17,7 @@ // scrollbar state and to paint the image in the scrollbar. class CORE_EXPORT ScrollbarLayerDelegate : public cc::Scrollbar { public: - ScrollbarLayerDelegate(blink::Scrollbar& scrollbar, - float device_scale_factor); + explicit ScrollbarLayerDelegate(blink::Scrollbar& scrollbar); ScrollbarLayerDelegate(const ScrollbarLayerDelegate&) = delete; ScrollbarLayerDelegate& operator=(const ScrollbarLayerDelegate&) = delete; @@ -55,7 +54,6 @@ bool ShouldPaint() const; Persistent<blink::Scrollbar> scrollbar_; - float device_scale_factor_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc index 68e4c2ee..6a1d2eb 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/html/html_anchor_element.h" #include "third_party/blink/renderer/core/url_pattern/url_pattern.h" @@ -37,6 +38,14 @@ }); } + HeapVector<Member<StyleRule>> GetStyleRules() const override { + HeapVector<Member<StyleRule>> rules; + for (DocumentRulePredicate* clause : clauses_) { + rules.AppendVector(clause->GetStyleRules()); + } + return rules; + } + String ToString() const override { StringBuilder builder; builder.Append("And("); @@ -79,6 +88,14 @@ }); } + HeapVector<Member<StyleRule>> GetStyleRules() const override { + HeapVector<Member<StyleRule>> rules; + for (DocumentRulePredicate* clause : clauses_) { + rules.AppendVector(clause->GetStyleRules()); + } + return rules; + } + String ToString() const override { StringBuilder builder; builder.Append("Or("); @@ -118,6 +135,10 @@ return !clause_->Matches(el); } + HeapVector<Member<StyleRule>> GetStyleRules() const override { + return clause_->GetStyleRules(); + } + String ToString() const override { StringBuilder builder; builder.Append("Not("); @@ -168,6 +189,8 @@ return false; } + HeapVector<Member<StyleRule>> GetStyleRules() const override { return {}; } + String ToString() const override { StringBuilder builder; builder.Append("Href(["); @@ -203,10 +226,33 @@ : style_rules_(std::move(style_rules)) {} bool Matches(const HTMLAnchorElement& link) const override { - // TODO(crbug.com/1371522): Implement this. + // TODO(crbug.com/1371522): We should be able to assert that style is clean + // here (i.e. we have computed the latest matched selectors for a link), + // otherwise we might be using stale results and preloading extra URLs. + // TODO(crbug.com/1371522): We need to deal with "display: none" elements, + // they will not have a ComputedStyle (even if style is clean). + const ComputedStyle* computed_style = link.GetComputedStyle(); + if (!computed_style) { + return false; + } + const Persistent<HeapHashSet<WeakMember<StyleRule>>>& matched_selectors = + computed_style->DocumentRulesSelectors(); + if (!matched_selectors) { + return false; + } + + for (StyleRule* style_rule : style_rules_) { + if (matched_selectors->Contains(style_rule)) { + return true; + } + } return false; } + HeapVector<Member<StyleRule>> GetStyleRules() const override { + return style_rules_; + } + String ToString() const override { StringBuilder builder; builder.Append("Selector(["); @@ -232,16 +278,22 @@ } private: - // TODO(crbug.com/1371522): If we do not end up integrating with the - // style engine, change this to use CSSSelectorList instead of StyleRule to - // save space. HeapVector<Member<StyleRule>> style_rules_; }; namespace { +// If `out_error` is provided and hasn't already had a message set, sets it to +// `message`. +void SetParseErrorMessage(String* out_error, String message) { + if (out_error && out_error->IsNull()) { + *out_error = message; + } +} + URLPattern* ParseRawPattern(JSONValue* raw_pattern, const KURL& base_url, - ExceptionState& exception_state) { + ExceptionState& exception_state, + String* out_error) { // If rawPattern is a string, then: if (String raw_string; raw_pattern->AsString(&raw_string)) { // Set pattern to the result of constructing a URLPattern using the @@ -264,30 +316,38 @@ String key = entry.first; String value; // If value is not a string - if (!entry.second->AsString(&value)) + if (!entry.second->AsString(&value)) { + SetParseErrorMessage( + out_error, "Values for a URL pattern object must be strings."); return nullptr; + } // Set init[key] to value. - if (key == "protocol") + if (key == "protocol") { init->setProtocol(value); - else if (key == "username") + } else if (key == "username") { init->setUsername(value); - else if (key == "password") + } else if (key == "password") { init->setPassword(value); - else if (key == "hostname") + } else if (key == "hostname") { init->setHostname(value); - else if (key == "port") + } else if (key == "port") { init->setPort(value); - else if (key == "pathname") + } else if (key == "pathname") { init->setPathname(value); - else if (key == "search") + } else if (key == "search") { init->setSearch(value); - else if (key == "hash") + } else if (key == "hash") { init->setHash(value); - else if (key == "baseURL") + } else if (key == "baseURL") { init->setBaseURL(value); - else + } else { + SetParseErrorMessage( + out_error, + String::Format("Invalid key \"%s\" for a URL pattern object found.", + key.Latin1().c_str())); return nullptr; + } } // Set pattern to the result of constructing a URLPattern using the @@ -296,23 +356,38 @@ MakeGarbageCollected<V8URLPatternInput>(init); return URLPattern::Create(url_pattern_input, exception_state); } + SetParseErrorMessage(out_error, + "Value for \"href_matches\" should either be a " + "string, an object, or a list of strings and objects."); return nullptr; } -String GetPredicateType(JSONObject* input) { +String GetPredicateType(JSONObject* input, String* out_error) { String predicate_type; constexpr const char* kValidTypes[] = {"and", "or", "not", "href_matches", "selector_matches"}; for (String type : kValidTypes) { if (input->Get(type)) { // If we'd already found one, then this is ambiguous. - if (!predicate_type.IsNull()) + if (!predicate_type.IsNull()) { + SetParseErrorMessage( + out_error, + String::Format("Document rule predicate type is ambiguous, " + "two types found: \"%s\" and \"%s\".", + predicate_type.Latin1().c_str(), + type.Latin1().c_str())); return String(); + } // Otherwise, this is the predicate type. predicate_type = std::move(type); } } + if (predicate_type.IsNull()) { + SetParseErrorMessage(out_error, + "Could not infer type of document rule predicate, no " + "valid type specified."); + } return predicate_type; } } // namespace @@ -322,27 +397,41 @@ JSONObject* input, const KURL& ruleset_base_url, const ExecutionContext* execution_context, - ExceptionState& exception_state) { + ExceptionState& exception_state, + String* out_error) { // If input is not a map, then return null. - if (!input) + if (!input) { + SetParseErrorMessage(out_error, + "Document rule predicate must be an object."); return nullptr; + } // If we can't get a valid predicate type, return null. - String predicate_type = GetPredicateType(input); + String predicate_type = GetPredicateType(input, out_error); if (predicate_type.IsNull()) return nullptr; // If predicateType is "and" or "or" if (predicate_type == "and" || predicate_type == "or") { // "and" and "or" cannot be paired with any other keys. - if (input->size() != 1) + if (input->size() != 1) { + SetParseErrorMessage( + out_error, + String::Format( + "Document rule predicate with \"%s\" key cannot have other keys.", + predicate_type.Latin1().c_str())); return nullptr; + } // Let rawClauses be the input[predicateType]. blink::JSONArray* raw_clauses = input->GetArray(predicate_type); // If rawClauses is not a list, then return null. - if (!raw_clauses) + if (!raw_clauses) { + SetParseErrorMessage( + out_error, String::Format("\"%s\" key should have a list value.", + predicate_type.Latin1().c_str())); return nullptr; + } // Let clauses be an empty list. HeapVector<Member<DocumentRulePredicate>> clauses; @@ -352,8 +441,9 @@ JSONObject* raw_clause = JSONObject::Cast(raw_clauses->at(i)); // Let clause be the result of parsing a document rule predicate given // rawClause and baseURL. - DocumentRulePredicate* clause = Parse(raw_clause, ruleset_base_url, - execution_context, exception_state); + DocumentRulePredicate* clause = + Parse(raw_clause, ruleset_base_url, execution_context, + exception_state, out_error); // If clause is null, then return null. if (!clause) return nullptr; @@ -374,15 +464,20 @@ // If predicateType is "not" if (predicate_type == "not") { // "not" cannot be paired with any other keys. - if (input->size() != 1) + if (input->size() != 1) { + SetParseErrorMessage( + out_error, + "Document rule predicate with \"not\" key cannot have other keys."); return nullptr; + } // Let rawClause be the input[predicateType]. JSONObject* raw_clause = input->GetJSONObject(predicate_type); // Let clause be the result of parsing a document rule predicate given // rawClause and baseURL. DocumentRulePredicate* clause = - Parse(raw_clause, ruleset_base_url, execution_context, exception_state); + Parse(raw_clause, ruleset_base_url, execution_context, exception_state, + out_error); // If clause is null, then return null. if (!clause) @@ -410,11 +505,20 @@ } else if (key == "relative_to") { const char* const kKnownRelativeToValues[] = {"ruleset", "document"}; String relative_to; + if (!relative_to_enabled) { + SetParseErrorMessage(out_error, + "\"relative_to\" is currently unsupported."); + return nullptr; + } // If relativeTo is neither the string "ruleset" nor the string // "document", then return null. - if (!relative_to_enabled || - !input->GetString("relative_to", &relative_to) || + if (!input->GetString("relative_to", &relative_to) || !base::Contains(kKnownRelativeToValues, relative_to)) { + SetParseErrorMessage( + out_error, + String::Format( + "Unrecognized \"relative_to\" value: %s.", + input->Get("relative_to")->ToJSONString().Latin1().c_str())); return nullptr; } // If relativeTo is "document", set baseURL to the document's @@ -424,6 +528,9 @@ } } else { // Otherwise, this is an unrecognized key. The predicate is invalid. + SetParseErrorMessage(out_error, + String::Format("Unrecognized key found: \"%s\".", + key.Latin1().c_str())); return nullptr; } } @@ -444,10 +551,15 @@ // For each rawPattern of rawPatterns: for (JSONValue* raw_pattern : raw_patterns) { URLPattern* pattern = - ParseRawPattern(raw_pattern, base_url, exception_state); + ParseRawPattern(raw_pattern, base_url, exception_state, out_error); // If those steps throw, catch the exception and return null. if (exception_state.HadException()) { exception_state.ClearException(); + SetParseErrorMessage( + out_error, + String::Format( + "URL Pattern for \"href_matches\" could not be parsed: %s.", + raw_pattern->ToJSONString().Latin1().c_str())); return nullptr; } if (!pattern) @@ -464,6 +576,8 @@ const bool selector_matches_enabled = RuntimeEnabledFeatures:: SpeculationRulesDocumentRulesSelectorMatchesEnabled(execution_context); if (!selector_matches_enabled) { + SetParseErrorMessage(out_error, + "\"selector_matches\" is currently unsupported."); return nullptr; } @@ -490,6 +604,9 @@ String raw_selector_string; // If rawSelector is not a string, then return null. if (!raw_selector->AsString(&raw_selector_string)) { + SetParseErrorMessage(out_error, + "Value for \"selector_matches\" must be a string " + "or a list of strings."); return nullptr; } @@ -498,6 +615,9 @@ base::span<CSSSelector> selector_vector = CSSParser::ParseSelector( css_parser_context, nullptr, nullptr, raw_selector_string, arena); if (selector_vector.empty()) { + SetParseErrorMessage( + out_error, String::Format("\"%s\" is not a valid selector.", + raw_selector_string.Latin1().c_str())); return nullptr; } StyleRule* selector =
diff --git a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h index 12508d8..e199d47 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h +++ b/third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h
@@ -30,12 +30,14 @@ static DocumentRulePredicate* Parse(JSONObject* input, const KURL& ruleset_base_url, const ExecutionContext* context, - ExceptionState& exception_state); + ExceptionState& exception_state, + String* out_error = nullptr); // Creates a predicate that matches with any link (i.e. Matches() below will // always returns true). static DocumentRulePredicate* MakeDefaultPredicate(); virtual bool Matches(const HTMLAnchorElement& link) const = 0; + virtual HeapVector<Member<StyleRule>> GetStyleRules() const = 0; // Methods for testing. enum class Type { kAnd, kOr, kNot, kURLPatterns, kCSSSelectors };
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc index f60c95c7..8049590 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -8,6 +8,8 @@ #include "base/ranges/algorithm.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-shared.h" +#include "third_party/blink/renderer/core/css/style_engine.h" +#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/dom/shadow_including_tree_order_traversal.h" #include "third_party/blink/renderer/core/execution_context/agent.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -175,6 +177,9 @@ WebFeature::kSpeculationRulesDocumentRules); InitializeIfNecessary(); InvalidateAllLinks(); + if (!rule_set->selectors().empty()) { + UpdateSelectors(); + } } QueueUpdateSpeculationCandidates(); } @@ -183,8 +188,12 @@ auto* it = base::ranges::remove(rule_sets_, rule_set); DCHECK(it != rule_sets_.end()) << "rule set was removed without existing"; rule_sets_.erase(it, rule_sets_.end()); - if (rule_set->has_document_rule()) + if (rule_set->has_document_rule()) { InvalidateAllLinks(); + if (!rule_set->selectors().empty()) { + UpdateSelectors(); + } + } QueueUpdateSpeculationCandidates(); } @@ -284,6 +293,13 @@ QueueUpdateSpeculationCandidates(); } +void DocumentSpeculationRules::LinkMatchedSelectorsUpdated( + HTMLAnchorElement* link) { + DCHECK(initialized_); + InvalidateLink(link); + QueueUpdateSpeculationCandidates(); +} + void DocumentSpeculationRules::Trace(Visitor* visitor) const { Supplement::Trace(visitor); visitor->Trace(rule_sets_); @@ -292,6 +308,7 @@ visitor->Trace(matched_links_); visitor->Trace(unmatched_links_); visitor->Trace(pending_links_); + visitor->Trace(selectors_); } mojom::blink::SpeculationHost* DocumentSpeculationRules::GetHost() { @@ -396,6 +413,7 @@ sent_is_part_of_no_vary_search_trial_ = true; host->EnableNoVarySearchSupport(); } + host->UpdateSpeculationCandidates(std::move(candidates)); } @@ -554,4 +572,22 @@ unmatched_links_.clear(); } +void DocumentSpeculationRules::UpdateSelectors() { + ExecutionContext* execution_context = + GetSupplementable()->GetExecutionContext(); + if (!RuntimeEnabledFeatures:: + SpeculationRulesDocumentRulesSelectorMatchesEnabled( + execution_context)) { + return; + } + + HeapVector<Member<StyleRule>> selectors; + for (SpeculationRuleSet* rule_set : rule_sets_) { + selectors.AppendVector(rule_set->selectors()); + } + + selectors_ = std::move(selectors); + GetSupplementable()->GetStyleEngine().DocumentRulesSelectorsChanged(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h index 51836fb..af7ddd2 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
@@ -55,6 +55,9 @@ void RelAttributeChanged(HTMLAnchorElement* link); void DocumentReferrerPolicyChanged(); void DocumentBaseURLChanged(); + void LinkMatchedSelectorsUpdated(HTMLAnchorElement* link); + + const HeapVector<Member<StyleRule>>& selectors() { return selectors_; } void Trace(Visitor*) const override; @@ -85,6 +88,9 @@ void InvalidateLink(HTMLAnchorElement* link); void InvalidateAllLinks(); + // Populates |selectors_| and notifies the StyleEngine. + void UpdateSelectors(); + HeapVector<Member<SpeculationRuleSet>> rule_sets_; HeapMojoRemote<mojom::blink::SpeculationHost> host_; HeapHashSet<Member<SpeculationRuleLoader>> speculation_rule_loaders_; @@ -104,6 +110,10 @@ HeapHashSet<Member<HTMLAnchorElement>> unmatched_links_; HeapHashSet<Member<HTMLAnchorElement>> pending_links_; + // Collects every CSS selector from every CSS selector document rule predicate + // in this document's speculation rules. + HeapVector<Member<StyleRule>> selectors_; + bool has_pending_update_ = false; bool initialized_ = false; bool sent_is_part_of_no_vary_search_trial_ = false;
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc index 6005a188..c0087c50 100644 --- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc +++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.cc
@@ -7,6 +7,7 @@ #include "base/containers/contains.h" #include "base/feature_list.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" +#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/speculation_rules/document_rule_predicate.h" @@ -168,13 +169,24 @@ } } - // TODO(mcnee): Populate `out_error` for document rule warnings. DocumentRulePredicate* document_rule_predicate = nullptr; if (source == "document") { DCHECK(document_rules_enabled); // If input["urls"] exists, then return null. - if (input->Get("urls")) + if (input->Get("urls")) { + SetParseErrorMessage(out_error, + "A document rule cannot have a \"urls\" key."); return nullptr; + } + + // "relative_to" outside the "href_matches" clause is not allowed for + // document rules. + if (input->Get("relative_to")) { + SetParseErrorMessage(out_error, + "A document rule cannot have \"relative_to\" " + "outside the \"where\" clause."); + return nullptr; + } // If input["where"] does not exist, then set predicate to a document rule // conjunction whose clauses is an empty list. @@ -184,13 +196,9 @@ // Otherwise, set predicate to the result of parsing a document rule // predicate given input["where"] and baseURL. else { - // "relative_to" outside the "href_matches" clause is not allowed for - // document rules. - if (input->Get("relative_to")) - return nullptr; - document_rule_predicate = - DocumentRulePredicate::Parse(input->GetJSONObject("where"), base_url, - context, IGNORE_EXCEPTION_FOR_TESTING); + document_rule_predicate = DocumentRulePredicate::Parse( + input->GetJSONObject("where"), base_url, context, + IGNORE_EXCEPTION_FOR_TESTING, out_error); } if (!document_rule_predicate) return nullptr; @@ -427,8 +435,10 @@ continue; } - if (rule->predicate()) + if (rule->predicate()) { result->has_document_rule_ = true; + result->selectors_.AppendVector(rule->predicate()->GetStyleRules()); + } // Append rule to result's prefetch/prerender rules. destination.push_back(rule); @@ -454,6 +464,7 @@ visitor->Trace(prefetch_with_subresources_rules_); visitor->Trace(prerender_rules_); visitor->Trace(source_); + visitor->Trace(selectors_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h index bce88cd..6d893ca 100644 --- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h +++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h
@@ -16,6 +16,7 @@ class ExecutionContext; class KURL; class SpeculationRule; +class StyleRule; // A set of rules generated from a single <script type=speculationrules>, which // provides rules to identify URLs and corresponding conditions for speculation, @@ -68,6 +69,8 @@ Source* source() const { return source_; } + const HeapVector<Member<StyleRule>>& selectors() { return selectors_; } + void Trace(Visitor*) const; private: @@ -77,6 +80,7 @@ // The original source is reused to reparse speculation rule sets when the // document base URL changes. Member<Source> source_; + HeapVector<Member<StyleRule>> selectors_; bool has_document_rule_ = false; };
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc index c326916..c2626a9 100644 --- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc +++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -671,6 +671,23 @@ }); } +// Same as above, except it runs a style update after the functor and before +// performing a microtask checkpoint. +template <typename F> +void PropagateRulesToStubSpeculationHostWithStyleUpdate( + DummyPageHolder& page_holder, + StubSpeculationHost& speculation_host, + const F& functor) { + PropagateRulesToStubSpeculationHost(page_holder, speculation_host, [&]() { + auto* script_state = ToScriptStateForMainWorld(&page_holder.GetFrame()); + v8::MicrotasksScope microtasks_scope(script_state->GetIsolate(), + ToMicrotaskQueue(script_state), + v8::MicrotasksScope::kRunMicrotasks); + functor(); + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + }); +} + // This function adds a speculationrules script to the given page, and simulates // the process of sending the parsed candidates to the browser. void PropagateRulesToStubSpeculationHost(DummyPageHolder& page_holder, @@ -681,6 +698,44 @@ }); } +// Similar to the function above, but also runs a full lifecycle update. +void PropagateRulesToStubSpeculationHostWithStyleUpdate( + DummyPageHolder& page_holder, + StubSpeculationHost& speculation_host, + const String& speculation_script) { + PropagateRulesToStubSpeculationHost(page_holder, speculation_host, [&]() { + InsertSpeculationRules(page_holder.GetDocument(), speculation_script); + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + }); +} + +template <typename F> +void AssertNoRulesPropogatedToStubSpeculationHost( + DummyPageHolder& page_holder, + StubSpeculationHost& speculation_host, + const F& functor) { + LocalFrame& frame = page_holder.GetFrame(); + auto& broker = frame.DomWindow()->GetBrowserInterfaceBroker(); + broker.SetBinderForTesting( + mojom::blink::SpeculationHost::Name_, + WTF::BindRepeating(&StubSpeculationHost::BindUnsafe, + WTF::Unretained(&speculation_host))); + + base::RunLoop run_loop; + speculation_host.SetDoneClosure( + base::BindLambdaForTesting([]() { NOTREACHED(); })); + { + auto* script_state = ToScriptStateForMainWorld(&frame); + v8::MicrotasksScope microtasks_scope(script_state->GetIsolate(), + ToMicrotaskQueue(script_state), + v8::MicrotasksScope::kRunMicrotasks); + functor(); + } + run_loop.RunUntilIdle(); + + broker.SetBinderForTesting(mojom::blink::SpeculationHost::Name_, {}); +} + TEST_F(SpeculationRuleSetTest, PropagatesAllRulesToBrowser) { DummyPageHolder page_holder; StubSpeculationHost speculation_host; @@ -1195,6 +1250,27 @@ DocumentRulePredicate* CreatePredicate( String where_text, KURL base_url = KURL("https://example.com/")) { + String parse_error; + auto* rule_set = + CreateRuleSetWithPredicate(where_text, base_url, &parse_error); + DCHECK(!rule_set->prefetch_rules().empty()) + << "Invalid predicate: " << parse_error; + return rule_set->prefetch_rules()[0]->predicate(); + } + + String CreateInvalidPredicate(String where_text) { + String parse_error; + auto* rule_set = CreateRuleSetWithPredicate( + where_text, KURL("https://example.com"), &parse_error); + EXPECT_TRUE(!rule_set || rule_set->prefetch_rules().empty()) + << "Rule set is valid."; + return parse_error; + } + + private: + SpeculationRuleSet* CreateRuleSetWithPredicate(String where_text, + KURL base_url, + String* parse_error) { // clang-format off auto* rule_set = CreateRuleSet( @@ -1205,14 +1281,12 @@ "where": {%s} }] })", - where_text.Latin1().c_str()), base_url, execution_context() - ); + where_text.Latin1().c_str()), + base_url, execution_context(), parse_error); // clang-format on - DCHECK(!rule_set->prefetch_rules().empty()) << "Invalid predicate."; - return rule_set->prefetch_rules()[0]->predicate(); + return rule_set; } - private: ScopedSpeculationRulesDocumentRulesForTest enable_document_rules_{true}; }; @@ -1509,6 +1583,132 @@ Neg(And({Href({URLPattern("https://world.com")})}))})))); } +// Tests that errors of individual rules which cause them to be ignored are +// logged to the console. +TEST_F(DocumentRulesTest, ConsoleWarningForInvalidRule) { + auto* chrome_client = MakeGarbageCollected<ConsoleCapturingChromeClient>(); + DummyPageHolder page_holder(/*initial_view_size=*/{}, chrome_client); + page_holder.GetFrame().GetSettings()->SetScriptEnabled(true); + + Document& document = page_holder.GetDocument(); + HTMLScriptElement* script = + MakeGarbageCollected<HTMLScriptElement>(document, CreateElementFlags()); + script->setAttribute(html_names::kTypeAttr, "speculationrules"); + script->setText( + R"({ + "prefetch": [{ + "source": "document", + "where": {"and": [], "or": []} + }] + })"); + document.head()->appendChild(script); + + EXPECT_TRUE(base::ranges::any_of( + chrome_client->ConsoleMessages(), [](const String& message) { + return message.Contains("Document rule predicate type is ambiguous"); + })); +} + +TEST_F(DocumentRulesTest, DocumentRuleParseErrors) { + String parse_error; + CreateRuleSet(R"({"prefetch": [{ + "source": "document", "relative_to": "document" + }]})", + KURL("https://example.com"), execution_context(), &parse_error); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("A document rule cannot have \"relative_to\" " + "outside the \"where\" clause")); + + parse_error = String(); + CreateRuleSet(R"({"prefetch": [{ + "source": "document", + "urls": ["/one", "/two"] + }]})", + KURL("https://example.com"), execution_context(), &parse_error); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("A document rule cannot have a \"urls\" key")); +} + +TEST_F(DocumentRulesTest, DocumentRulePredicateParseErrors) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + selector_matches_enabled{true}; + String parse_error; + + parse_error = CreateInvalidPredicate(R"("and": [], "not": {})"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr( + "Document rule predicate type is ambiguous, two types found")); + + parse_error = CreateInvalidPredicate(R"()"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("Could not infer type of document rule " + "predicate, no valid type specified")); + + parse_error = + CreateInvalidPredicate(R"("not": [{"href_matches": "foo.com"}])"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("Document rule predicate must be an object")); + + parse_error = + CreateInvalidPredicate(R"("and": [], "relative_to": "document")"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr( + "Document rule predicate with \"and\" key cannot have other keys.")); + + parse_error = CreateInvalidPredicate(R"("or": {})"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("\"or\" key should have a list value")); + + parse_error = CreateInvalidPredicate(R"("href_matches": {"port": 1234})"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("Values for a URL pattern object must be strings")); + + parse_error = + CreateInvalidPredicate(R"("href_matches": {"path_name": "foo"})"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("Invalid key \"path_name\" for a URL " + "pattern object found")); + + parse_error = + CreateInvalidPredicate(R"("href_matches": [["bar.com/foo.html"]])"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("Value for \"href_matches\" should " + "either be a string")); + + parse_error = CreateInvalidPredicate( + R"("href_matches": "/home", "relative_to": "window")"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("Unrecognized \"relative_to\" value: \"window\"")); + + parse_error = CreateInvalidPredicate( + R"("href_matches": "/home", "relativeto": "document")"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("Unrecognized key found: \"relativeto\"")); + + parse_error = CreateInvalidPredicate(R"("href_matches": "https//:")"); + EXPECT_THAT(parse_error.Utf8(), + ::testing::HasSubstr("URL Pattern for \"href_matches\" could not " + "be parsed: \"https//:\"")); + + parse_error = CreateInvalidPredicate(R"("selector_matches": {})"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("Value for \"selector_matches\" must be a string")); + + parse_error = + CreateInvalidPredicate(R"("selector_matches": "##bad_selector")"); + EXPECT_THAT( + parse_error.Utf8(), + ::testing::HasSubstr("\"##bad_selector\" is not a valid selector")); +} + TEST_F(DocumentRulesTest, DefaultPredicate) { auto* rule_set = CreateRuleSet( R"({ @@ -2280,6 +2480,299 @@ Selector({StyleRuleWithSelectorText(".interesting-section > a")})); } +TEST_F(DocumentRulesTest, GetStyleRules) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + auto* predicate = CreatePredicate(R"( + "and": [ + {"or": [ + {"not": {"selector_matches": "span.fizz > a"}}, + {"selector_matches": "#bar a"} + ]}, + {"selector_matches": "a.foo"} + ] + )"); + EXPECT_THAT( + predicate, + And({Or({Neg(Selector({StyleRuleWithSelectorText("span.fizz > a")})), + Selector({StyleRuleWithSelectorText("#bar a")})}), + Selector({StyleRuleWithSelectorText("a.foo")})})); + EXPECT_THAT(predicate->GetStyleRules(), + UnorderedElementsAre(StyleRuleWithSelectorText("span.fizz > a"), + StyleRuleWithSelectorText("#bar a"), + StyleRuleWithSelectorText("a.foo"))); +} + +TEST_F(DocumentRulesTest, SelectorMatchesAddsCandidates) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = document.getElementById("important-section"); + auto* unimportant_section = document.getElementById("unimportant-section"); + + AddAnchor(*important_section, "https://foo.com/foo"); + AddAnchor(*unimportant_section, "https://foo.com/bar"); + AddAnchor(*important_section, "https://foo.com/fizz"); + AddAnchor(*unimportant_section, "https://foo.com/buzz"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#important-section > a"} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + const auto& candidates = speculation_host.candidates(); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/foo"), + KURL("https://foo.com/fizz"))); +} + +TEST_F(DocumentRulesTest, SelectorMatchesIsDynamic) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = document.getElementById("important-section"); + auto* unimportant_section = document.getElementById("unimportant-section"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"or": [ + {"selector_matches": "#important-section > a"}, + {"selector_matches": ".important-link"} + ]} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + const auto& candidates = speculation_host.candidates(); + EXPECT_TRUE(candidates.empty()); + + HTMLAnchorElement* second_anchor = nullptr; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, [&]() { + AddAnchor(*important_section, "https://foo.com/fizz"); + second_anchor = AddAnchor(*unimportant_section, "https://foo.com/buzz"); + }); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/fizz"))); + + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, [&]() { + second_anchor->setAttribute(html_names::kClassAttr, "important-link"); + }); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/fizz"), + KURL("https://foo.com/buzz"))); + + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, + [&]() { important_section->SetIdAttribute("random-section"); }); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/buzz"))); +} + +TEST_F(DocumentRulesTest, AddingDocumentRulesInvalidatesStyle) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = document.getElementById("important-section"); + auto* unimportant_section = document.getElementById("unimportant-section"); + + AddAnchor(*important_section, "https://foo.com/fizz"); + AddAnchor(*unimportant_section, "https://foo.com/buzz"); + + page_holder.GetFrame().GetSettings()->SetScriptEnabled(true); + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + ASSERT_FALSE(document.NeedsLayoutTreeUpdate()); + + auto* script_without_selector_matches = InsertSpeculationRules(document, R"( + {"prefetch": [{"source": "document", "where": {"href_matches": "/foo"}}]} + )"); + ASSERT_FALSE(important_section->NeedsStyleInvalidation()); + + auto* script_with_irrelevant_selector_matches = + InsertSpeculationRules(document, R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#irrelevant a"} + }]} + )"); + ASSERT_FALSE(important_section->NeedsStyleInvalidation()); + + auto* script_with_selector_matches = InsertSpeculationRules(document, R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#important-section a"} + }]} + )"); + EXPECT_TRUE(important_section->NeedsStyleInvalidation()); + + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + ASSERT_FALSE(important_section->NeedsStyleInvalidation()); + + // Test removing SpeculationRuleSets, removing a ruleset should also cause + // invalidations. + script_with_selector_matches->remove(); + EXPECT_TRUE(important_section->NeedsStyleInvalidation()); + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + + script_without_selector_matches->remove(); + ASSERT_FALSE(important_section->NeedsStyleInvalidation()); + + script_with_irrelevant_selector_matches->remove(); + ASSERT_FALSE(important_section->NeedsStyleInvalidation()); +} + +TEST_F(DocumentRulesTest, BasicStyleInvalidation) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = document.getElementById("important-section"); + auto* unimportant_section = document.getElementById("unimportant-section"); + + AddAnchor(*important_section, "https://foo.com/fizz"); + AddAnchor(*unimportant_section, "https://foo.com/buzz"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#important-section > a"} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + + EXPECT_FALSE(document.NeedsLayoutTreeUpdate()); + unimportant_section->SetIdAttribute("random-section"); + EXPECT_FALSE(document.NeedsLayoutTreeUpdate()); + unimportant_section->SetIdAttribute("important-section"); + EXPECT_TRUE(document.NeedsLayoutTreeUpdate()); +} + +TEST_F(DocumentRulesTest, IrrelevantDOMChangeShouldNotInvalidateCandidateList) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = document.getElementById("important-section"); + auto* unimportant_section = document.getElementById("unimportant-section"); + + AddAnchor(*important_section, "https://foo.com/fizz"); + AddAnchor(*unimportant_section, "https://foo.com/buzz"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#important-section > a"} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + const auto& candidates = speculation_host.candidates(); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/fizz"))); + + AssertNoRulesPropogatedToStubSpeculationHost( + page_holder, speculation_host, [&]() { + unimportant_section->SetIdAttribute("random-section"); + page_holder.GetFrameView().UpdateAllLifecyclePhasesForTest(); + }); +} + +TEST_F(DocumentRulesTest, SelectorMatchesInsideShadowTree) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + ShadowRoot& shadow_root = + document.body()->AttachShadowRootInternal(ShadowRootType::kOpen); + shadow_root.setInnerHTML(R"HTML( + <div id="important-section"></div> + <div id="unimportant-section"></div> + )HTML"); + auto* important_section = shadow_root.getElementById("important-section"); + auto* unimportant_section = shadow_root.getElementById("unimportant-section"); + + AddAnchor(*important_section, "https://foo.com/fizz"); + AddAnchor(*unimportant_section, "https://foo.com/buzz"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": "#important-section > a"} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + const auto& candidates = speculation_host.candidates(); + // TODO(crbug.com/1371522): Having document as the scoping root while matching + // 'selector_matches' means no link inside a shadow tree can ever be matched. + // If https://github.com/WICG/nav-speculation/pull/241 changes this, update + // this expectation. + EXPECT_THAT(candidates, HasURLs()); +} + +TEST_F(DocumentRulesTest, SelectorMatchesWithScopePseudoSelector) { + ScopedSpeculationRulesDocumentRulesSelectorMatchesForTest + enabled_selector_matches_{true}; + DummyPageHolder page_holder; + StubSpeculationHost speculation_host; + Document& document = page_holder.GetDocument(); + + document.body()->setAttribute(html_names::kClassAttr, "foo"); + document.body()->setInnerHTML(R"HTML( + <a href="https://foo.com/fizz"></a> + <div class="foo"> + <a href="https://foo.com/buzz"></a> + </div> + )HTML"); + + String speculation_script = R"( + {"prefetch": [{ + "source": "document", + "where": {"selector_matches": ":scope > .foo > a"} + }]} + )"; + PropagateRulesToStubSpeculationHostWithStyleUpdate( + page_holder, speculation_host, speculation_script); + const auto& candidates = speculation_host.candidates(); + EXPECT_THAT(candidates, HasURLs(KURL("https://foo.com/fizz"))); +} + TEST_F(SpeculationRuleSetTest, EagernessRuntimeEnabledFlag) { ScopedSpeculationRulesEagernessForTest enable_eagerness{false};
diff --git a/third_party/blink/renderer/core/style/build.gni b/third_party/blink/renderer/core/style/build.gni index 83f3040..ecd10c5 100644 --- a/third_party/blink/renderer/core/style/build.gni +++ b/third_party/blink/renderer/core/style/build.gni
@@ -28,6 +28,7 @@ "cursor_data.h", "cursor_list.h", "data_ref.h", + "display_style.h", "fill_layer.cc", "fill_layer.h", "filter_operation.cc",
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 7ca1821..0a7f789 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2374,29 +2374,32 @@ return static_cast<EPaintOrderType>(pt); } -bool ComputedStyle::ShouldApplyAnyContainment(const Element& element) const { +bool ComputedStyle::ShouldApplyAnyContainment(const Element& element, + const DisplayStyle& display_style, + unsigned effective_containment) { DCHECK(IsA<HTMLBodyElement>(element) || IsA<HTMLHtmlElement>(element)) << "Since elements can override the computed display for which box type " "to create, this method is not generally correct. Use " "LayoutObject::ShouldApplyAnyContainment if possible."; - if (ContainsStyle()) { + if (effective_containment & kContainsStyle) { return true; } - if (!element.LayoutObjectIsNeeded(*this)) { + if (!element.LayoutObjectIsNeeded(display_style)) { return false; } - if (Display() == EDisplay::kInline) { + EDisplay display = display_style.Display(); + if (display == EDisplay::kInline) { return false; } - if ((ContainsInlineSize() || ContainsBlockSize()) && - (!IsDisplayTableType() || Display() == EDisplay::kTableCaption || - ShouldUseContentDataForElement(GetContentData()))) { + if ((effective_containment & kContainsSize) && + (!IsDisplayTableType(display) || display == EDisplay::kTableCaption || + ShouldUseContentDataForElement(display_style.GetContentData()))) { return true; } - return (ContainsLayout() || ContainsPaint()) && - (!IsDisplayTableType() || IsDisplayTableBox() || - Display() == EDisplay::kTableCell || - Display() == EDisplay::kTableCaption); + return (effective_containment & (kContainsLayout | kContainsPaint)) && + (!IsDisplayTableType(display) || IsDisplayTableBox(display) || + display == EDisplay::kTableCell || + display == EDisplay::kTableCaption); } bool ComputedStyle::CanMatchSizeContainerQueries(const Element& element) const {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 7442a72..f840c68 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -52,6 +52,7 @@ #include "third_party/blink/renderer/core/style/computed_style_initial_values.h" #include "third_party/blink/renderer/core/style/cursor_list.h" #include "third_party/blink/renderer/core/style/data_ref.h" +#include "third_party/blink/renderer/core/style/display_style.h" #include "third_party/blink/renderer/core/style/style_cached_data.h" #include "third_party/blink/renderer/core/style/style_highlight_data.h" #include "third_party/blink/renderer/core/style/transform_origin.h" @@ -1638,39 +1639,74 @@ // Contain utility functions. // // Containment can be enabled from a variety of sources, not just the - // 'contain' property itself. The return values represent whether or not - // we should enable containment of a given type, taking those different - // sources into account. + // 'contain' property itself. The "effective containment" represents whether + // or not we should enable containment of a given type, taking those + // different sources into account. // - // Note that even with a return value of |true|, containment may still not - // be applied if the layout object is ineligible for the given containment - // type. See |LayoutObject::IsEligibleForSizeContainment| and similar - // functions. + // Note that even a certain type of containment appears to be in effect from + // the perspective of ComputedStyle, containment may still not be applied if + // the LayoutObject is ineligible for the given containment type. See + // |LayoutObject::IsEligibleForSizeContainment| and similar functions. - bool ContainsPaint() const { - return (Contain() & kContainsPaint) || !IsContentVisibilityVisible(); + static unsigned EffectiveContainment(unsigned contain, + unsigned container_type, + EContentVisibility content_visibility, + const AtomicString& toggle_visibility, + bool skips_contents) { + unsigned effective = contain; + + if (container_type & kContainerTypeInlineSize) { + effective |= kContainsStyle; + effective |= kContainsLayout; + effective |= kContainsInlineSize; + } + if (container_type & kContainerTypeBlockSize) { + effective |= kContainsStyle; + effective |= kContainsLayout; + effective |= kContainsBlockSize; + } + if (!IsContentVisibilityVisible(content_visibility, toggle_visibility)) { + effective |= kContainsStyle; + effective |= kContainsLayout; + effective |= kContainsPaint; + } + if (skips_contents) { + effective |= kContainsSize; + } + + return effective; } - bool ContainsStyle() const { - return (Contain() & kContainsStyle) || IsInlineOrBlockSizeContainer() || - !IsContentVisibilityVisible(); + + unsigned EffectiveContainment() const { + return ComputedStyle::EffectiveContainment( + Contain(), ContainerType(), ContentVisibility(), ToggleVisibility(), + SkipsContents()); } + + bool ContainsStyle() const { return EffectiveContainment() & kContainsStyle; } + bool ContainsPaint() const { return EffectiveContainment() & kContainsPaint; } bool ContainsLayout() const { - return (Contain() & kContainsLayout) || IsInlineOrBlockSizeContainer() || - !IsContentVisibilityVisible(); + return EffectiveContainment() & kContainsLayout; } bool ContainsSize() const { - return ((Contain() & kContainsSize) == kContainsSize) || - IsSizeContainer() || SkipsContents(); + return (EffectiveContainment() & kContainsSize) == kContainsSize; } bool ContainsInlineSize() const { - return (Contain() & kContainsInlineSize) || IsInlineSizeContainer() || - SkipsContents(); + return EffectiveContainment() & kContainsInlineSize; } bool ContainsBlockSize() const { - return (Contain() & kContainsBlockSize) || IsBlockSizeContainer() || - SkipsContents(); + return EffectiveContainment() & kContainsBlockSize; } - CORE_EXPORT bool ShouldApplyAnyContainment(const Element& element) const; + + CORE_EXPORT static bool ShouldApplyAnyContainment( + const Element& element, + const DisplayStyle&, + unsigned effective_containment); + + CORE_EXPORT bool ShouldApplyAnyContainment(const Element& element) const { + return ShouldApplyAnyContainment(element, GetDisplayStyle(), + EffectiveContainment()); + } // Return true if an element can match size container queries. In addition to // checking if it has a size container-type, we check if we are never able to @@ -1681,9 +1717,15 @@ return IsInlineOrBlockSizeContainer() && StyleType() == kPseudoIdNone; } + static bool IsContentVisibilityVisible( + EContentVisibility content_visibility, + const AtomicString& toggle_visibility) { + return content_visibility == EContentVisibility::kVisible && + toggle_visibility.IsNull(); + } + bool IsContentVisibilityVisible() const { - return ContentVisibility() == EContentVisibility::kVisible && - ToggleVisibility().IsNull(); + return IsContentVisibilityVisible(ContentVisibility(), ToggleVisibility()); } // Interleaving roots are elements that may require layout to fully update @@ -1730,25 +1772,16 @@ // Isolation utility functions. bool HasIsolation() const { return Isolation() != EIsolation::kAuto; } + DisplayStyle GetDisplayStyle() const { + return DisplayStyle(Display(), StyleType(), GetContentData()); + } + // Content utility functions. bool ContentBehavesAsNormal() const { - switch (StyleType()) { - case kPseudoIdMarker: - return !GetContentData(); - default: - return !GetContentData() || GetContentData()->IsNone(); - } + return GetDisplayStyle().ContentBehavesAsNormal(); } bool ContentPreventsBoxGeneration() const { - switch (StyleType()) { - case kPseudoIdBefore: - case kPseudoIdAfter: - return ContentBehavesAsNormal(); - case kPseudoIdMarker: - return GetContentData() && GetContentData()->IsNone(); - default: - return false; - } + return GetDisplayStyle().ContentPreventsBoxGeneration(); } // Cursor utility functions. @@ -2886,6 +2919,14 @@ return ComputedStyle::SpecifiesColumns(HasAutoColumnCount(), HasAutoColumnWidth()); } + // contain + bool ShouldApplyAnyContainment(const Element& element) const { + unsigned effective_containment = ComputedStyle::EffectiveContainment( + Contain(), ContainerType(), ContentVisibility(), ToggleVisibility(), + SkipsContents()); + return ComputedStyle::ShouldApplyAnyContainment(element, GetDisplayStyle(), + effective_containment); + } // content ContentData* GetContentData() const { return ContentInternal().Get(); } @@ -2958,6 +2999,9 @@ Display() == EDisplay::kTableColumn || Display() == EDisplay::kTableColumnGroup; } + DisplayStyle GetDisplayStyle() const { + return DisplayStyle(Display(), StyleType(), GetContentData()); + } // filter FilterOperations& MutableFilter() { @@ -3247,6 +3291,15 @@ } } + // DocumentRulesSelectors + void AddDocumentRulesSelector(StyleRule* selector) { + if (!DocumentRulesSelectors()) { + MutableDocumentRulesSelectorsInternal() = + MakeGarbageCollected<HeapHashSet<WeakMember<StyleRule>>>(); + } + DocumentRulesSelectors()->insert(selector); + } + // ::selection, etc StyleHighlightData& MutableHighlightData();
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index 2bab7542..9d12e626 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -585,6 +585,19 @@ computed_style_custom_functions: ["setter"], }, { + name: "DocumentRulesSelectors", + field_template: "external", + type_name: "HeapHashSet<WeakMember<StyleRule>>", + wrapper_pointer_name: "Persistent", + field_group: "*", + default_value: "nullptr", + include_paths: ["third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h", + "third_party/blink/renderer/platform/heap/member.h", + "third_party/blink/renderer/platform/heap/persistent.h", + "third_party/blink/renderer/core/css/style_rule.h"], + computed_style_custom_functions: ["setter"], + }, + { name: "PaintImages", field_template: "external", type_name: "PaintImages",
diff --git a/third_party/blink/renderer/core/style/display_style.h b/third_party/blink/renderer/core/style/display_style.h new file mode 100644 index 0000000..ab31c7a4 --- /dev/null +++ b/third_party/blink/renderer/core/style/display_style.h
@@ -0,0 +1,62 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_DISPLAY_STYLE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_DISPLAY_STYLE_H_ + +#include "third_party/blink/renderer/core/style/content_data.h" + +namespace blink { + +class ContentData; + +// DisplayStyle contains the subset of ComputedStyle which is needed to +// determine whether an Element needs a LayoutObject or not. It is useful +// to keep this separate from ComputedStyle, because we sometimes need to +// make that determination before the ComputedStyle is created. +class DisplayStyle { + STACK_ALLOCATED(); + + public: + DisplayStyle(EDisplay display, + PseudoId style_type, + const ContentData* content_data) + : display_(display), + style_type_(style_type), + content_data_(content_data) {} + + EDisplay Display() const { return display_; } + PseudoId StyleType() const { return style_type_; } + const ContentData* GetContentData() const { return content_data_; } + + bool ContentBehavesAsNormal() const { + switch (style_type_) { + case kPseudoIdMarker: + return !content_data_; + default: + return !content_data_ || content_data_->IsNone(); + } + } + + bool ContentPreventsBoxGeneration() const { + switch (style_type_) { + case kPseudoIdBefore: + case kPseudoIdAfter: + return ContentBehavesAsNormal(); + case kPseudoIdMarker: + return content_data_ && content_data_->IsNone(); + default: + return false; + } + } + + private: + EDisplay display_; + PseudoId style_type_; + const ContentData* content_data_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_DISPLAY_STYLE_H_
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h index 5fddf051..2eca3ad9 100644 --- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h +++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
@@ -181,7 +181,7 @@ void StartedActiveInterval(); void EndedActiveInterval(); - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.h b/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.h index 0cf9fe17..9f17570 100644 --- a/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.h +++ b/third_party/blink/renderer/core/svg/svg_component_transfer_function_element.h
@@ -54,7 +54,7 @@ void SvgAttributeChanged(const SvgAttributeChangedParams&) final; - bool LayoutObjectIsNeeded(const ComputedStyle& style) const final { + bool LayoutObjectIsNeeded(const DisplayStyle& style) const final { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_desc_element.h b/third_party/blink/renderer/core/svg/svg_desc_element.h index 579d1f25..31377c1a8 100644 --- a/third_party/blink/renderer/core/svg/svg_desc_element.h +++ b/third_party/blink/renderer/core/svg/svg_desc_element.h
@@ -32,7 +32,7 @@ explicit SVGDescElement(Document&); private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; } };
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc index 1086417..c5f9bac 100644 --- a/third_party/blink/renderer/core/svg/svg_element.cc +++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -1085,7 +1085,7 @@ corresponding_element, style_recalc_context, style_request); } -bool SVGElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool SVGElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { return IsValid() && HasSVGParent() && Element::LayoutObjectIsNeeded(style); }
diff --git a/third_party/blink/renderer/core/svg/svg_element.h b/third_party/blink/renderer/core/svg/svg_element.h index 4d8ce19..1b38d7831 100644 --- a/third_party/blink/renderer/core/svg/svg_element.h +++ b/third_party/blink/renderer/core/svg/svg_element.h
@@ -167,7 +167,7 @@ scoped_refptr<ComputedStyle> CustomStyleForLayoutObject( const StyleRecalcContext&) final; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; #if DCHECK_IS_ON() virtual bool IsAnimatableAttribute(const QualifiedName&) const;
diff --git a/third_party/blink/renderer/core/svg/svg_fe_light_element.h b/third_party/blink/renderer/core/svg/svg_fe_light_element.h index 5b3d6ff..30882330 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_light_element.h +++ b/third_party/blink/renderer/core/svg/svg_fe_light_element.h
@@ -83,7 +83,7 @@ void SvgAttributeChanged(const SvgAttributeChangedParams&) final; void ChildrenChanged(const ChildrenChange&) final; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.h b/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.h index a1ccd03..aa92ea3 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.h +++ b/third_party/blink/renderer/core/svg/svg_fe_merge_node_element.h
@@ -41,7 +41,7 @@ private: void SvgAttributeChanged(const SvgAttributeChangedParams&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.cc b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.cc index fde8eb5..2e5d46e6 100644 --- a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.cc +++ b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.cc
@@ -174,7 +174,7 @@ } bool SVGFilterPrimitiveStandardAttributes::LayoutObjectIsNeeded( - const ComputedStyle& style) const { + const DisplayStyle& style) const { if (IsA<SVGFilterElement>(parentNode())) return SVGElement::LayoutObjectIsNeeded(style);
diff --git a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h index 9a0ed982..0468741b 100644 --- a/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h +++ b/third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h
@@ -74,7 +74,7 @@ bool IsFilterEffect() const final { return true; } LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const final; + bool LayoutObjectIsNeeded(const DisplayStyle&) const final; Member<SVGAnimatedLength> x_; Member<SVGAnimatedLength> y_;
diff --git a/third_party/blink/renderer/core/svg/svg_g_element.cc b/third_party/blink/renderer/core/svg/svg_g_element.cc index 0dd1421..4e6746a 100644 --- a/third_party/blink/renderer/core/svg/svg_g_element.cc +++ b/third_party/blink/renderer/core/svg/svg_g_element.cc
@@ -43,7 +43,7 @@ return MakeGarbageCollected<LayoutSVGTransformableContainer>(this); } -bool SVGGElement::LayoutObjectIsNeeded(const ComputedStyle&) const { +bool SVGGElement::LayoutObjectIsNeeded(const DisplayStyle&) const { // Unlike SVGElement::layoutObjectIsNeeded(), we still create layoutObjects, // even if display is set to 'none' - which is special to SVG <g> container // elements.
diff --git a/third_party/blink/renderer/core/svg/svg_g_element.h b/third_party/blink/renderer/core/svg/svg_g_element.h index 57f0dfc..e6067938 100644 --- a/third_party/blink/renderer/core/svg/svg_g_element.h +++ b/third_party/blink/renderer/core/svg/svg_g_element.h
@@ -36,7 +36,7 @@ LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_length_context.cc b/third_party/blink/renderer/core/svg/svg_length_context.cc index 8317e0ab..5fd47849 100644 --- a/third_party/blink/renderer/core/svg/svg_length_context.cc +++ b/third_party/blink/renderer/core/svg/svg_length_context.cc
@@ -28,13 +28,10 @@ #include "third_party/blink/renderer/core/css/css_resolution_units.h" #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" -#include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/svg/svg_length.h" #include "third_party/blink/renderer/core/svg/svg_svg_element.h" -#include "third_party/blink/renderer/platform/fonts/font_metrics.h" #include "third_party/blink/renderer/platform/geometry/length_functions.h" #include "third_party/blink/renderer/platform/geometry/length_point.h" #include "ui/gfx/geometry/size_f.h" @@ -45,12 +42,8 @@ namespace { const ComputedStyle* ComputedStyleForLengthResolving( - const SVGElement* context) { - if (!context) { - return nullptr; - } - - const ContainerNode* current_context = context; + const SVGElement& context) { + const ContainerNode* current_context = &context; do { if (current_context->GetLayoutObject()) { return current_context->GetLayoutObject()->Style(); @@ -63,6 +56,11 @@ return nullptr; } +const ComputedStyle* ComputedStyleForLengthResolving( + const SVGElement* context) { + return context ? ComputedStyleForLengthResolving(*context) : nullptr; +} + const ComputedStyle* RootElementStyle(const SVGElement& element) { if (auto* document_element = element.GetDocument().documentElement()) { if (element != document_element) { @@ -72,10 +70,6 @@ return nullptr; } -const ComputedStyle* RootElementStyle(const SVGElement* element) { - return element ? RootElementStyle(*element) : nullptr; -} - class SVGLengthConversionData : public CSSToLengthConversionData { STACK_ALLOCATED(); @@ -114,181 +108,6 @@ return FloatValueForLength(length, unit_dimension, nullptr) * ref_dimension; } -float ConvertValueFromUserUnitsToEMS(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - float font_size = style->SpecifiedFontSize(); - if (!font_size) { - return 0; - } - return value / font_size; -} - -float ConvertValueFromEMSToUserUnits(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - return value * style->SpecifiedFontSize(); -} - -float ConvertValueFromUserUnitsToEXS(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - // Use of ceil allows a pixel match to the W3Cs expected output of - // coords-units-03-b.svg, if this causes problems in real world cases maybe it - // would be best to remove this. - float x_height = - ceilf(font_data->GetFontMetrics().XHeight() / style->EffectiveZoom()); - if (!x_height) { - return 0; - } - return value / x_height; -} - -float ConvertValueFromEXSToUserUnits(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - // Use of ceil allows a pixel match to the W3Cs expected output of - // coords-units-03-b.svg, if this causes problems in real world cases maybe it - // would be best to remove this. - return value * - ceilf(font_data->GetFontMetrics().XHeight() / style->EffectiveZoom()); -} - -float ConvertValueFromUserUnitsToCHS(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - float zero_width = - font_data->GetFontMetrics().ZeroWidth() / style->EffectiveZoom(); - if (!zero_width) { - return 0; - } - return value / zero_width; -} - -float ConvertValueFromCHSToUserUnits(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - return value * font_data->GetFontMetrics().ZeroWidth() / - style->EffectiveZoom(); -} - -float ConvertValueFromUserUnitsToICS(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - float ideographic_full_width = - font_data->GetFontMetrics().IdeographicFullWidth().value_or( - style->ComputedFontSize()) / - style->EffectiveZoom(); - if (!ideographic_full_width) { - return 0; - } - return value / ideographic_full_width; -} - -float ConvertValueFromICSToUserUnits(const ComputedStyle* style, float value) { - if (!style) { - return 0; - } - const SimpleFontData* font_data = style->GetFont().PrimaryFont(); - if (!font_data) { - return 0; - } - return value * - font_data->GetFontMetrics().IdeographicFullWidth().value_or( - style->ComputedFontSize()) / - style->EffectiveZoom(); -} - -float ConvertValueFromUserUnitsToLHS(const ComputedStyle* style, float value) { - return value / AdjustForAbsoluteZoom::AdjustFloat(style->ComputedLineHeight(), - *style); -} - -float ConvertValueFromLHSToUserUnits(const ComputedStyle* style, float value) { - return value * AdjustForAbsoluteZoom::AdjustFloat(style->ComputedLineHeight(), - *style); -} - -inline float ViewportLengthPercent(const float width_or_height) { - return width_or_height / 100; -} - -inline float ViewportMinPercent(const gfx::SizeF& viewport_size) { - return std::min(viewport_size.width(), viewport_size.height()) / 100; -} - -inline float ViewportMaxPercent(const gfx::SizeF& viewport_size) { - return std::max(viewport_size.width(), viewport_size.height()) / 100; -} - -inline float DimensionForViewportUnit(const SVGElement* context, - CSSPrimitiveValue::UnitType unit) { - if (!context) { - return 0; - } - - const Document& document = context->GetDocument(); - LocalFrameView* view = document.View(); - if (!view) { - return 0; - } - - const ComputedStyle* style = ComputedStyleForLengthResolving(context); - if (!style) { - return 0; - } - - gfx::SizeF viewport_size(view->Width(), view->Height()); - - switch (unit) { - case CSSPrimitiveValue::UnitType::kViewportWidth: - return ViewportLengthPercent(viewport_size.width()) / - style->EffectiveZoom(); - - case CSSPrimitiveValue::UnitType::kViewportHeight: - return ViewportLengthPercent(viewport_size.height()) / - style->EffectiveZoom(); - - case CSSPrimitiveValue::UnitType::kViewportMin: - return ViewportMinPercent(viewport_size) / style->EffectiveZoom(); - - case CSSPrimitiveValue::UnitType::kViewportMax: - return ViewportMaxPercent(viewport_size) / style->EffectiveZoom(); - default: - break; - } - - NOTREACHED(); - return 0; -} - } // namespace SVGLengthContext::SVGLengthContext(const SVGElement* context) @@ -432,148 +251,71 @@ return FloatValueForLength(length, dimension * zoom) / zoom; } -float SVGLengthContext::ConvertValueToUserUnits( +double SVGLengthContext::ConvertValueToUserUnitsUnclamped( float value, SVGLengthMode mode, CSSPrimitiveValue::UnitType from_unit) const { - double user_units = value; + // Handle absolute units. switch (from_unit) { case CSSPrimitiveValue::UnitType::kPixels: case CSSPrimitiveValue::UnitType::kNumber: case CSSPrimitiveValue::UnitType::kInteger: case CSSPrimitiveValue::UnitType::kUserUnits: - user_units = value; - break; - case CSSPrimitiveValue::UnitType::kPercentage: - user_units = value * ViewportDimension(mode) / 100; - break; - case CSSPrimitiveValue::UnitType::kEms: - user_units = ConvertValueFromEMSToUserUnits( - ComputedStyleForLengthResolving(context_), value); - break; - case CSSPrimitiveValue::UnitType::kExs: - user_units = ConvertValueFromEXSToUserUnits( - ComputedStyleForLengthResolving(context_), value); - break; + return value; case CSSPrimitiveValue::UnitType::kCentimeters: - user_units = value * kCssPixelsPerCentimeter; - break; + return value * kCssPixelsPerCentimeter; case CSSPrimitiveValue::UnitType::kMillimeters: - user_units = value * kCssPixelsPerMillimeter; - break; + return value * kCssPixelsPerMillimeter; case CSSPrimitiveValue::UnitType::kQuarterMillimeters: - user_units = value * kCssPixelsPerQuarterMillimeter; - break; + return value * kCssPixelsPerQuarterMillimeter; case CSSPrimitiveValue::UnitType::kInches: - user_units = value * kCssPixelsPerInch; - break; + return value * kCssPixelsPerInch; case CSSPrimitiveValue::UnitType::kPoints: - user_units = value * kCssPixelsPerPoint; - break; + return value * kCssPixelsPerPoint; case CSSPrimitiveValue::UnitType::kPicas: - user_units = value * kCssPixelsPerPica; - break; - case CSSPrimitiveValue::UnitType::kRems: - user_units = - ConvertValueFromEMSToUserUnits(RootElementStyle(context_), value); - break; - case CSSPrimitiveValue::UnitType::kRexs: - user_units = - ConvertValueFromEXSToUserUnits(RootElementStyle(context_), value); - break; - case CSSPrimitiveValue::UnitType::kChs: - user_units = ConvertValueFromCHSToUserUnits( - ComputedStyleForLengthResolving(context_), value); - break; - case CSSPrimitiveValue::UnitType::kRchs: - user_units = - ConvertValueFromCHSToUserUnits(RootElementStyle(context_), value); - break; - case CSSPrimitiveValue::UnitType::kIcs: - user_units = ConvertValueFromICSToUserUnits( - ComputedStyleForLengthResolving(context_), value); - break; - case CSSPrimitiveValue::UnitType::kRics: - user_units = - ConvertValueFromICSToUserUnits(RootElementStyle(context_), value); - break; - case CSSPrimitiveValue::UnitType::kLhs: - user_units = ConvertValueFromLHSToUserUnits( - ComputedStyleForLengthResolving(context_), value); - break; - case CSSPrimitiveValue::UnitType::kRlhs: - user_units = - ConvertValueFromLHSToUserUnits(RootElementStyle(context_), value); - break; - case CSSPrimitiveValue::UnitType::kViewportWidth: - case CSSPrimitiveValue::UnitType::kViewportHeight: - case CSSPrimitiveValue::UnitType::kViewportMin: - case CSSPrimitiveValue::UnitType::kViewportMax: - user_units = value * DimensionForViewportUnit(context_, from_unit); - break; - case CSSPrimitiveValue::UnitType::kContainerWidth: - case CSSPrimitiveValue::UnitType::kContainerHeight: - case CSSPrimitiveValue::UnitType::kContainerInlineSize: - case CSSPrimitiveValue::UnitType::kContainerBlockSize: - case CSSPrimitiveValue::UnitType::kContainerMin: - case CSSPrimitiveValue::UnitType::kContainerMax: - NOTREACHED() << "Must be handled using ResolveValue"; - break; + return value * kCssPixelsPerPica; default: - NOTREACHED(); break; } + if (!context_) { + return 0; + } + // Handle the percentage unit. + if (from_unit == CSSPrimitiveValue::UnitType::kPercentage) { + return value * ViewportDimension(mode) / 100; + } + // For remaining units, just instantiate a CSSToLengthConversionData object + // and use that for resolving. + const ComputedStyle* style = ComputedStyleForLengthResolving(*context_); + if (!style) { + return 0; + } + const SVGLengthConversionData conversion_data(*context_, *style); + return conversion_data.ZoomedComputedPixels(value, from_unit); +} +float SVGLengthContext::ConvertValueToUserUnits( + float value, + SVGLengthMode mode, + CSSPrimitiveValue::UnitType from_unit) const { // Since we mix css <length> values with svg's length values we need to // clamp values to the narrowest range, otherwise it can result in // rendering issues. - return CSSPrimitiveValue::ClampToCSSLengthRange(user_units); + return CSSPrimitiveValue::ClampToCSSLengthRange( + ConvertValueToUserUnitsUnclamped(value, mode, from_unit)); } float SVGLengthContext::ConvertValueFromUserUnits( float value, SVGLengthMode mode, CSSPrimitiveValue::UnitType to_unit) const { + // Handle absolute units. switch (to_unit) { case CSSPrimitiveValue::UnitType::kPixels: case CSSPrimitiveValue::UnitType::kNumber: case CSSPrimitiveValue::UnitType::kInteger: case CSSPrimitiveValue::UnitType::kUserUnits: return value; - case CSSPrimitiveValue::UnitType::kPercentage: { - const float dimension = ViewportDimension(mode); - if (!dimension) { - return 0; - } - // LengthTypePercentage is represented with 100% = 100.0. - // Good for accuracy but could eventually be changed. - return value * 100 / dimension; - } - case CSSPrimitiveValue::UnitType::kEms: - return ConvertValueFromUserUnitsToEMS( - ComputedStyleForLengthResolving(context_), value); - case CSSPrimitiveValue::UnitType::kExs: - return ConvertValueFromUserUnitsToEXS( - ComputedStyleForLengthResolving(context_), value); - case CSSPrimitiveValue::UnitType::kRems: - return ConvertValueFromUserUnitsToEMS(RootElementStyle(context_), value); - case CSSPrimitiveValue::UnitType::kRexs: - return ConvertValueFromUserUnitsToEXS(RootElementStyle(context_), value); - case CSSPrimitiveValue::UnitType::kChs: - return ConvertValueFromUserUnitsToCHS( - ComputedStyleForLengthResolving(context_), value); - case CSSPrimitiveValue::UnitType::kRchs: - return ConvertValueFromUserUnitsToCHS(RootElementStyle(context_), value); - case CSSPrimitiveValue::UnitType::kIcs: - return ConvertValueFromUserUnitsToICS( - ComputedStyleForLengthResolving(context_), value); - case CSSPrimitiveValue::UnitType::kRics: - return ConvertValueFromUserUnitsToICS(RootElementStyle(context_), value); - case CSSPrimitiveValue::UnitType::kLhs: - return ConvertValueFromUserUnitsToLHS( - ComputedStyleForLengthResolving(context_), value); - case CSSPrimitiveValue::UnitType::kRlhs: - return ConvertValueFromUserUnitsToLHS(RootElementStyle(context_), value); case CSSPrimitiveValue::UnitType::kCentimeters: return value / kCssPixelsPerCentimeter; case CSSPrimitiveValue::UnitType::kMillimeters: @@ -586,25 +328,34 @@ return value / kCssPixelsPerPoint; case CSSPrimitiveValue::UnitType::kPicas: return value / kCssPixelsPerPica; - case CSSPrimitiveValue::UnitType::kViewportWidth: - case CSSPrimitiveValue::UnitType::kViewportHeight: - case CSSPrimitiveValue::UnitType::kViewportMin: - case CSSPrimitiveValue::UnitType::kViewportMax: - return value / DimensionForViewportUnit(context_, to_unit); - case CSSPrimitiveValue::UnitType::kContainerWidth: - case CSSPrimitiveValue::UnitType::kContainerHeight: - case CSSPrimitiveValue::UnitType::kContainerInlineSize: - case CSSPrimitiveValue::UnitType::kContainerBlockSize: - case CSSPrimitiveValue::UnitType::kContainerMin: - case CSSPrimitiveValue::UnitType::kContainerMax: - NOTREACHED() << "Must be handled using ResolveValue"; - break; default: break; } - - NOTREACHED(); - return 0; + if (!context_) { + return 0; + } + // Handle the percentage unit. + if (to_unit == CSSPrimitiveValue::UnitType::kPercentage) { + const float dimension = ViewportDimension(mode); + if (!dimension) { + return 0; + } + // LengthTypePercentage is represented with 100% = 100.0. + // Good for accuracy but could eventually be changed. + return value * 100 / dimension; + } + // For remaining units, just instantiate a CSSToLengthConversionData object + // and use that for resolving. + const ComputedStyle* style = ComputedStyleForLengthResolving(*context_); + if (!style) { + return 0; + } + const SVGLengthConversionData conversion_data(*context_, *style); + const double reference = conversion_data.ZoomedComputedPixels(1, to_unit); + if (!reference) { + return 0; + } + return ClampTo<float>(value / reference); } gfx::SizeF SVGLengthContext::ResolveViewport() const {
diff --git a/third_party/blink/renderer/core/svg/svg_length_context.h b/third_party/blink/renderer/core/svg/svg_length_context.h index 9b2c51f..8f7ae93 100644 --- a/third_party/blink/renderer/core/svg/svg_length_context.h +++ b/third_party/blink/renderer/core/svg/svg_length_context.h
@@ -96,6 +96,11 @@ float ValueForLength(const Length&, float zoom, SVGLengthMode) const; static float ValueForLength(const Length&, float zoom, float dimension); + double ConvertValueToUserUnitsUnclamped( + float value, + SVGLengthMode mode, + CSSPrimitiveValue::UnitType from_unit) const; + const SVGElement* context_; };
diff --git a/third_party/blink/renderer/core/svg/svg_marker_element.cc b/third_party/blink/renderer/core/svg/svg_marker_element.cc index 0bacac06..ae9496b 100644 --- a/third_party/blink/renderer/core/svg/svg_marker_element.cc +++ b/third_party/blink/renderer/core/svg/svg_marker_element.cc
@@ -170,7 +170,7 @@ marker_height_->CurrentValue()->IsRelative(); } -bool SVGMarkerElement::LayoutObjectIsNeeded(const ComputedStyle&) const { +bool SVGMarkerElement::LayoutObjectIsNeeded(const DisplayStyle&) const { return IsValid() && HasSVGParent(); }
diff --git a/third_party/blink/renderer/core/svg/svg_marker_element.h b/third_party/blink/renderer/core/svg/svg_marker_element.h index 67a8f4e..49e21bc 100644 --- a/third_party/blink/renderer/core/svg/svg_marker_element.h +++ b/third_party/blink/renderer/core/svg/svg_marker_element.h
@@ -81,7 +81,7 @@ void ChildrenChanged(const ChildrenChange&) override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; bool SelfHasRelativeLengths() const override;
diff --git a/third_party/blink/renderer/core/svg/svg_metadata_element.h b/third_party/blink/renderer/core/svg/svg_metadata_element.h index 3a6ba9c4..ca00e67 100644 --- a/third_party/blink/renderer/core/svg/svg_metadata_element.h +++ b/third_party/blink/renderer/core/svg/svg_metadata_element.h
@@ -32,7 +32,7 @@ explicit SVGMetadataElement(Document&); private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; } };
diff --git a/third_party/blink/renderer/core/svg/svg_mpath_element.h b/third_party/blink/renderer/core/svg/svg_mpath_element.h index 9db6ca2a..12944fc 100644 --- a/third_party/blink/renderer/core/svg/svg_mpath_element.h +++ b/third_party/blink/renderer/core/svg/svg_mpath_element.h
@@ -48,7 +48,7 @@ void SvgAttributeChanged(const SvgAttributeChangedParams&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; } void NotifyParentOfPathChange(ContainerNode*);
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.h b/third_party/blink/renderer/core/svg/svg_script_element.h index ab07735..c3d010576 100644 --- a/third_party/blink/renderer/core/svg/svg_script_element.h +++ b/third_party/blink/renderer/core/svg/svg_script_element.h
@@ -106,7 +106,7 @@ Type GetScriptElementType() override; Element& CloneWithoutAttributesAndChildren(Document&) const override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_stop_element.h b/third_party/blink/renderer/core/svg/svg_stop_element.h index 37ca59f4..5be26e82 100644 --- a/third_party/blink/renderer/core/svg/svg_stop_element.h +++ b/third_party/blink/renderer/core/svg/svg_stop_element.h
@@ -48,7 +48,7 @@ void SvgAttributeChanged(const SvgAttributeChangedParams&) override; // Stop elements don't have associated layout objects. - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_style_element.h b/third_party/blink/renderer/core/svg/svg_style_element.h index f6d7401..1c3a407 100644 --- a/third_party/blink/renderer/core/svg/svg_style_element.h +++ b/third_party/blink/renderer/core/svg/svg_style_element.h
@@ -59,7 +59,7 @@ void ChildrenChanged(const ChildrenChange&) override; void FinishParsingChildren() override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_svg_element.cc b/third_party/blink/renderer/core/svg/svg_svg_element.cc index 260cea0..1e1c85a 100644 --- a/third_party/blink/renderer/core/svg/svg_svg_element.cc +++ b/third_party/blink/renderer/core/svg/svg_svg_element.cc
@@ -497,7 +497,7 @@ return transform; } -bool SVGSVGElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool SVGSVGElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { // FIXME: We should respect display: none on the documentElement svg element // but many things in LocalFrameView and SVGImage depend on the LayoutSVGRoot // when they should instead depend on the LayoutView.
diff --git a/third_party/blink/renderer/core/svg/svg_svg_element.h b/third_party/blink/renderer/core/svg/svg_svg_element.h index 64dedb07ac..7ae920d 100644 --- a/third_party/blink/renderer/core/svg/svg_svg_element.h +++ b/third_party/blink/renderer/core/svg/svg_svg_element.h
@@ -122,7 +122,7 @@ MutableCSSPropertyValueSet*) override; void AttachLayoutTree(AttachContext&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; InsertionNotificationRequest InsertedInto(ContainerNode&) override;
diff --git a/third_party/blink/renderer/core/svg/svg_text_path_element.cc b/third_party/blink/renderer/core/svg/svg_text_path_element.cc index 3ec150af..f9b989d69 100644 --- a/third_party/blink/renderer/core/svg/svg_text_path_element.cc +++ b/third_party/blink/renderer/core/svg/svg_text_path_element.cc
@@ -116,8 +116,7 @@ return MakeGarbageCollected<LayoutSVGTextPath>(this); } -bool SVGTextPathElement::LayoutObjectIsNeeded( - const ComputedStyle& style) const { +bool SVGTextPathElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { if (parentNode() && (IsA<SVGAElement>(*parentNode()) || IsA<SVGTextElement>(*parentNode()))) return SVGElement::LayoutObjectIsNeeded(style);
diff --git a/third_party/blink/renderer/core/svg/svg_text_path_element.h b/third_party/blink/renderer/core/svg/svg_text_path_element.h index 3787e106..16013ba9 100644 --- a/third_party/blink/renderer/core/svg/svg_text_path_element.h +++ b/third_party/blink/renderer/core/svg/svg_text_path_element.h
@@ -78,7 +78,7 @@ void SvgAttributeChanged(const SvgAttributeChangedParams&) override; LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; bool SelfHasRelativeLengths() const override;
diff --git a/third_party/blink/renderer/core/svg/svg_title_element.h b/third_party/blink/renderer/core/svg/svg_title_element.h index de14e80..e22d343 100644 --- a/third_party/blink/renderer/core/svg/svg_title_element.h +++ b/third_party/blink/renderer/core/svg/svg_title_element.h
@@ -38,7 +38,7 @@ void RemovedFrom(ContainerNode&) override; void ChildrenChanged(const ChildrenChange&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; }
diff --git a/third_party/blink/renderer/core/svg/svg_tspan_element.cc b/third_party/blink/renderer/core/svg/svg_tspan_element.cc index b61b029..90b4bca 100644 --- a/third_party/blink/renderer/core/svg/svg_tspan_element.cc +++ b/third_party/blink/renderer/core/svg/svg_tspan_element.cc
@@ -33,7 +33,7 @@ return MakeGarbageCollected<LayoutSVGTSpan>(this); } -bool SVGTSpanElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { +bool SVGTSpanElement::LayoutObjectIsNeeded(const DisplayStyle& style) const { if (parentNode() && (IsA<SVGAElement>(*parentNode()) || IsA<SVGTextElement>(*parentNode()) || IsA<SVGTextPathElement>(*parentNode()) ||
diff --git a/third_party/blink/renderer/core/svg/svg_tspan_element.h b/third_party/blink/renderer/core/svg/svg_tspan_element.h index d74f798..b47b9a8 100644 --- a/third_party/blink/renderer/core/svg/svg_tspan_element.h +++ b/third_party/blink/renderer/core/svg/svg_tspan_element.h
@@ -33,7 +33,7 @@ private: LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool LayoutObjectIsNeeded(const DisplayStyle&) const override; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_unknown_element.h b/third_party/blink/renderer/core/svg/svg_unknown_element.h index fb9404a2..07165e1 100644 --- a/third_party/blink/renderer/core/svg/svg_unknown_element.h +++ b/third_party/blink/renderer/core/svg/svg_unknown_element.h
@@ -49,7 +49,7 @@ SVGUnknownElement(const QualifiedName&, Document&); private: - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; } };
diff --git a/third_party/blink/renderer/core/svg/svg_view_element.h b/third_party/blink/renderer/core/svg/svg_view_element.h index b3e4045..a05d31e6 100644 --- a/third_party/blink/renderer/core/svg/svg_view_element.h +++ b/third_party/blink/renderer/core/svg/svg_view_element.h
@@ -41,7 +41,7 @@ private: void ParseAttribute(const AttributeModificationParams&) override; - bool LayoutObjectIsNeeded(const ComputedStyle&) const override { + bool LayoutObjectIsNeeded(const DisplayStyle&) const override { return false; } };
diff --git a/third_party/blink/renderer/core/view_transition/view_transition.cc b/third_party/blink/renderer/core/view_transition/view_transition.cc index e98a1aaf..8039b919 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition.cc
@@ -685,7 +685,7 @@ bool ViewTransition::MatchForOnlyChild( PseudoId pseudo_id, - AtomicString view_transition_name) const { + const AtomicString& view_transition_name) const { if (!style_tracker_) return false; return style_tracker_->MatchForOnlyChild(pseudo_id, view_transition_name);
diff --git a/third_party/blink/renderer/core/view_transition/view_transition.h b/third_party/blink/renderer/core/view_transition/view_transition.h index 64cd115..393a9e2 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition.h +++ b/third_party/blink/renderer/core/view_transition/view_transition.h
@@ -97,7 +97,7 @@ // Returns true if the pseudo element corresponding to the given id and name // is the only child. bool MatchForOnlyChild(PseudoId pseudo_id, - AtomicString view_transition_name) const; + const AtomicString& view_transition_name) const; // ExecutionContextLifecycleObserver implementation. void ContextDestroyed() override;
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc index 32d6b982..0caa77c 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.cc
@@ -246,11 +246,13 @@ bool ViewTransitionStyleTracker::MatchForOnlyChild( PseudoId pseudo_id, - AtomicString view_transition_name) const { - DCHECK(view_transition_name); - + const AtomicString& view_transition_name) const { switch (pseudo_id) { + case kPseudoIdViewTransition: + DCHECK(!view_transition_name); + return false; case kPseudoIdViewTransitionGroup: { + DCHECK(view_transition_name); const bool has_root = old_root_data_ || new_root_data_; if (has_root) { return element_data_map_.empty(); @@ -260,8 +262,10 @@ } } case kPseudoIdViewTransitionImagePair: + DCHECK(view_transition_name); return true; case kPseudoIdViewTransitionOld: { + DCHECK(view_transition_name); if (new_root_data_ && new_root_data_->names.Contains(view_transition_name)) { return false; @@ -278,6 +282,7 @@ return !element_data->new_snapshot_id.IsValid(); } case kPseudoIdViewTransitionNew: { + DCHECK(view_transition_name); if (old_root_data_ && old_root_data_->names.Contains(view_transition_name)) { return false;
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h index b80d333..c355b3c 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h +++ b/third_party/blink/renderer/core/view_transition/view_transition_style_tracker.h
@@ -72,7 +72,7 @@ // Returns true if the pseudo element corresponding to the given id and name // is the only child. bool MatchForOnlyChild(PseudoId pseudo_id, - AtomicString view_transition_name) const; + const AtomicString& view_transition_name) const; // Indicate that capture was requested. This verifies that the combination of // set elements and names is valid. Returns true if capture phase started, and
diff --git a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc index 361d343..c7fd319 100644 --- a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc +++ b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -1166,8 +1166,9 @@ // Scheduling an AX update for the cache will schedule it for both the main // document, and the popup document (if present). - if (document->HasAXObjectCache()) - document->ExistingAXObjectCache()->ScheduleAXUpdate(); + if (auto* cache = document->ExistingAXObjectCache()) { + cache->ScheduleAXUpdate(); + } } void InspectorAccessibilityAgent::ScheduleAXChangeNotification(
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc index dbdf1cc..0cc8161d 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -70,7 +70,6 @@ "all-petite-caps"; const char BaseRenderingContext2D::kUnicaseVariantString[] = "unicase"; const char BaseRenderingContext2D::kTitlingCapsVariantString[] = "titling-caps"; -const double BaseRenderingContext2D::kCDeviceScaleFactor = 1.0; const char BaseRenderingContext2D::kAutoRendering[] = "auto"; const char BaseRenderingContext2D::kOptimizeSpeedRendering[] = "optimizespeed"; const char BaseRenderingContext2D::kOptimizeLegibilityRendering[] =
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h index d4af81d..7382ca2b 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
@@ -499,8 +499,6 @@ static const char kOptimizeSpeedRendering[]; static const char kOptimizeLegibilityRendering[]; static const char kGeometricPrecisionRendering[]; - // Canvas is device independent - static const double kCDeviceScaleFactor; virtual void DisableAcceleration() {} virtual bool IsPaint2D() const { return false; }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index a2c9b415..bb80974 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -1092,7 +1092,7 @@ TextRunPaintInfo text_run_paint_info(text_run); this->AccessFont().DrawBidiText(c, text_run_paint_info, location, Font::kUseFallbackIfFontNotReady, - kCDeviceScaleFactor, *flags); + *flags); }, [](const SkIRect& rect) // overdraw test lambda { return false; },
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc index 85bec99..bca4788 100644 --- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -731,7 +731,7 @@ TextRunPaintInfo text_run_paint_info(text_run); this->AccessFont().DrawBidiText( paint_canvas, text_run_paint_info, location, - Font::kUseFallbackIfFontNotReady, kCDeviceScaleFactor, *flags); + Font::kUseFallbackIfFontNotReady, *flags); }, [](const SkIRect& rect) // overdraw test lambda { return false; },
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc index 4e36e78..aa578c4 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -1220,20 +1220,22 @@ if (options->publicKey()->extensions()->hasPrf()) { const char* error = validateGetPublicKeyCredentialPRFExtension( *options->publicKey()->extensions()->prf()); - if (error == nullptr && - options->publicKey()->extensions()->prf()->hasEvalByCredential() && + if (error != nullptr) { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kSyntaxError, error)); + return promise; + } + + if (options->publicKey()->extensions()->prf()->hasEvalByCredential() && options->publicKey()->allowCredentials().empty()) { - error = - "'prf' extension has 'evalByCredential' with an empty allow list"; + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNotSupportedError, + "'prf' extension has 'evalByCredential' with an empty allow " + "list")); + return promise; } // Prohibiting uv=preferred is omitted. See // https://github.com/w3c/webauthn/pull/1836. - - if (error != nullptr) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kNotSupportedError, error)); - return promise; - } } if (RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled(context) && options->publicKey()->extensions()->hasPayment()) {
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc index 0c94aa5..fd3dc0c 100644 --- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc +++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc
@@ -77,7 +77,8 @@ // Picture-in-Picture is not allowed if the window is a document // Picture-in-Picture window. - if (RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled() && + if (RuntimeEnabledFeatures::DocumentPictureInPictureAPIEnabled( + GetSupplementable()->GetExecutionContext()) && DomWindow() && DomWindow()->IsPictureInPictureWindow()) { return Status::kDocumentPip; }
diff --git a/third_party/blink/renderer/modules/hid/hid.cc b/third_party/blink/renderer/modules/hid/hid.cc index 2239682..92543c0 100644 --- a/third_party/blink/renderer/modules/hid/hid.cc +++ b/third_party/blink/renderer/modules/hid/hid.cc
@@ -35,11 +35,28 @@ // requirements for them to be served are met. Returns true if any conditions // fail to be met, generating an appropriate exception as well. Otherwise, // returns false to indicate the call should be allowed. -bool ShouldBlockHidServiceCall(ExecutionContext* context, +bool ShouldBlockHidServiceCall(LocalDOMWindow* window, + ExecutionContext* context, ExceptionState& exception_state) { if (!context) { exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError, kContextGone); + return true; + } + + // The security origin must match the one checked by the browser process. + // Service Workers do not use delegated permissions so we use their security + // origin directly. + DCHECK(context->IsWindow() || context->IsServiceWorkerGlobalScope()); + auto* security_origin = + window + ? window->GetFrame()->Top()->GetSecurityContext()->GetSecurityOrigin() + : context->GetSecurityOrigin(); + + if (security_origin->IsOpaque()) { + exception_state.ThrowSecurityError( + "Access to the WebHID API is denied from contexts where the top-level " + "document has an opaque origin."); } else if (!context->IsFeatureEnabled( mojom::blink::PermissionsPolicyFeature::kHid, ReportOptions::kReportOnFailure)) { @@ -145,7 +162,8 @@ ScriptPromise HID::getDevices(ScriptState* script_state, ExceptionState& exception_state) { - if (ShouldBlockHidServiceCall(GetExecutionContext(), exception_state)) { + if (ShouldBlockHidServiceCall(GetSupplementable()->DomWindow(), + GetExecutionContext(), exception_state)) { return ScriptPromise(); } @@ -163,14 +181,15 @@ ExceptionState& exception_state) { // requestDevice requires a window to satisfy the user activation requirement // and to show a chooser dialog. - const auto* window = GetSupplementable()->DomWindow(); + auto* window = GetSupplementable()->DomWindow(); if (!window) { exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError, kContextGone); return ScriptPromise(); } - if (ShouldBlockHidServiceCall(GetExecutionContext(), exception_state)) { + if (ShouldBlockHidServiceCall(window, GetExecutionContext(), + exception_state)) { return ScriptPromise(); }
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc index e5c1a8a..a05621d2 100644 --- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc +++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -367,9 +367,9 @@ settings->fill_light_mode = ParseFillLightMode(fill_light_mode); } - service_->SetOptions( + service_->SetPhotoOptions( SourceId(), std::move(settings), - WTF::BindOnce(&ImageCapture::OnMojoSetOptions, WrapPersistent(this), + WTF::BindOnce(&ImageCapture::OnMojoSetPhotoOptions, WrapPersistent(this), WrapPersistent(resolver), /*trigger_take_photo=*/true)); return promise; } @@ -783,9 +783,9 @@ service_requests_.insert(resolver); - service_->SetOptions( + service_->SetPhotoOptions( SourceId(), std::move(settings), - WTF::BindOnce(&ImageCapture::OnMojoSetOptions, WrapPersistent(this), + WTF::BindOnce(&ImageCapture::OnMojoSetPhotoOptions, WrapPersistent(this), WrapPersistent(resolver), /*trigger_take_photo=*/false)); } @@ -842,7 +842,7 @@ settings->zoom = zoom.value(); } - service_->SetOptions( + service_->SetPhotoOptions( SourceId(), std::move(settings), WTF::BindOnce(&ImageCapture::OnSetPanTiltZoomSettingsFromTrack, WrapPersistent(this), std::move(initialized_callback))); @@ -1023,17 +1023,17 @@ service_requests_.erase(resolver); } -void ImageCapture::OnMojoSetOptions(ScriptPromiseResolver* resolver, - bool trigger_take_photo, - bool result) { +void ImageCapture::OnMojoSetPhotoOptions(ScriptPromiseResolver* resolver, + bool trigger_take_photo, + bool result) { DCHECK(service_requests_.Contains(resolver)); TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"), - "ImageCapture::OnMojoSetOptions", + "ImageCapture::OnMojoSetPhotoOptions", TRACE_EVENT_SCOPE_PROCESS); if (!result) { resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kUnknownError, "setOptions failed")); + DOMExceptionCode::kUnknownError, "setPhotoOptions failed")); service_requests_.erase(resolver); return; }
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.h b/third_party/blink/renderer/modules/imagecapture/image_capture.h index 66211a2c..5354bae 100644 --- a/third_party/blink/renderer/modules/imagecapture/image_capture.h +++ b/third_party/blink/renderer/modules/imagecapture/image_capture.h
@@ -99,9 +99,9 @@ PromiseResolverFunction, bool trigger_take_photo, media::mojom::blink::PhotoStatePtr); - void OnMojoSetOptions(ScriptPromiseResolver*, - bool trigger_take_photo, - bool result); + void OnMojoSetPhotoOptions(ScriptPromiseResolver*, + bool trigger_take_photo, + bool result); void OnMojoTakePhoto(ScriptPromiseResolver*, media::mojom::blink::BlobPtr); // If getUserMedia contains either pan, tilt, or zoom constraints, the
diff --git a/third_party/blink/renderer/modules/mediastream/test/fake_image_capturer.h b/third_party/blink/renderer/modules/mediastream/test/fake_image_capturer.h index 18e5f90..8ccccdd 100644 --- a/third_party/blink/renderer/modules/mediastream/test/fake_image_capturer.h +++ b/third_party/blink/renderer/modules/mediastream/test/fake_image_capturer.h
@@ -23,9 +23,9 @@ void GetPhotoState(const WTF::String& source_id, GetPhotoStateCallback callback) override; - void SetOptions(const WTF::String& source_id, - media::mojom::blink::PhotoSettingsPtr settings, - SetOptionsCallback callback) override {} + void SetPhotoOptions(const WTF::String& source_id, + media::mojom::blink::PhotoSettingsPtr settings, + SetPhotoOptionsCallback callback) override {} void TakePhoto(const WTF::String& source_id, TakePhotoCallback callback) override {}
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc index 79d40e2f..a3ee99ee 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc
@@ -72,7 +72,7 @@ } webrtc::VideoCodecType VideoCodecTypeFromRTCVideoCodecType( - String video_codec_type) { + const String& video_codec_type) { if (video_codec_type == "vp8") { return webrtc::VideoCodecType::kVideoCodecVP8; } else if (video_codec_type == "vp9") { @@ -85,6 +85,35 @@ } } +String RTCEncodedVideoFrameTypeFromVideoFrameType( + webrtc::VideoFrameType video_frame_type) { + switch (video_frame_type) { + case webrtc::VideoFrameType::kEmptyFrame: + return "empty"; + case webrtc::VideoFrameType::kVideoFrameKey: + return "key"; + case webrtc::VideoFrameType::kVideoFrameDelta: + return "delta"; + default: + NOTREACHED(); + return ""; + } +} + +webrtc::VideoFrameType VideoFrameTypeFromRTCEncodedVideoFrameType( + const String& video_frame_type) { + if (video_frame_type == "empty") { + return webrtc::VideoFrameType::kEmptyFrame; + } else if (video_frame_type == "key") { + return webrtc::VideoFrameType::kVideoFrameKey; + } else if (video_frame_type == "delta") { + return webrtc::VideoFrameType::kVideoFrameDelta; + } else { + NOTREACHED(); + return webrtc::VideoFrameType::kEmptyFrame; + } +} + } // namespace RTCEncodedVideoFrame::RTCEncodedVideoFrame( @@ -176,6 +205,9 @@ LOG(ERROR) << "Unsupported RTCCodecSpecifics."; break; } + + metadata->setFrameType(RTCEncodedVideoFrameTypeFromVideoFrameType( + webrtc_metadata->GetFrameType())); } return metadata; } @@ -213,6 +245,9 @@ webrtc_metadata.SetSimulcastIdx(metadata->simulcastIdx()); webrtc::VideoCodecType codec = VideoCodecTypeFromRTCVideoCodecType(metadata->codec()); + webrtc_metadata.SetFrameType( + VideoFrameTypeFromRTCEncodedVideoFrameType(metadata->frameType())); + webrtc_metadata.SetCodec(codec); switch (codec) { case webrtc::VideoCodecType::kVideoCodecVP8: {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_metadata.idl b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_metadata.idl index 3eff127..3a20574 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_metadata.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_metadata.idl
@@ -37,6 +37,8 @@ RTCVideoCodecType codec; [RuntimeEnabled=RTCEncodedVideoFrameAdditionalMetadata] RTCCodecSpecifics codecSpecifics; + [RuntimeEnabled=RTCEncodedVideoFrameAdditionalMetadata] + RTCEncodedVideoFrameType frameType; // RTP related metadata unsigned long synchronizationSource;
diff --git a/third_party/blink/renderer/modules/sanitizer_api/README.md b/third_party/blink/renderer/modules/sanitizer_api/README.md index e438ada..c065e4c 100644 --- a/third_party/blink/renderer/modules/sanitizer_api/README.md +++ b/third_party/blink/renderer/modules/sanitizer_api/README.md
@@ -24,15 +24,13 @@ ## Staged / Incremental Rollout -The Sanitizer API is scheduled to be launched in stages. The API availability +An initial version of the Sanitizer API is enabled by default. Additional +features are scheduled to be launched in stages. The API availability can be controlled via flags: -* `--enable-blink-features=SanitizerAPIv0`: This includes the basic Sanitizer - API with configuration and the `Element.setHTML` method, but not the - `.sanitizeFor` or `.sanitize` methods. This flag is on by default. -* `--enable-blink-features=SanitizerAPI`: This includes `SanitizerAPv0` - plus the sanitization methods of the `Sanitizer` object, as specified - as of 04/2022. These APIs are likely to change. +* `--enable-blink-features=SanitizerAPI`: This includes the sanitization + methods of the `Sanitizer` object, as specified as of 04/2022. +These APIs are likely to change. The general `--enable-experimental-web-platform-features` flag implies the full `--enable-blink-features=SanitizerAPI` feature set.
diff --git a/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl b/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl index e0afbb8..a8a9180 100644 --- a/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl +++ b/third_party/blink/renderer/modules/sanitizer_api/element_sanitizer.idl
@@ -4,14 +4,11 @@ // https://github.com/WICG/sanitizer-api -[ - RuntimeEnabled=SanitizerAPIv0 -] dictionary ElementSetHTMLOptions { +dictionary ElementSetHTMLOptions { Sanitizer sanitizer; }; [ - RuntimeEnabled=SanitizerAPIv0, SecureContext, ImplementedAs=ElementSanitizer ] partial interface Element {
diff --git a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl index 97405e68..1a4823e5 100644 --- a/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl +++ b/third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl
@@ -8,8 +8,7 @@ [ Exposed=Window, - SecureContext, - RuntimeEnabled=SanitizerAPIv0 + SecureContext ] interface Sanitizer { [MeasureAs=SanitizerAPICreated, CallWith=ExecutionContext, RaisesException] constructor(optional SanitizerConfig config = {});
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h index 33c3568..fba82b5 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -37,6 +37,7 @@ #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "services/network/public/cpp/data_element.h" #include "services/network/public/mojom/network_context.mojom-blink-forward.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h"
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc index 76d4be1..cd6709e 100644 --- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc +++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -14,6 +14,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#include "services/network/public/cpp/resource_request.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h"
diff --git a/third_party/blink/renderer/modules/wake_lock/README.md b/third_party/blink/renderer/modules/wake_lock/README.md index e52ef4e..3d72508 100644 --- a/third_party/blink/renderer/modules/wake_lock/README.md +++ b/third_party/blink/renderer/modules/wake_lock/README.md
@@ -42,7 +42,7 @@ ### Testing -Validation, exception types, permissions policy integration and general IDL compliance are tested in [web platform tests], while Chromium-specific implementation details (e.g. permission handling) are tested in [web tests]. +Validation, exception types, permissions policy integration and general IDL compliance are tested in [web platform tests]. Larger parts of the Blink implementation are tested as browser and unit tests: @@ -53,7 +53,6 @@ * content_shell implements its own permission logic that mimics what is done in `//chrome` in [`shell_permission_manager.cc`](/content/shell/browser/shell_permission_manager.cc). [web platform tests]: ../../../web_tests/external/wpt/screen-wake-lock/ -[web tests]: ../../../web_tests/wake-lock/ ## Example workflows
diff --git a/third_party/blink/renderer/modules/webaudio/audio_destination_handler.h b/third_party/blink/renderer/modules/webaudio/audio_destination_handler.h index 97c590e..9e0516f 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_destination_handler.h +++ b/third_party/blink/renderer/modules/webaudio/audio_destination_handler.h
@@ -36,6 +36,11 @@ // restart of the context. virtual void RestartRendering() = 0; + // The worklet thread change can happen when a context/destination is + // suspended. In that case, we prepare the worklet operation but do not start + // running. + virtual void PrepareTaskRunnerForWorklet() = 0; + size_t CurrentSampleFrame() const { return current_sample_frame_.load(std::memory_order_acquire); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc index ce05890..9ded3a8 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
@@ -251,8 +251,9 @@ return processor_info_list; } -ProcessorCreationParams* AudioWorkletGlobalScope::GetProcessorCreationParams() { - return processor_creation_params_.get(); +std::unique_ptr<ProcessorCreationParams> +AudioWorkletGlobalScope::GetProcessorCreationParams() { + return std::move(processor_creation_params_); } void AudioWorkletGlobalScope::SetCurrentFrame(size_t current_frame) {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h index 479cea8..5a81191 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h
@@ -87,7 +87,7 @@ // Gets `processor_creation_params_` for the processor construction. If there // is no on-going processor construction, this MUST return `nullptr`. - ProcessorCreationParams* GetProcessorCreationParams(); + std::unique_ptr<ProcessorCreationParams> GetProcessorCreationParams(); void SetCurrentFrame(size_t current_frame); void SetSampleRate(float sample_rate);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc index ed694bc..1f884cb1 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h" +#include <memory> + #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_blink_audio_worklet_process_callback.h" #include "third_party/blink/renderer/core/messaging/message_port.h" @@ -17,15 +19,23 @@ namespace blink { AudioWorkletProcessor* AudioWorkletProcessor::Create( - ExecutionContext* context) { + ExecutionContext* context, + ExceptionState& exception_state) { AudioWorkletGlobalScope* global_scope = To<AudioWorkletGlobalScope>(context); DCHECK(global_scope); DCHECK(global_scope->IsContextThread()); // Get the stored initialization parameter from the global scope. - ProcessorCreationParams* params = global_scope->GetProcessorCreationParams(); - DCHECK(params); + std::unique_ptr<ProcessorCreationParams> params = + global_scope->GetProcessorCreationParams(); + // `params` can be null if there's no matching AudioWorkletNode instance. + // (e.g. invoking AudioWorkletProcessor directly in AudioWorkletGlobalScope) + if (!params) { + exception_state.ThrowTypeError( + "Illegal invocation of AudioWorkletProcessor constructor."); + return nullptr; + } auto* port = MakeGarbageCollected<MessagePort>(*global_scope); port->Entangle(std::move(params->PortChannel())); return MakeGarbageCollected<AudioWorkletProcessor>(global_scope,
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h index 77ab2a3..8284ccf 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.h
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/webaudio/audio_worklet_processor_error_state.h" #include "third_party/blink/renderer/platform/audio/audio_array.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -37,7 +38,7 @@ // AudioWorkletNode gets created by user-supplied JS code in the main // thread. This factory must not be called by user in // AudioWorkletGlobalScope. - static AudioWorkletProcessor* Create(ExecutionContext*); + static AudioWorkletProcessor* Create(ExecutionContext*, ExceptionState&); AudioWorkletProcessor(AudioWorkletGlobalScope*, const String& name,
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.idl b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.idl index 34ace51..327c63c 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.idl +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_processor.idl
@@ -7,6 +7,6 @@ [ Exposed=AudioWorklet ] interface AudioWorkletProcessor { - [CallWith=ExecutionContext] constructor(); + [CallWith=ExecutionContext, RaisesException] constructor(); readonly attribute MessagePort port; };
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc index 66cffa84..2d37a7576 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -896,12 +896,24 @@ audioWorklet()->GetMessagingProxy()->GetBackingWorkerThread(); } - // If the context is running, restart the destination to switch the render - // thread with the worklet thread. When the context is suspended, the next - // resume() call will start rendering with the worklet thread. - // Note that restarting can happen right after the context construction. - if (ContextState() == kRunning) { - destination()->GetAudioDestinationHandler().RestartRendering(); + switch (ContextState()) { + case kRunning: + // If the context is running, restart the destination to switch the render + // thread with the worklet thread right away. + destination()->GetAudioDestinationHandler().RestartRendering(); + break; + case kSuspended: + // For the suspended context, the destination will use the worklet task + // runner for rendering. This also prevents the regular audio thread from + // touching worklet-related objects by blocking an invalid transitory + // state where the context state is suspended and the destination state is + // running. See: crbug.com/1403515 + destination()->GetAudioDestinationHandler().PrepareTaskRunnerForWorklet(); + break; + case kClosed: + // When the context is closed, no preparation for the worklet operations + // is necessary. + return; } }
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h index 88fb292b8..461facf 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_handler.h
@@ -47,6 +47,7 @@ void Pause() override; void Resume() override; uint32_t MaxChannelCount() const override; + void PrepareTaskRunnerForWorklet() override {} void RestartRendering() override;
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc index 19b5ea67..12b6b5ae 100644 --- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.cc
@@ -364,6 +364,18 @@ } } +void RealtimeAudioDestinationHandler::PrepareTaskRunnerForWorklet() { + DCHECK(IsMainThread()); + DCHECK_EQ(Context()->ContextState(), BaseAudioContext::kSuspended); + DCHECK(Context()->audioWorklet()); + DCHECK(Context()->audioWorklet()->IsReady()); + + platform_destination_->SetWorkletTaskRunner( + Context()->audioWorklet()->GetMessagingProxy() + ->GetBackingWorkerThread() + ->GetTaskRunner(TaskType::kInternalMediaRealTime)); +} + void RealtimeAudioDestinationHandler::SetSinkDescriptor( const WebAudioSinkDescriptor& sink_descriptor, media::OutputDeviceStatusCB callback) {
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.h b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.h index e32019e3..2e6b5dc 100644 --- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.h +++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_handler.h
@@ -53,6 +53,7 @@ void RestartRendering() override; uint32_t MaxChannelCount() const override; double SampleRate() const override; + void PrepareTaskRunnerForWorklet() override; // For AudioIOCallback. This is invoked by the platform audio destination to // get the next render quantum into `destination_bus` and update
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc index ea14013..9513335 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -118,6 +118,8 @@ std::string label; WGPUBufferDescriptor dawn_desc = AsDawnType(webgpu_desc, &label); + // Save the requested size of the buffer, for reflection and defaults. + uint64_t buffer_size = dawn_desc.size; // If the buffer is mappable, make sure the size stays in a size_t but still // guarantees that we have an OOM. bool is_mappable = @@ -141,7 +143,7 @@ } GPUBuffer* buffer = - MakeGarbageCollected<GPUBuffer>(device, dawn_desc.size, wgpuBuffer); + MakeGarbageCollected<GPUBuffer>(device, buffer_size, wgpuBuffer); if (webgpu_desc->hasLabel()) buffer->setLabel(webgpu_desc->label());
diff --git a/third_party/blink/renderer/platform/audio/audio_destination.cc b/third_party/blink/renderer/platform/audio/audio_destination.cc index ffa7038f..3bcf236 100644 --- a/third_party/blink/renderer/platform/audio/audio_destination.cc +++ b/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -216,10 +216,25 @@ SetDeviceState(DeviceState::kRunning); } +void AudioDestination::SetWorkletTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner) { + DCHECK(IsMainThread()); + TRACE_EVENT0("webaudio", "AudioDestination::SetWorkletTaskRunner"); + + if (worklet_task_runner_) { + DCHECK_EQ(worklet_task_runner_, worklet_task_runner); + return; + } + + // The dual-thread rendering kicks off, so update the earmark frames + // accordingly. + fifo_->SetEarmarkFrames(callback_buffer_size_); + worklet_task_runner_ = std::move(worklet_task_runner); +} + void AudioDestination::StartWithWorkletTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner) { DCHECK(IsMainThread()); - DCHECK_EQ(worklet_task_runner_, nullptr); TRACE_EVENT0("webaudio", "AudioDestination::StartWithWorkletTaskRunner"); SendLogMessage(String::Format("%s", __func__)); @@ -227,11 +242,7 @@ return; } - // The dual-thread rendering kicks off, so update the earmark frames - // accordingly. - fifo_->SetEarmarkFrames(callback_buffer_size_); - - worklet_task_runner_ = std::move(worklet_task_runner); + SetWorkletTaskRunner(worklet_task_runner); web_audio_device_->Start(); SetDeviceState(DeviceState::kRunning); }
diff --git a/third_party/blink/renderer/platform/audio/audio_destination.h b/third_party/blink/renderer/platform/audio/audio_destination.h index b0416038..f53bc7b 100644 --- a/third_party/blink/renderer/platform/audio/audio_destination.h +++ b/third_party/blink/renderer/platform/audio/audio_destination.h
@@ -103,7 +103,11 @@ void Pause(); void Resume(); - // Starts the destination with the AudioWorklet support. + // Sets the destination for worklet operation, but does not start rendering. + void SetWorkletTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner); + + // Starts rendering in the AudioWorklet mode. void StartWithWorkletTaskRunner( scoped_refptr<base::SingleThreadTaskRunner> worklet_task_runner);
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc index 089a11b..d7ab37b 100644 --- a/third_party/blink/renderer/platform/fonts/font.cc +++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -211,17 +211,14 @@ void Font::DrawText(cc::PaintCanvas* canvas, const TextRunPaintInfo& run_info, const gfx::PointF& point, - float device_scale_factor, const cc::PaintFlags& flags, DrawType draw_type) const { - DrawText(canvas, run_info, point, device_scale_factor, cc::kInvalidNodeId, - flags, draw_type); + DrawText(canvas, run_info, point, cc::kInvalidNodeId, flags, draw_type); } void Font::DrawText(cc::PaintCanvas* canvas, const TextRunPaintInfo& run_info, const gfx::PointF& point, - float device_scale_factor, cc::NodeId node_id, const cc::PaintFlags& flags, DrawType draw_type) const { @@ -234,7 +231,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, run_info, buffer, + GetFontDescription(), run_info, buffer, draw_type == Font::DrawType::kGlyphsOnly ? ShapeResultBloberizer::Type::kNormal : ShapeResultBloberizer::Type::kEmitText); @@ -244,7 +241,6 @@ void Font::DrawText(cc::PaintCanvas* canvas, const NGTextFragmentPaintInfo& text_info, const gfx::PointF& point, - float device_scale_factor, cc::NodeId node_id, const cc::PaintFlags& flags, DrawType draw_type) const { @@ -254,8 +250,8 @@ return; ShapeResultBloberizer::FillGlyphsNG bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, text_info.text, - text_info.from, text_info.to, text_info.shape_result, + GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, draw_type == Font::DrawType::kGlyphsOnly ? ShapeResultBloberizer::Type::kNormal : ShapeResultBloberizer::Type::kEmitText); @@ -266,7 +262,6 @@ const TextRunPaintInfo& run_info, const gfx::PointF& point, CustomFontNotReadyAction custom_font_not_ready_action, - float device_scale_factor, const cc::PaintFlags& flags, DrawType draw_type) const { // Don't draw anything while we are using custom fonts that are in the process @@ -310,7 +305,7 @@ // Fix regression with -ftrivial-auto-var-init=pattern. See // crbug.com/1055652. STACK_UNINITIALIZED ShapeResultBloberizer::FillGlyphs bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, subrun_info, buffer, + GetFontDescription(), subrun_info, buffer, draw_type == Font::DrawType::kGlyphsOnly ? ShapeResultBloberizer::Type::kNormal : ShapeResultBloberizer::Type::kEmitText); @@ -328,7 +323,6 @@ const TextRunPaintInfo& run_info, const AtomicString& mark, const gfx::PointF& point, - float device_scale_factor, const cc::PaintFlags& flags) const { if (ShouldSkipDrawing()) return; @@ -343,8 +337,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillTextEmphasisGlyphs bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, run_info, buffer, - emphasis_glyph_data); + GetFontDescription(), run_info, buffer, emphasis_glyph_data); DrawBlobs(canvas, flags, bloberizer.Blobs(), point); } @@ -352,7 +345,6 @@ const NGTextFragmentPaintInfo& text_info, const AtomicString& mark, const gfx::PointF& point, - float device_scale_factor, const cc::PaintFlags& flags) const { if (ShouldSkipDrawing()) return; @@ -363,9 +355,8 @@ return; ShapeResultBloberizer::FillTextEmphasisGlyphsNG bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, text_info.text, - text_info.from, text_info.to, text_info.shape_result, - emphasis_glyph_data); + GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, emphasis_glyph_data); DrawBlobs(canvas, flags, bloberizer.Blobs(), point); } @@ -441,7 +432,6 @@ } // anonymous namespace void Font::GetTextIntercepts(const TextRunPaintInfo& run_info, - float device_scale_factor, const cc::PaintFlags& flags, const std::tuple<float, float>& bounds, Vector<TextIntercept>& intercepts) const { @@ -452,14 +442,13 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, run_info, buffer, + GetFontDescription(), run_info, buffer, ShapeResultBloberizer::Type::kTextIntercepts); GetTextInterceptsInternal(bloberizer.Blobs(), flags, bounds, intercepts); } void Font::GetTextIntercepts(const NGTextFragmentPaintInfo& text_info, - float device_scale_factor, const cc::PaintFlags& flags, const std::tuple<float, float>& bounds, Vector<TextIntercept>& intercepts) const { @@ -467,9 +456,8 @@ return; ShapeResultBloberizer::FillGlyphsNG bloberizer( - GetFontDescription(), device_scale_factor > 1.0f, text_info.text, - text_info.from, text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kTextIntercepts); + GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kTextIntercepts); GetTextInterceptsInternal(bloberizer.Blobs(), flags, bounds, intercepts); }
diff --git a/third_party/blink/renderer/platform/fonts/font.h b/third_party/blink/renderer/platform/fonts/font.h index e616859..8c559e2 100644 --- a/third_party/blink/renderer/platform/fonts/font.h +++ b/third_party/blink/renderer/platform/fonts/font.h
@@ -89,20 +89,17 @@ void DrawText(cc::PaintCanvas*, const TextRunPaintInfo&, const gfx::PointF&, - float device_scale_factor, const cc::PaintFlags&, DrawType = DrawType::kGlyphsOnly) const; void DrawText(cc::PaintCanvas*, const TextRunPaintInfo&, const gfx::PointF&, - float device_scale_factor, cc::NodeId node_id, const cc::PaintFlags&, DrawType = DrawType::kGlyphsOnly) const; void DrawText(cc::PaintCanvas*, const NGTextFragmentPaintInfo&, const gfx::PointF&, - float device_scale_factor, cc::NodeId node_id, const cc::PaintFlags&, DrawType = DrawType::kGlyphsOnly) const; @@ -110,20 +107,17 @@ const TextRunPaintInfo&, const gfx::PointF&, CustomFontNotReadyAction, - float device_scale_factor, const cc::PaintFlags&, DrawType = DrawType::kGlyphsOnly) const; void DrawEmphasisMarks(cc::PaintCanvas*, const TextRunPaintInfo&, const AtomicString& mark, const gfx::PointF&, - float device_scale_factor, const cc::PaintFlags&) const; void DrawEmphasisMarks(cc::PaintCanvas*, const NGTextFragmentPaintInfo&, const AtomicString& mark, const gfx::PointF&, - float device_scale_factor, const cc::PaintFlags&) const; gfx::RectF TextInkBounds(const NGTextFragmentPaintInfo&) const; @@ -139,12 +133,10 @@ // a line crossing through the text, parallel to the baseline. // TODO(drott): crbug.com/655154 Fix this for upright in vertical. void GetTextIntercepts(const TextRunPaintInfo&, - float device_scale_factor, const cc::PaintFlags&, const std::tuple<float, float>& bounds, Vector<TextIntercept>&) const; void GetTextIntercepts(const NGTextFragmentPaintInfo&, - float device_scale_factor, const cc::PaintFlags&, const std::tuple<float, float>& bounds, Vector<TextIntercept>&) const;
diff --git a/third_party/blink/renderer/platform/fonts/font_platform_data.cc b/third_party/blink/renderer/platform/fonts/font_platform_data.cc index 1a6bf6f..ef9353c 100644 --- a/third_party/blink/renderer/platform/fonts/font_platform_data.cc +++ b/third_party/blink/renderer/platform/fonts/font_platform_data.cc
@@ -284,10 +284,9 @@ return result; } -SkFont FontPlatformData::CreateSkFont(bool should_use_subpixel_positioning, - const FontDescription*) const { +SkFont FontPlatformData::CreateSkFont(const FontDescription*) const { SkFont font; - style_.ApplyToSkFont(&font, should_use_subpixel_positioning); + style_.ApplyToSkFont(&font); const float ts = text_size_ >= 0 ? text_size_ : 12; font.setSize(SkFloatToScalar(ts));
diff --git a/third_party/blink/renderer/platform/fonts/font_platform_data.h b/third_party/blink/renderer/platform/fonts/font_platform_data.h index 8ee73a1..530b5969 100644 --- a/third_party/blink/renderer/platform/fonts/font_platform_data.h +++ b/third_party/blink/renderer/platform/fonts/font_platform_data.h
@@ -136,8 +136,7 @@ const WebFontRenderStyle& GetFontRenderStyle() const { return style_; } #endif - SkFont CreateSkFont(bool should_use_subpixel_positioning = false, - const FontDescription* = nullptr) const; + SkFont CreateSkFont(const FontDescription* = nullptr) const; scoped_refptr<OpenTypeVerticalData> CreateVerticalData() const;
diff --git a/third_party/blink/renderer/platform/fonts/font_test.cc b/third_party/blink/renderer/platform/fonts/font_test.cc index 75fe34d6..33b02d5 100644 --- a/third_party/blink/renderer/platform/fonts/font_test.cc +++ b/third_party/blink/renderer/platform/fonts/font_test.cc
@@ -157,13 +157,12 @@ TextRun ahem_above_below_baseline(ahem_above_below_baseline_string, 9); TextRunPaintInfo text_run_paint_info(ahem_above_below_baseline); cc::PaintFlags default_paint; - float device_scale_factor = 1; std::tuple<float, float> below_baseline_bounds = std::make_tuple(2, 4); Vector<Font::TextIntercept> text_intercepts; // 4 intercept ranges for below baseline p glyphs in the test string - font.GetTextIntercepts(text_run_paint_info, device_scale_factor, - default_paint, below_baseline_bounds, text_intercepts); + font.GetTextIntercepts(text_run_paint_info, default_paint, + below_baseline_bounds, text_intercepts); EXPECT_EQ(text_intercepts.size(), 4u); for (auto text_intercept : text_intercepts) { EXPECT_GT(text_intercept.end_, text_intercept.begin_); @@ -171,8 +170,8 @@ std::tuple<float, float> above_baseline_bounds = std::make_tuple(-4, -2); // 5 intercept ranges for the above baseline E ACUTE glyphs - font.GetTextIntercepts(text_run_paint_info, device_scale_factor, - default_paint, above_baseline_bounds, text_intercepts); + font.GetTextIntercepts(text_run_paint_info, default_paint, + above_baseline_bounds, text_intercepts); EXPECT_EQ(text_intercepts.size(), 5u); for (auto text_intercept : text_intercepts) { EXPECT_GT(text_intercept.end_, text_intercept.begin_);
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm index 76a8ca0d..db856db 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
@@ -263,7 +263,6 @@ } SkFont FontPlatformData::CreateSkFont( - bool, const FontDescription* font_description) const { bool should_smooth_fonts = true; bool should_antialias = true;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc index 8e5e0bce..a3d2851 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
@@ -55,9 +55,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 0, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); bloberizer_ng.Blobs(); // Bloberize @@ -79,7 +78,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(subrun_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - font.GetFontDescription(), false, subrun_info, buffer, + font.GetFontDescription(), subrun_info, buffer, ShapeResultBloberizer::Type::kEmitText); bloberizer.Blobs(); }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc index 0bb039a3..60e3c32 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -31,11 +31,8 @@ ShapeResultBloberizer::ShapeResultBloberizer( const FontDescription& font_description, - bool should_use_subpixel_antialiasing, Type type) - : font_description_(font_description), - should_use_subpixel_antialiasing_(should_use_subpixel_antialiasing), - type_(type) {} + : font_description_(font_description), type_(type) {} bool ShapeResultBloberizer::HasPendingVerticalOffsets() const { // We exclusively store either horizontal/x-only offsets -- in which case @@ -168,8 +165,8 @@ if (UNLIKELY(!current_character_indexes_.empty())) CommitText(); - SkFont run_font = pending_font_data_->PlatformData().CreateSkFont( - should_use_subpixel_antialiasing_, &font_description_); + SkFont run_font = + pending_font_data_->PlatformData().CreateSkFont(&font_description_); const auto run_size = pending_glyphs_.size(); const auto text_size = pending_utf8_.size(); @@ -432,13 +429,10 @@ ShapeResultBloberizer::FillGlyphs::FillGlyphs( const FontDescription& font_description, - bool should_use_subpixel_antialiasing, const TextRunPaintInfo& run_info, const ShapeResultBuffer& result_buffer, const Type type) - : ShapeResultBloberizer(font_description, - should_use_subpixel_antialiasing, - type) { + : ShapeResultBloberizer(font_description, type) { if (CanUseFastPath(run_info.from, run_info.to, run_info.run.length(), result_buffer.HasVerticalOffsets())) { DVLOG(4) << "FillGlyphs fast path"; @@ -506,15 +500,12 @@ ShapeResultBloberizer::FillGlyphsNG::FillGlyphsNG( const FontDescription& font_description, - bool should_use_subpixel_antialiasing, const StringView& text, unsigned from, unsigned to, const ShapeResultView* result, const Type type) - : ShapeResultBloberizer(font_description, - should_use_subpixel_antialiasing, - type) { + : ShapeResultBloberizer(font_description, type) { DCHECK(result); DCHECK(to <= text.length()); float initial_advance = 0; @@ -551,13 +542,10 @@ ShapeResultBloberizer::FillTextEmphasisGlyphs::FillTextEmphasisGlyphs( const FontDescription& font_description, - bool should_use_subpixel_antialiasing, const TextRunPaintInfo& run_info, const ShapeResultBuffer& result_buffer, const GlyphData& emphasis) - : ShapeResultBloberizer(font_description, - should_use_subpixel_antialiasing, - Type::kNormal) { + : ShapeResultBloberizer(font_description, Type::kNormal) { gfx::PointF glyph_center = emphasis.font_data->BoundsForGlyph(emphasis.glyph).CenterPoint(); @@ -594,15 +582,12 @@ ShapeResultBloberizer::FillTextEmphasisGlyphsNG::FillTextEmphasisGlyphsNG( const FontDescription& font_description, - bool should_use_subpixel_antialiasing, const StringView& text, unsigned from, unsigned to, const ShapeResultView* result, const GlyphData& emphasis) - : ShapeResultBloberizer(font_description, - should_use_subpixel_antialiasing, - Type::kNormal) { + : ShapeResultBloberizer(font_description, Type::kNormal) { gfx::PointF glyph_center = emphasis.font_data->BoundsForGlyph(emphasis.glyph).CenterPoint(); ClusterCallbackContext context = {this, text, emphasis, glyph_center};
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h index 8de04ca..245e8536 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
@@ -33,9 +33,7 @@ struct FillGlyphs; struct FillTextEmphasisGlyphs; - explicit ShapeResultBloberizer(const FontDescription&, - bool should_use_subpixel_antialiasing, - Type); + explicit ShapeResultBloberizer(const FontDescription&, Type); ShapeResultBloberizer(const ShapeResultBloberizer&) = delete; ShapeResultBloberizer& operator=(const ShapeResultBloberizer&) = delete; @@ -169,7 +167,6 @@ bool HasPendingVerticalOffsets() const; const FontDescription& font_description_; - const bool should_use_subpixel_antialiasing_; const Type type_; // Current text blob state. @@ -204,7 +201,6 @@ struct PLATFORM_EXPORT ShapeResultBloberizer::FillGlyphsNG : public ShapeResultBloberizer { FillGlyphsNG(const FontDescription&, - bool should_use_subpixel_antialiasing, const StringView&, unsigned from, unsigned to, @@ -214,7 +210,6 @@ struct PLATFORM_EXPORT ShapeResultBloberizer::FillTextEmphasisGlyphsNG : public ShapeResultBloberizer { FillTextEmphasisGlyphsNG(const FontDescription&, - bool should_use_subpixel_antialiasing, const StringView&, unsigned from, unsigned to, @@ -225,7 +220,6 @@ struct PLATFORM_EXPORT ShapeResultBloberizer::FillGlyphs : public ShapeResultBloberizer { FillGlyphs(const FontDescription&, - bool should_use_subpixel_antialiasing, const TextRunPaintInfo&, const ShapeResultBuffer&, Type); @@ -233,7 +227,6 @@ struct PLATFORM_EXPORT ShapeResultBloberizer::FillTextEmphasisGlyphs : public ShapeResultBloberizer { FillTextEmphasisGlyphs(const FontDescription&, - bool should_use_subpixel_antialiasing, const TextRunPaintInfo&, const ShapeResultBuffer&, const GlyphData& emphasis_data);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc index 95b021c6..4a9e2b6 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer_test.cc
@@ -127,7 +127,7 @@ TEST_F(ShapeResultBloberizerTest, StartsEmpty) { Font font; - ShapeResultBloberizer bloberizer(font.GetFontDescription(), 1, + ShapeResultBloberizer bloberizer(font.GetFontDescription(), ShapeResultBloberizer::Type::kNormal); EXPECT_EQ(ShapeResultBloberizerTestInfo::PendingRunFontData(bloberizer), @@ -147,7 +147,7 @@ TEST_F(ShapeResultBloberizerTest, StoresGlyphsOffsets) { Font font; - ShapeResultBloberizer bloberizer(font.GetFontDescription(), 1, + ShapeResultBloberizer bloberizer(font.GetFontDescription(), ShapeResultBloberizer::Type::kNormal); scoped_refptr<SimpleFontData> font1 = CreateTestSimpleFontData(); @@ -211,7 +211,7 @@ TEST_F(ShapeResultBloberizerTest, StoresGlyphsVerticalOffsets) { Font font; - ShapeResultBloberizer bloberizer(font.GetFontDescription(), 1, + ShapeResultBloberizer bloberizer(font.GetFontDescription(), ShapeResultBloberizer::Type::kNormal); scoped_refptr<SimpleFontData> font1 = CreateTestSimpleFontData(); @@ -281,7 +281,7 @@ TEST_F(ShapeResultBloberizerTest, MixedBlobRotation) { Font font; - ShapeResultBloberizer bloberizer(font.GetFontDescription(), 1, + ShapeResultBloberizer bloberizer(font.GetFontDescription(), ShapeResultBloberizer::Type::kNormal); scoped_refptr<SimpleFontData> test_font = CreateTestSimpleFontData(); @@ -343,7 +343,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - font.GetFontDescription(), false, run_info, buffer, + font.GetFontDescription(), run_info, buffer, ShapeResultBloberizer::Type::kEmitText); Font reference_font(font_description); @@ -353,7 +353,7 @@ ShapeResultBuffer reference_buffer; reference_word_shaper.FillResultBuffer(run_info, &reference_buffer); ShapeResultBloberizer::FillGlyphs reference_bloberizer( - reference_font.GetFontDescription(), false, run_info, reference_buffer, + reference_font.GetFontDescription(), run_info, reference_buffer, ShapeResultBloberizer::Type::kEmitText); const auto& glyphs = @@ -393,7 +393,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - font.GetFontDescription(), false, run_info, buffer, + font.GetFontDescription(), run_info, buffer, ShapeResultBloberizer::Type::kEmitText); Font reference_font(font_description); @@ -403,7 +403,7 @@ ShapeResultBuffer reference_buffer; reference_word_shaper.FillResultBuffer(run_info, &reference_buffer); ShapeResultBloberizer::FillGlyphs reference_bloberizer( - reference_font.GetFontDescription(), false, run_info, reference_buffer, + reference_font.GetFontDescription(), run_info, reference_buffer, ShapeResultBloberizer::Type::kEmitText); const auto& glyphs = @@ -433,9 +433,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 1, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); CheckBlobBuffer( bloberizer_ng.Blobs(), @@ -460,9 +459,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 0, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); CheckBlobBuffer( bloberizer_ng.Blobs(), @@ -488,9 +486,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 1, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); // Do not expect the trailing surrogate to be in any output. const auto& glyphs = @@ -543,9 +540,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 1, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); CheckBlobBuffer( bloberizer_ng.Blobs(), @@ -604,9 +600,8 @@ NGTextFragmentPaintInfo text_info{StringView(string), 0, string.length(), result_view.get()}; ShapeResultBloberizer::FillGlyphsNG bloberizer_ng( - font.GetFontDescription(), false, text_info.text, text_info.from, - text_info.to, text_info.shape_result, - ShapeResultBloberizer::Type::kEmitText); + font.GetFontDescription(), text_info.text, text_info.from, text_info.to, + text_info.shape_result, ShapeResultBloberizer::Type::kEmitText); CheckBlobBuffer(bloberizer_ng.Blobs(), {{ @@ -643,7 +638,7 @@ ShapeResultBuffer buffer; word_shaper.FillResultBuffer(run_info, &buffer); ShapeResultBloberizer::FillGlyphs bloberizer( - font.GetFontDescription(), false, run_info, buffer, + font.GetFontDescription(), run_info, buffer, ShapeResultBloberizer::Type::kEmitText); shaper.GetCharacterRange(text_run, 0, 8);
diff --git a/third_party/blink/renderer/platform/fonts/web_font_render_style.cc b/third_party/blink/renderer/platform/fonts/web_font_render_style.cc index 35ef5e9..5ccc450 100644 --- a/third_party/blink/renderer/platform/fonts/web_font_render_style.cc +++ b/third_party/blink/renderer/platform/fonts/web_font_render_style.cc
@@ -96,9 +96,7 @@ use_subpixel_positioning = other.use_subpixel_positioning; } -void WebFontRenderStyle::ApplyToSkFont( - SkFont* font, - bool should_use_subpixel_positioning) const { +void WebFontRenderStyle::ApplyToSkFont(SkFont* font) const { auto sk_hint_style = static_cast<SkFontHinting>(hint_style); font->setHinting(sk_hint_style); font->setEmbeddedBitmaps(use_bitmaps); @@ -111,11 +109,10 @@ font->setEdging(SkFont::Edging::kAlias); } - // Force-enable subpixel positioning, except when full hinting is requested on - // low-dpi screen or when running web tests. + // Force-enable subpixel positioning, except when full hinting is requested + // or when running web tests. bool force_subpixel_positioning = !WebTestSupport::IsRunningWebTest() && - (sk_hint_style != SkFontHinting::kFull || - should_use_subpixel_positioning); + sk_hint_style != SkFontHinting::kFull; font->setSubpixel(force_subpixel_positioning || use_subpixel_positioning);
diff --git a/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc b/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc index 02b82ab..8d8a827 100644 --- a/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc +++ b/third_party/blink/renderer/platform/fonts/win/font_platform_data_win.cc
@@ -39,7 +39,7 @@ namespace blink { -SkFont FontPlatformData::CreateSkFont(bool, const FontDescription*) const { +SkFont FontPlatformData::CreateSkFont(const FontDescription*) const { SkFont font; font.setSize(SkFloatToScalar(text_size_)); font.setTypeface(typeface_);
diff --git a/third_party/blink/renderer/platform/graphics/color.cc b/third_party/blink/renderer/platform/graphics/color.cc index 0fc68fa..c587452 100644 --- a/third_party/blink/renderer/platform/graphics/color.cc +++ b/third_party/blink/renderer/platform/graphics/color.cc
@@ -143,7 +143,6 @@ float AngleToUnitCircleDegrees(float angle) { return fmod(fmod(angle, 360.f) + 360.f, 360.f); } - } // namespace // The color parameters will use 16 bytes (for 4 floats). Ensure that the @@ -285,6 +284,62 @@ return AngleToUnitCircleDegrees(blink::Blend(value1, value2, percentage)); } +namespace {} // namespace + +void Color::CarryForwardAnalogousMissingComponents( + Color color, + Color::ColorSpace prev_color_space) { + auto HasRGBOrXYZComponents = [](Color::ColorSpace color_space) { + return color_space == Color::ColorSpace::kSRGB || + color_space == Color::ColorSpace::kSRGBLinear || + color_space == Color::ColorSpace::kDisplayP3 || + color_space == Color::ColorSpace::kA98RGB || + color_space == Color::ColorSpace::kProPhotoRGB || + color_space == Color::ColorSpace::kRec2020 || + color_space == Color::ColorSpace::kXYZD50 || + color_space == Color::ColorSpace::kXYZD65 || + color_space == Color::ColorSpace::kRGBLegacy; + }; + + auto IsLightnessFirstComponent = [](Color::ColorSpace color_space) { + return color_space == Color::ColorSpace::kLab || + color_space == Color::ColorSpace::kOklab || + color_space == Color::ColorSpace::kLch || + color_space == Color::ColorSpace::kOklch; + }; + + const auto cur_color_space = color.GetColorSpace(); + if (cur_color_space == prev_color_space) { + return; + } + if (HasRGBOrXYZComponents(cur_color_space) && + HasRGBOrXYZComponents(prev_color_space)) { + return; + } + if (IsLightnessFirstComponent(cur_color_space) && + IsLightnessFirstComponent(prev_color_space)) { + color.param1_is_none_ = false; + color.param2_is_none_ = false; + return; + } + if (IsLightnessFirstComponent(prev_color_space) && + cur_color_space == ColorSpace::kHSL) { + color.param2_is_none_ = color.param0_is_none_; + color.param0_is_none_ = false; + if (prev_color_space != ColorSpace::kLch && + prev_color_space != ColorSpace::kOklch) { + DCHECK(prev_color_space == ColorSpace::kLab || + prev_color_space == ColorSpace::kOklab); + color.param1_is_none_ = false; + } + return; + } + // There are no analogous missing components. + color.param0_is_none_ = false; + color.param1_is_none_ = false; + color.param2_is_none_ = false; +} + // static Color::ColorSpace Color::ColorInterpolationSpaceToColorSpace( Color::ColorInterpolationSpace color_interpolation_space) { @@ -324,9 +379,22 @@ // hwb colorspaces. DCHECK(percentage >= 0.0f && percentage <= 1.0f); + const auto color1_prev_color_space = color1.GetColorSpace(); color1.ConvertToColorInterpolationSpace(interpolation_space); + const auto color2_prev_color_space = color2.GetColorSpace(); color2.ConvertToColorInterpolationSpace(interpolation_space); + CarryForwardAnalogousMissingComponents(color1, color1_prev_color_space); + CarryForwardAnalogousMissingComponents(color2, color2_prev_color_space); + + if (color1.alpha_is_none_ && !color2.alpha_is_none_) { + color1.alpha_ = color2.alpha_; + color1.alpha_is_none_ = false; + } else if (color2.alpha_is_none_ && !color1.alpha_is_none_) { + color2.alpha_ = color1.alpha_; + color2.alpha_is_none_ = false; + } + absl::optional<float> alpha1 = color1.PremultiplyColor(); absl::optional<float> alpha2 = color2.PremultiplyColor(); @@ -378,10 +446,12 @@ hue_method.value()) : blink::Blend(color1.param2_, color2.param2_, percentage); + if (color1.alpha_is_none_ || color2.alpha_is_none_) { + DCHECK_EQ(color1.alpha_is_none_, color2.alpha_is_none_); + } absl::optional<float> alpha = (color1.alpha_is_none_ && color2.alpha_is_none_) - ? HandleNoneInterpolation(alpha1.value(), color1.alpha_is_none_, - alpha2.value(), color2.alpha_is_none_) + ? absl::optional<float>(absl::nullopt) : blink::Blend(alpha1.value(), alpha2.value(), percentage); Color result;
diff --git a/third_party/blink/renderer/platform/graphics/color.h b/third_party/blink/renderer/platform/graphics/color.h index 54b88455c..8272ff0b 100644 --- a/third_party/blink/renderer/platform/graphics/color.h +++ b/third_party/blink/renderer/platform/graphics/color.h
@@ -111,6 +111,24 @@ color_space == ColorSpace::kXYZD65; } + static bool HasRGBOrXYZComponents(ColorSpace color_space) { + return color_space == ColorSpace::kSRGB || + color_space == ColorSpace::kSRGBLinear || + color_space == ColorSpace::kDisplayP3 || + color_space == ColorSpace::kA98RGB || + color_space == ColorSpace::kProPhotoRGB || + color_space == ColorSpace::kRec2020 || + color_space == ColorSpace::kXYZD50 || + color_space == ColorSpace::kXYZD65 || + color_space == ColorSpace::kRGBLegacy; + } + + static bool IsLightnessFirstComponent(ColorSpace color_space) { + return color_space == ColorSpace::kLab || + color_space == ColorSpace::kOklab || + color_space == ColorSpace::kLch || color_space == ColorSpace::kOklch; + } + // The default constructor creates a transparent color. constexpr Color() : param0_is_none_(0), @@ -378,6 +396,13 @@ float percentage, HueInterpolationMethod hue_method); + // According the Spec https://www.w3.org/TR/css-color-4/#interpolation-missing + // we have to do a special treatment of when to carry forward the 'noneness' + // of a component, given if it's an 'analog component'. + static void CarryForwardAnalogousMissingComponents( + Color color, + ColorSpace prev_color_space); + ColorSpace color_space_ = ColorSpace::kRGBLegacy; // Whether or not color parameters were specified as none (this only affects
diff --git a/third_party/blink/renderer/platform/graphics/color_test.cc b/third_party/blink/renderer/platform/graphics/color_test.cc index be92a71..59c01cf 100644 --- a/third_party/blink/renderer/platform/graphics/color_test.cc +++ b/third_party/blink/renderer/platform/graphics/color_test.cc
@@ -182,24 +182,43 @@ // Tests extracted from the CSS Color 4 spec. // https://csswg.sesse.net/css-color-4/#interpolation-alpha ColorsTest colors_test[] = { - {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.24f, 0.12f, 0.98f, - 0.4f), + {Color::FromColorSpace(Color::ColorSpace::kSRGB, absl::nullopt, 0.12f, + 0.98f, 1.0f), Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.26f, 0.64f, - 0.6f), + 1.0f), Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f, - Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.468f, 0.204f, - 0.776f, 0.5f)}, + Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.19f, 0.81f, + 1.0f)}, + {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.5f, absl::nullopt, + 1.0f, 1.0f), + Color::FromColorSpace(Color::ColorSpace::kSRGB, 1.0f, 0.5f, 0.0f, 1.0f), + Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f, + Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.75f, 0.5f, 0.5f, + 1.0f)}, + {Color::FromColorSpace(Color::ColorSpace::kSRGB, .5f, 0.0f, 0.0f, + absl::nullopt), + Color::FromColorSpace(Color::ColorSpace::kSRGB, 1.f, 0.5f, 1.0f, 1.0f), + Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f, + Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.75f, 0.25f, 0.5f, + 1.0f)}, + {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.24f, 0.12f, 0.98f, + 0.4f), + Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.62f, 0.26f, 0.64f, + 0.6f), + Color::ColorInterpolationSpace::kSRGB, absl::nullopt, 0.5f, + Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.468f, 0.204f, 0.776f, + 0.5f)}, {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.76f, 0.62f, 0.03f, - 0.4f), - Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, - 0.72f, 0.6f), + 0.4f), + Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, 0.72f, + 0.6f), Color::ColorInterpolationSpace::kLab, absl::nullopt, 0.5f, Color::FromColorSpace(Color::ColorSpace::kLab, 58.873f, 51.552f, 7.108f, 0.5f)}, {Color::FromColorSpace(Color::ColorSpace::kSRGB, 0.76f, 0.62f, 0.03f, - 0.4f), - Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, - 0.72f, 0.6f), + 0.4f), + Color::FromColorSpace(Color::ColorSpace::kDisplayP3, 0.84f, 0.19f, 0.72f, + 0.6f), Color::ColorInterpolationSpace::kLch, Color::HueInterpolationMethod::kShorter, 0.5f, // There is an issue with the spec where the hue is un-premultiplied even @@ -211,10 +230,114 @@ Color result = Color::InterpolateColors( color_test.space, color_test.hue_method, color_test.color1, color_test.color2, color_test.percentage); - EXPECT_NEAR(result.param0_, color_test.expected.param0_, 0.01f); - EXPECT_NEAR(result.param1_, color_test.expected.param1_, 0.01f); - EXPECT_NEAR(result.param2_, color_test.expected.param2_, 0.01f); - EXPECT_NEAR(result.alpha_, color_test.expected.alpha_, 0.01f); + EXPECT_NEAR(result.param0_, color_test.expected.param0_, 0.01f) + << "Mixing \n" + << color_test.color1.param0_is_none_ << ' ' << color_test.color1.param0_ + << " " << color_test.color1.param1_is_none_ << ' ' + << color_test.color1.param1_ << " " << color_test.color1.param2_is_none_ + << ' ' << color_test.color1.param2_ << " " + << color_test.color1.alpha_is_none_ << ' ' << color_test.color1.alpha_ + << " and \n" + << color_test.color2.param0_is_none_ << ' ' << color_test.color2.param0_ + << " " << color_test.color2.param1_is_none_ << ' ' + << color_test.color2.param1_ << " " << color_test.color2.param2_is_none_ + << ' ' << color_test.color2.param2_ << " " + << color_test.color2.alpha_is_none_ << ' ' << color_test.color2.alpha_ + << " produced\n" + << result.param0_is_none_ << ' ' << result.param0_ << " " + << result.param1_is_none_ << ' ' << result.param1_ << " " + << result.param2_is_none_ << ' ' << result.param2_ << " " + << result.alpha_is_none_ << ' ' << result.alpha_ + << " and it was expecting \n" + << color_test.expected.param0_is_none_ << ' ' + << color_test.expected.param0_ << " " + << color_test.expected.param1_is_none_ << ' ' + << color_test.expected.param1_ << " " + << color_test.expected.param2_is_none_ << ' ' + << color_test.expected.param2_ << " " + << color_test.expected.alpha_is_none_ << ' ' + << color_test.expected.alpha_; + EXPECT_NEAR(result.param1_, color_test.expected.param1_, 0.01f) + << "Mixing \n" + << color_test.color1.param0_is_none_ << ' ' << color_test.color1.param0_ + << " " << color_test.color1.param1_is_none_ << ' ' + << color_test.color1.param1_ << " " << color_test.color1.param2_is_none_ + << ' ' << color_test.color1.param2_ << " " + << color_test.color1.alpha_is_none_ << ' ' << color_test.color1.alpha_ + << " \n" + << color_test.color2.param0_is_none_ << ' ' << color_test.color2.param0_ + << " " << color_test.color2.param1_is_none_ << ' ' + << color_test.color2.param1_ << " " << color_test.color2.param2_is_none_ + << ' ' << color_test.color2.param2_ << " " + << color_test.color2.alpha_is_none_ << ' ' << color_test.color2.alpha_ + << " produced \n" + << result.param0_is_none_ << ' ' << result.param0_ << " " + << result.param1_is_none_ << ' ' << result.param1_ << " " + << result.param2_is_none_ << ' ' << result.param2_ << " " + << result.alpha_is_none_ << ' ' << result.alpha_ + << " and it was expecting \n" + << color_test.expected.param0_is_none_ << ' ' + << color_test.expected.param0_ << " " + << color_test.expected.param1_is_none_ << ' ' + << color_test.expected.param1_ << " " + << color_test.expected.param2_is_none_ << ' ' + << color_test.expected.param2_ << " " + << color_test.expected.alpha_is_none_ << ' ' + << color_test.expected.alpha_; + EXPECT_NEAR(result.param2_, color_test.expected.param2_, 0.01f) + << "Mixing \n" + << color_test.color1.param0_is_none_ << ' ' << color_test.color1.param0_ + << " " << color_test.color1.param1_is_none_ << ' ' + << color_test.color1.param1_ << " " << color_test.color1.param2_is_none_ + << ' ' << color_test.color1.param2_ << " " + << color_test.color1.alpha_is_none_ << ' ' << color_test.color1.alpha_ + << " \n" + << color_test.color2.param0_is_none_ << ' ' << color_test.color2.param0_ + << " " << color_test.color2.param1_is_none_ << ' ' + << color_test.color2.param1_ << " " << color_test.color2.param2_is_none_ + << ' ' << color_test.color2.param2_ << " " + << color_test.color2.alpha_is_none_ << ' ' << color_test.color2.alpha_ + << " produced \n" + << result.param0_is_none_ << ' ' << result.param0_ << " " + << result.param1_is_none_ << ' ' << result.param1_ << " " + << result.param2_is_none_ << ' ' << result.param2_ << " " + << result.alpha_is_none_ << ' ' << result.alpha_ + << " and it was expecting \n" + << color_test.expected.param0_is_none_ << ' ' + << color_test.expected.param0_ << " " + << color_test.expected.param1_is_none_ << ' ' + << color_test.expected.param1_ << " " + << color_test.expected.param2_is_none_ << ' ' + << color_test.expected.param2_ << " " + << color_test.expected.alpha_is_none_ << ' ' + << color_test.expected.alpha_; + EXPECT_NEAR(result.alpha_, color_test.expected.alpha_, 0.01f) + << "Mixing \n" + << color_test.color1.param0_is_none_ << ' ' << color_test.color1.param0_ + << " " << color_test.color1.param1_is_none_ << ' ' + << color_test.color1.param1_ << " " << color_test.color1.param2_is_none_ + << ' ' << color_test.color1.param2_ << " " + << color_test.color1.alpha_is_none_ << ' ' << color_test.color1.alpha_ + << " \n" + << color_test.color2.param0_is_none_ << ' ' << color_test.color2.param0_ + << " " << color_test.color2.param1_is_none_ << ' ' + << color_test.color2.param1_ << " " << color_test.color2.param2_is_none_ + << ' ' << color_test.color2.param2_ << " " + << color_test.color2.alpha_is_none_ << ' ' << color_test.color2.alpha_ + << " produced \n" + << result.param0_is_none_ << ' ' << result.param0_ << " " + << result.param1_is_none_ << ' ' << result.param1_ << " " + << result.param2_is_none_ << ' ' << result.param2_ << " " + << result.alpha_is_none_ << ' ' << result.alpha_ + << " and it was expecting \n" + << color_test.expected.param0_is_none_ << ' ' + << color_test.expected.param0_ << " " + << color_test.expected.param1_is_none_ << ' ' + << color_test.expected.param1_ << " " + << color_test.expected.param2_is_none_ << ' ' + << color_test.expected.param2_ << " " + << color_test.expected.alpha_is_none_ << ' ' + << color_test.expected.alpha_; } }
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 4b454464..ab7d071 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -159,7 +159,6 @@ void GraphicsContext::CopyConfigFrom(GraphicsContext& other) { SetPrintingMetafile(other.printing_metafile_); SetPaintPreviewTracker(other.paint_preview_tracker_); - SetDeviceScaleFactor(other.device_scale_factor_); SetPrinting(other.printing_); } @@ -601,8 +600,7 @@ dark_mode_flags); return; } - font.DrawText(canvas_, text_info, point, device_scale_factor_, node_id, - dark_mode_flags, + font.DrawText(canvas_, text_info, point, node_id, dark_mode_flags, printing_ ? Font::DrawType::kGlyphsAndClusters : Font::DrawType::kGlyphsOnly); } @@ -674,8 +672,7 @@ const AutoDarkMode& auto_dark_mode) { DrawTextPasses(auto_dark_mode, [&font, &text_info, &mark, &point, this](const cc::PaintFlags& flags) { - font.DrawEmphasisMarks(canvas_, text_info, mark, point, - device_scale_factor_, flags); + font.DrawEmphasisMarks(canvas_, text_info, mark, point, flags); }); } @@ -706,8 +703,7 @@ auto_dark_mode, [&font, &run_info, &point, custom_font_not_ready_action, this](const cc::PaintFlags& flags) { if (font.DrawBidiText(canvas_, run_info, point, - custom_font_not_ready_action, - device_scale_factor_, flags, + custom_font_not_ready_action, flags, printing_ ? Font::DrawType::kGlyphsAndClusters : Font::DrawType::kGlyphsOnly)) { paint_controller_.SetTextPainted();
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.h b/third_party/blink/renderer/platform/graphics/graphics_context.h index 04b20fbd..b43cb06 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.h +++ b/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -172,8 +172,8 @@ GraphicsContext& operator=(const GraphicsContext&) = delete; ~GraphicsContext(); - // Copy configs such as printing, dark mode, device scale factor etc. from - // another GraphicsContext. + // Copy configs such as printing, dark mode, etc. from another + // GraphicsContext. void CopyConfigFrom(GraphicsContext&); void SetPrintingMetafile(printing::MetafileSkia* metafile) { @@ -260,11 +260,6 @@ ImageInterpolationQuality())); } - // Specify the device scale factor which may change the way document markers - // and fonts are rendered. - void SetDeviceScaleFactor(float factor) { device_scale_factor_ = factor; } - float DeviceScaleFactor() const { return device_scale_factor_; } - // Set to true if context is for printing. Bitmaps won't be resampled when // printing to keep the best possible quality. When printing text will be // provided along with glyphs. @@ -637,8 +632,6 @@ bool disable_destruction_checks_ = false; #endif - float device_scale_factor_ = 1.0f; - std::unique_ptr<DarkModeFilter> dark_mode_filter_; bool printing_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/placeholder_image.cc b/third_party/blink/renderer/platform/graphics/placeholder_image.cc index 65ba8f7..3afef32 100644 --- a/third_party/blink/renderer/platform/graphics/placeholder_image.cc +++ b/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -350,7 +350,7 @@ canvas, TextRunPaintInfo(TextRun(text_)), gfx::PointF(text_x, feature_y + icon_and_text_scale_factor_ * (kTextPaddingY + kFontSize)), - Font::kUseFallbackIfFontNotReady, 1.0f, flags); + Font::kUseFallbackIfFontNotReady, flags); } void PlaceholderImage::DrawPattern(GraphicsContext& context,
diff --git a/third_party/blink/renderer/platform/heap/member.h b/third_party/blink/renderer/platform/heap/member.h index 9889627..e2bda61 100644 --- a/third_party/blink/renderer/platform/heap/member.h +++ b/third_party/blink/renderer/platform/heap/member.h
@@ -90,7 +90,11 @@ // Member. Prefer compressing raw pointers instead of decompressing Members, // assuming the former is cheaper. static unsigned GetHash(const T* key) { - cppgc::internal::MemberBase::RawStorage st(key); +#if defined(CPPGC_POINTER_COMPRESSION) + cppgc::internal::CompressedPointer st(key); +#else + cppgc::internal::RawPointer st(key); +#endif return WTF::GetHash(st.GetAsInteger()); } template <typename Member,
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc index 194c187a..51613a0 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc +++ b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/renderer/platform/loader/attribution_header_constants.h" #include "third_party/blink/renderer/platform/network/http_names.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -13,6 +14,34 @@ namespace blink { +ScriptFetchOptions::ScriptFetchOptions() + : parser_state_(ParserDisposition::kNotParserInserted), + credentials_mode_(network::mojom::CredentialsMode::kSameOrigin), + referrer_policy_(network::mojom::ReferrerPolicy::kDefault), + fetch_priority_hint_(mojom::blink::FetchPriorityHint::kAuto) {} + +ScriptFetchOptions::ScriptFetchOptions( + const String& nonce, + const IntegrityMetadataSet& integrity_metadata, + const String& integrity_attribute, + ParserDisposition parser_state, + network::mojom::CredentialsMode credentials_mode, + network::mojom::ReferrerPolicy referrer_policy, + mojom::blink::FetchPriorityHint fetch_priority_hint, + RenderBlockingBehavior render_blocking_behavior, + RejectCoepUnsafeNone reject_coep_unsafe_none) + : nonce_(nonce), + integrity_metadata_(integrity_metadata), + integrity_attribute_(integrity_attribute), + parser_state_(parser_state), + credentials_mode_(credentials_mode), + referrer_policy_(referrer_policy), + fetch_priority_hint_(fetch_priority_hint), + render_blocking_behavior_(render_blocking_behavior), + reject_coep_unsafe_none_(reject_coep_unsafe_none) {} + +ScriptFetchOptions::~ScriptFetchOptions() = default; + // https://html.spec.whatwg.org/C/#fetch-a-classic-script FetchParameters ScriptFetchOptions::CreateFetchParameters( const KURL& url,
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h index 2394ce62..28f7298 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h +++ b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_SCRIPT_FETCH_OPTIONS_H_ #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h" #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" @@ -40,12 +40,7 @@ // cryptographic nonce is the empty string, integrity metadata is the empty // string, parser metadata is "not-parser-inserted", credentials mode is // "same-origin", and referrer policy is the empty string." [spec text] - ScriptFetchOptions() - : parser_state_(ParserDisposition::kNotParserInserted), - credentials_mode_(network::mojom::CredentialsMode::kSameOrigin), - referrer_policy_(network::mojom::ReferrerPolicy::kDefault), - fetch_priority_hint_(mojom::blink::FetchPriorityHint::kAuto) {} - + ScriptFetchOptions(); ScriptFetchOptions(const String& nonce, const IntegrityMetadataSet& integrity_metadata, const String& integrity_attribute, @@ -55,17 +50,8 @@ mojom::blink::FetchPriorityHint fetch_priority_hint, RenderBlockingBehavior render_blocking_behavior, RejectCoepUnsafeNone reject_coep_unsafe_none = - RejectCoepUnsafeNone(false)) - : nonce_(nonce), - integrity_metadata_(integrity_metadata), - integrity_attribute_(integrity_attribute), - parser_state_(parser_state), - credentials_mode_(credentials_mode), - referrer_policy_(referrer_policy), - fetch_priority_hint_(fetch_priority_hint), - render_blocking_behavior_(render_blocking_behavior), - reject_coep_unsafe_none_(reject_coep_unsafe_none) {} - ~ScriptFetchOptions() = default; + RejectCoepUnsafeNone(false)); + ~ScriptFetchOptions(); const String& Nonce() const { return nonce_; } const IntegrityMetadataSet& GetIntegrityMetadata() const {
diff --git a/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc b/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc index 3f7af0a2..d17a3b44 100644 --- a/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc +++ b/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc
@@ -15,6 +15,7 @@ #include "media/base/key_systems.h" #include "media/base/media_permission.h" #include "media/base/mime_util.h" +#include "media/cdm/clear_key_cdm_common.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/platform/web_content_settings_client.h" @@ -34,9 +35,8 @@ using EncryptionScheme = WebMediaKeySystemMediaCapability::EncryptionScheme; // Key system strings. Clear Key support is hardcoded in KeySystemConfigSelector -// so kClearKeyKeySystem is the real key system string. The rest key system -// strings are for testing purpose only. -const char kClearKeyKeySystem[] = "org.w3.clearkey"; +// so media::kClearKeyKeySystem is the real key system string. The rest key +// system strings are for testing purpose only. const char kSupportedKeySystem[] = "keysystem.test.supported"; const char kSupportedSubKeySystem[] = "keysystem.test.supported.sub"; const char kUnsupportedKeySystem[] = "keysystem.test.unsupported"; @@ -213,7 +213,7 @@ bool IsSupportedKeySystem(const std::string& key_system) const override { // Based on EME spec, Clear Key key system is always supported. - return key_system == kClearKeyKeySystem || + return key_system == media::kClearKeyKeySystem || key_system == kSupportedKeySystem || key_system == kSupportedSubKeySystem; } @@ -224,7 +224,7 @@ } bool CanUseAesDecryptor(const std::string& key_system) const override { - return key_system == kClearKeyKeySystem; + return key_system == media::kClearKeyKeySystem; } // TODO(sandersd): Move implementation into KeySystemConfigSelector? @@ -602,10 +602,10 @@ } TEST_F(KeySystemConfigSelectorTest, KeySystem_ClearKey) { - key_system_ = kClearKeyKeySystem; + key_system_ = media::kClearKeyKeySystem; configs_.push_back(UsableConfiguration()); SelectConfigReturnsConfig(); - DCHECK_EQ(cdm_config_.key_system, kClearKeyKeySystem); + DCHECK_EQ(cdm_config_.key_system, media::kClearKeyKeySystem); } TEST_F(KeySystemConfigSelectorTest, KeySystem_SubKeySystem) { @@ -621,7 +621,7 @@ media_permission_->is_encrypted_media_enabled = false; // Clear Key key system is always supported. - key_system_ = kClearKeyKeySystem; + key_system_ = media::kClearKeyKeySystem; configs_.push_back(UsableConfiguration()); SelectConfigReturnsConfig(); } @@ -1046,7 +1046,7 @@ TEST_F(KeySystemConfigSelectorTest, VideoCapabilities_UnsupportedByAesDecryptorCodec_ClearKey) { - key_system_ = kClearKeyKeySystem; + key_system_ = media::kClearKeyKeySystem; std::vector<WebMediaKeySystemMediaCapability> video_capabilities(1); video_capabilities[0].content_type = "a";
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ab119b4..50c2727d 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -919,6 +919,12 @@ status: "experimental", }, { + // Support for CSS top-layer property for being able to transition + // See: https://github.com/w3c/csswg-drafts/issues/8189 + name: "CSSTopLayerForTransitions", + status: "experimental", + }, + { // Support for tree-scoped [1] timeline names (e.g. produced by // scroll-timeline). // @@ -1115,6 +1121,8 @@ }, { name: "DocumentPictureInPictureAPI", + origin_trial_feature_name: "DocumentPictureInPictureAPI", + origin_trial_os: ["win", "mac", "linux", "chromeos"], status: { "Android": "", "ChromeOS_Lacros": "", @@ -1654,7 +1662,7 @@ // crbug.com/1353190 name: "LayoutNGNoCopyBack", depends_on: ["LayoutMediaNGContainer", "LayoutNGReplacedNoBoxSetters"], - status: "stable", + status: "test", base_feature: "LayoutNGNoCopyBack", }, { @@ -2431,12 +2439,6 @@ base_feature: "SanitizerAPI", }, { - name: "SanitizerAPIv0", - status: "stable", - implied_by: ["SanitizerAPI"], - base_feature: "SanitizerAPIv0", - }, - { // https://wicg.github.io/webcomponents/proposals/Scoped-Custom-Element-Registries name: "ScopedCustomElementRegistry", status: "test", @@ -2728,7 +2730,7 @@ }, { name: "StreamingDeclarativeShadowDOM", - status: "experimental", + status: "stable", base_feature: "StreamingDeclarativeShadowDOM", }, {
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key.cc b/third_party/blink/renderer/platform/storage/blink_storage_key.cc index 610fb61..f9b506c 100644 --- a/third_party/blink/renderer/platform/storage/blink_storage_key.cc +++ b/third_party/blink/renderer/platform/storage/blink_storage_key.cc
@@ -48,20 +48,23 @@ ancestor_chain_bit_if_third_party_enabled_(ancestor_chain_bit) { #if DCHECK_IS_ON() DCHECK(origin_); - // If we're setting a `nonce`, the `top_level_site` must be the same as - // the `origin` and the `ancestor_chain_bit` must be kSameSite. We don't - // serialize those pieces of information so have to check to prevent - // mistaken reliance on what is supposed to be an invariant. if (nonce) { + // If we're setting a `nonce`, the `top_level_site` must be the same as + // the `origin` and the `ancestor_chain_bit` must be kSameSite. We don't + // serialize those pieces of information so have to check to prevent + // mistaken reliance on what is supposed to be an invariant. DCHECK(!nonce->is_empty()); DCHECK(top_level_site == BlinkSchemefulSite(origin)); DCHECK_EQ(ancestor_chain_bit, mojom::blink::AncestorChainBit::kSameSite); - } - // If we're setting an opaque `top_level_site`, the `ancestor_chain_bit` must - // be kSameSite. We don't serialize that information so have to check to - // prevent mistaken reliance on what is supposed to be an invariant. - if (top_level_site.IsOpaque()) { + } else if (top_level_site.IsOpaque()) { + // If we're setting an opaque `top_level_site`, the `ancestor_chain_bit` + // must be kSameSite. We don't serialize that information so have to check + // to prevent mistaken reliance on what is supposed to be an invariant. DCHECK_EQ(ancestor_chain_bit, mojom::blink::AncestorChainBit::kSameSite); + } else if (top_level_site != BlinkSchemefulSite(origin)) { + // If `top_level_site` doesn't match `origin` then we must be making a + // third-party StorageKey and `ancestor_chain_bit` must be kCrossSite. + DCHECK_EQ(ancestor_chain_bit, mojom::blink::AncestorChainBit::kCrossSite); } #endif }
diff --git a/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc b/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc index b9d82f9..706217d 100644 --- a/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc +++ b/third_party/blink/renderer/platform/storage/blink_storage_key_test.cc
@@ -111,7 +111,7 @@ BlinkStorageKey::CreateWithNonce(origin1, nonce), BlinkStorageKey::CreateWithNonce(origin2, nonce), BlinkStorageKey(origin1, BlinkSchemefulSite(origin2), nullptr, - mojom::blink::AncestorChainBit::kSameSite), + mojom::blink::AncestorChainBit::kCrossSite), BlinkStorageKey(origin1, BlinkSchemefulSite(), nullptr, mojom::blink::AncestorChainBit::kSameSite), BlinkStorageKey(origin2, BlinkSchemefulSite(), nullptr, @@ -291,7 +291,7 @@ } } -TEST(StorageKeyTest, OpaqueTopLevelSiteRequiresSameSite) { +TEST(BlinkStorageKeyTest, OpaqueTopLevelSiteRequiresSameSite) { scoped_refptr<const SecurityOrigin> origin = SecurityOrigin::CreateFromString("https://foo.com"); const BlinkSchemefulSite site(origin); @@ -319,4 +319,37 @@ } } +TEST(BlinkStorageKeyTest, OriginAndSiteMismatchRequiresCrossSite) { + scoped_refptr<const SecurityOrigin> origin = + SecurityOrigin::CreateFromString("https://foo.com"); + scoped_refptr<const SecurityOrigin> opaque_origin = + SecurityOrigin::CreateUniqueOpaque(); + const BlinkSchemefulSite site(origin); + const BlinkSchemefulSite other_site( + SecurityOrigin::CreateFromString("https://notfoo.com")); + + for (const bool toggle : {false, true}) { + base::test::ScopedFeatureList scope_feature_list; + scope_feature_list.InitWithFeatureState( + net::features::kThirdPartyStoragePartitioning, toggle); + + // A matching origin and site can be SameSite or CrossSite. + std::ignore = BlinkStorageKey(origin, site, nullptr, + mojom::blink::AncestorChainBit::kSameSite); + std::ignore = BlinkStorageKey(origin, site, nullptr, + mojom::blink::AncestorChainBit::kCrossSite); + + // A mismatched origin and site cannot be SameSite. + EXPECT_DCHECK_DEATH( + BlinkStorageKey(origin, other_site, nullptr, + mojom::blink::AncestorChainBit::kSameSite)); + EXPECT_DCHECK_DEATH( + BlinkStorageKey(opaque_origin, other_site, nullptr, + mojom::blink::AncestorChainBit::kSameSite)); + + // A mismatched origin and site must be CrossSite. + std::ignore = BlinkStorageKey(origin, other_site, nullptr, + mojom::blink::AncestorChainBit::kCrossSite); + } +} } // namespace blink
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc index 88e685e..54380028 100644 --- a/third_party/blink/renderer/platform/widget/widget_base.cc +++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -80,9 +80,6 @@ static const int kInvalidNextPreviousFlagsValue = -1; -static const char kOOPIF[] = "OOPIF"; -static const char kRenderer[] = "Renderer"; - void OnDidPresentForceDrawFrame( mojom::blink::Widget::ForceRedrawCallback callback, const gfx::PresentationFeedback& feedback) { @@ -584,13 +581,6 @@ if (url.IsEmpty()) url = KURL("chrome://gpu/WidgetBase::RequestNewLayerTreeFrameSink"); - // TODO(danakj): This may not be accurate, depending on the intent. A child - // local root could be in the same process as the view, so if the client is - // meant to designate the process type, it seems kRenderer would be the - // correct choice. If client is meant to designate the widget type, then - // kOOPIF would denote that it is not for the main frame. However, kRenderer - // would also be used for other widgets such as popups. - const char* client_name = is_embedded_ ? kOOPIF : kRenderer; const bool for_web_tests = WebTestMode(); // Misconfigured bots (eg. crbug.com/780757) could run web tests on a // machine where gpu compositing doesn't work. Don't crash in that case. @@ -637,8 +627,6 @@ if (LayerTreeHost()->GetSettings().disable_frame_rate_limit) params->synthetic_begin_frame_source = CreateSyntheticBeginFrameSource(); - params->client_name = client_name; - mojo::PendingReceiver<viz::mojom::blink::CompositorFrameSink> compositor_frame_sink_receiver = CrossVariantMojoReceiver< viz::mojom::blink::CompositorFrameSinkInterfaceBase>(
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index 5fae71c6..99b403a 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -36,6 +36,8 @@ } component("wtf") { + output_name = "blink_platform_wtf" + sources = [ "allocator/allocator.h", "allocator/partition_allocator.cc",
diff --git a/third_party/blink/renderer/platform/wtf/hash_set.h b/third_party/blink/renderer/platform/wtf/hash_set.h index ad6a0bd..fb91f92e 100644 --- a/third_party/blink/renderer/platform/wtf/hash_set.h +++ b/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -223,6 +223,11 @@ } template <typename T, typename U, typename V> +inline bool operator!=(const HashSet<T, U, V>& a, const HashSet<T, U, V>& b) { + return !(a == b); +} + +template <typename T, typename U, typename V> inline unsigned HashSet<T, U, V>::size() const { return impl_.size(); }
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h index c6b36c11..b214477 100644 --- a/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -807,16 +807,13 @@ static ValueType* AllocateTable(unsigned size); static void DeleteAllBucketsAndDeallocate(ValueType* table, unsigned size); - typedef std::pair<ValueType*, bool> LookupType; - typedef std::pair<LookupType, unsigned> FullLookupType; - - LookupType LookupForWriting(const Key& key) { - return LookupForWriting<IdentityTranslatorType>(key); - } + struct LookupResult { + ValueType* entry; + bool found; + unsigned hash; + }; template <typename HashTranslator, typename T> - FullLookupType FullLookupForWriting(const T&); - template <typename HashTranslator, typename T> - LookupType LookupForWriting(const T&); + LookupResult LookupForWriting(const T&); void erase(const ValueType*); @@ -860,12 +857,6 @@ } } - FullLookupType MakeLookupResult(ValueType* position, - bool found, - unsigned hash) { - return FullLookupType(LookupType(position, found), hash); - } - iterator MakeIterator(ValueType* pos) { return iterator(pos, table_, table_ + table_size_, this); } @@ -1085,7 +1076,7 @@ typename Allocator> template <typename HashTranslator, typename T> inline typename HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>:: - LookupType + LookupResult HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>:: LookupForWriting(const T& key) { DCHECK(!AccessForbidden()); @@ -1100,57 +1091,8 @@ UPDATE_ACCESS_COUNTS(); - ValueType* deleted_entry = nullptr; - - while (true) { - ValueType* entry = table + i; - - if (IsEmptyBucket(*entry)) - return LookupType(deleted_entry ? deleted_entry : entry, false); - - if (KeyTraits::kSafeToCompareToEmptyOrDeleted) { - if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { - return LookupType(entry, true); - } - - if (IsDeletedBucket(*entry)) - deleted_entry = entry; - } else { - if (IsDeletedBucket(*entry)) { - deleted_entry = entry; - } else if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { - return LookupType(entry, true); - } - } - - ++probe_count; - UPDATE_PROBE_COUNTS(); - i = (i + probe_count) & size_mask; - } -} - -template <typename Key, - typename Value, - typename Extractor, - typename Traits, - typename KeyTraits, - typename Allocator> -template <typename HashTranslator, typename T> -inline typename HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>:: - FullLookupType - HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>:: - FullLookupForWriting(const T& key) { - DCHECK(!AccessForbidden()); - DCHECK(table_); - RegisterModification(); - - ValueType* table = table_; - size_t size_mask = TableSizeMask(); - unsigned h = HashTranslator::GetHash(key); - size_t i = h & size_mask; - size_t probe_count = 0; - - UPDATE_ACCESS_COUNTS(); + bool can_reuse_deleted_entry = + Allocator::template CanReuseHashTableDeletedBucket<Traits>(); ValueType* deleted_entry = nullptr; @@ -1158,20 +1100,23 @@ ValueType* entry = table + i; if (IsEmptyBucket(*entry)) - return MakeLookupResult(deleted_entry ? deleted_entry : entry, false, h); + return LookupResult{deleted_entry ? deleted_entry : entry, false, h}; if (KeyTraits::kSafeToCompareToEmptyOrDeleted) { if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { - return MakeLookupResult(entry, true, h); + return LookupResult{entry, true, h}; } - if (IsDeletedBucket(*entry)) + if (can_reuse_deleted_entry && IsDeletedBucket(*entry)) { deleted_entry = entry; + } } else { if (IsDeletedBucket(*entry)) { - deleted_entry = entry; + if (can_reuse_deleted_entry) { + deleted_entry = entry; + } } else if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { - return MakeLookupResult(entry, true, h); + return LookupResult{entry, true, h}; } } ++probe_count; @@ -1194,13 +1139,7 @@ DCHECK(IsHashTraitsEmptyValue<Traits>(bucket)); } - static void Reinitialize(Value& bucket) { - // Reinitialize is used when recycling a deleted bucket. For buckets for - // which empty value is non-zero, this is forbidden during marking. Thus if - // we get here, marking is not active and we can reuse Initialize. - DCHECK(Allocator::template CanReuseHashTableDeletedBucket<Traits>()); - Initialize(bucket); - } + static void Reinitialize(Value& bucket) { Initialize(bucket); } template <typename HashTable> static Value* AllocateTable(unsigned size, size_t alloc_size) { @@ -1287,6 +1226,9 @@ typename Allocator> inline void HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>:: ReinitializeBucket(ValueType& bucket) { + // Reinitialize is used when recycling a deleted bucket. + DCHECK(IsDeletedBucket(bucket)); + DCHECK(Allocator::template CanReuseHashTableDeletedBucket<Traits>()); HashTableBucketInitializer<Traits, Allocator, Value>::Reinitialize(bucket); } @@ -1333,11 +1275,14 @@ return AddResult(this, entry, false); } - if (IsDeletedBucket(*entry) && can_reuse_deleted_entry) + if (can_reuse_deleted_entry && IsDeletedBucket(*entry)) { deleted_entry = entry; + } } else { - if (IsDeletedBucket(*entry) && can_reuse_deleted_entry) { - deleted_entry = entry; + if (IsDeletedBucket(*entry)) { + if (can_reuse_deleted_entry) { + deleted_entry = entry; + } } else if (HashTranslator::Equal(Extractor::ExtractKey(*entry), key)) { return AddResult(this, entry, false); } @@ -1404,14 +1349,11 @@ if (!table_) Expand(); - FullLookupType lookup_result = FullLookupForWriting<HashTranslator>(key); - - ValueType* entry = lookup_result.first.first; - bool found = lookup_result.first.second; - unsigned h = lookup_result.second; - - if (found) + LookupResult lookup_result = LookupForWriting<HashTranslator>(key); + ValueType* entry = lookup_result.entry; + if (lookup_result.found) { return AddResult(this, entry, false); + } RegisterModification(); @@ -1421,7 +1363,7 @@ } HashTranslator::Translate(*entry, std::forward<T>(key), - std::forward<Extra>(extra), h); + std::forward<Extra>(extra), lookup_result.hash); DCHECK(!IsEmptyOrDeletedBucket(*entry)); // Translate constructs an element so we need to notify using the trait. Avoid // doing that in the translator so that they can be easily customized. @@ -1443,10 +1385,8 @@ Value* HashTable<Key, Value, Extractor, Traits, KeyTraits, Allocator>::Reinsert( ValueType&& entry) { DCHECK(table_); + DCHECK(!AccessForbidden()); RegisterModification(); - DCHECK(!LookupForWriting(Extractor::ExtractKey(entry)).second); - DCHECK(!IsDeletedBucket( - *(LookupForWriting(Extractor::ExtractKey(entry)).first))); #if DUMP_HASHTABLE_STATS HashTableStats::instance().numReinserts.fetch_add(1, std::memory_order_relaxed); @@ -1454,7 +1394,27 @@ #if DUMP_HASHTABLE_STATS_PER_TABLE stats_->numReinserts.fetch_add(1, std::memory_order_relaxed); #endif - Value* new_entry = LookupForWriting(Extractor::ExtractKey(entry)).first; + + ValueType* table = table_; + size_t size_mask = TableSizeMask(); + const auto& key = Extractor::ExtractKey(entry); + unsigned h = KeyTraits::GetHash(key); + size_t i = h & size_mask; + size_t probe_count = 0; + + UPDATE_ACCESS_COUNTS(); + + ValueType* new_entry = table + i; + while (!IsEmptyBucket(*new_entry)) { + DCHECK(!IsDeletedBucket(*new_entry)); + DCHECK(!KeyTraits::Equal(Extractor::ExtractKey(*new_entry), key)); + + ++probe_count; + UPDATE_PROBE_COUNTS(); + i = (i + probe_count) & size_mask; + new_entry = table + i; + } + Mover<ValueType, Allocator, Traits, Traits::template NeedsToForbidGCOnMove<>::value>::Move(std::move(entry), *new_entry);
diff --git a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py index b607ee2..d18bb6a1 100644 --- a/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py +++ b/third_party/blink/tools/blinkpy/common/checkout/baseline_optimizer.py
@@ -28,17 +28,22 @@ import copy import logging +from typing import Optional from blinkpy.common.memoized import memoized from blinkpy.web_tests.models.testharness_results import is_all_pass_testharness_result -from blinkpy.web_tests.models.test_expectations import TestExpectations +from blinkpy.web_tests.models.test_expectations import TestExpectationsCache from blinkpy.web_tests.models.typ_types import ResultType _log = logging.getLogger(__name__) class BaselineOptimizer(object): - def __init__(self, host, default_port, port_names): + def __init__(self, + host, + default_port, + port_names, + exp_cache: Optional[TestExpectationsCache] = None): self._filesystem = host.filesystem self._default_port = default_port self._host = host @@ -49,6 +54,7 @@ self._flag_specific_configs.update( host.builders.flag_specific_options_for_port_name(port_name)) + self._exp_cache = exp_cache or TestExpectationsCache() self._web_tests_dir = default_port.web_tests_dir() self._parent_of_tests = self._filesystem.dirname(self._web_tests_dir) self._web_tests_dir_name = self._filesystem.relpath( @@ -415,7 +421,7 @@ assert port_name in results_by_port_name # When the virtual test is skipped on a port, the baseline for the # non virtual test on the same port won't matter - full_expectations = TestExpectations(port) + full_expectations = self._exp_cache.load(port) if ResultType.Skip in full_expectations.get_expectations( test_name).results: continue
diff --git a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py index cc154c1..48b7ecdb 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py +++ b/third_party/blink/tools/blinkpy/tool/commands/copy_existing_baselines.py
@@ -6,7 +6,7 @@ from blinkpy.common.memoized import memoized from blinkpy.tool.commands.rebaseline import AbstractRebaseliningCommand -from blinkpy.web_tests.models.test_expectations import TestExpectations +from blinkpy.web_tests.models.test_expectations import TestExpectationsCache from blinkpy.web_tests.models.typ_types import ResultType _log = logging.getLogger(__name__) @@ -26,6 +26,7 @@ self.flag_specific_option, self.results_directory_option, ]) + self._exp_cache = TestExpectationsCache() def execute(self, options, args, tool): self._tool = tool @@ -85,7 +86,7 @@ self._tool.filesystem.remove(new_baseline) continue - full_expectations = TestExpectations(port) + full_expectations = self._exp_cache.load(port) if ResultType.Skip in full_expectations.get_expectations( test_name).results: self._log_skipped_test(port, test_name) @@ -123,7 +124,7 @@ port = self._tool.port_factory.get(port_name) if flag_specific: port.set_option_default('flag_specific', flag_specific) - full_expectations = TestExpectations(port) + full_expectations = self._exp_cache.load(port) if port.lookup_virtual_test_base(test_name): # Do nothing for virtual tests
diff --git a/third_party/blink/tools/blinkpy/tool/commands/optimize_baselines.py b/third_party/blink/tools/blinkpy/tool/commands/optimize_baselines.py index 81e9a5c..4159b02 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/optimize_baselines.py +++ b/third_party/blink/tools/blinkpy/tool/commands/optimize_baselines.py
@@ -7,6 +7,7 @@ from blinkpy.common.checkout.baseline_optimizer import BaselineOptimizer from blinkpy.tool.commands.rebaseline import AbstractRebaseliningCommand +from blinkpy.web_tests.models.test_expectations import TestExpectationsCache _log = logging.getLogger(__name__) @@ -31,6 +32,7 @@ self.port_name_option, self.all_option, ] + self.platform_options + self.wpt_options) + self._exp_cache = TestExpectationsCache() def _optimize_baseline(self, optimizer, test_name): for suffix in self._baseline_suffix_list: @@ -48,7 +50,7 @@ _log.error("No port names match '%s'", options.platform) return port = tool.port_factory.get(port_names[0], options) - optimizer = BaselineOptimizer(tool, port, port_names) + optimizer = BaselineOptimizer(tool, port, port_names, self._exp_cache) test_set = set(port.tests() if options.all_tests else port.tests(args)) virtual_tests_to_exclude = set([ test for test in test_set
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py index c5cb353..38836d09 100644 --- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py +++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -30,14 +30,14 @@ import copy import logging import re - from collections import defaultdict from collections import OrderedDict +from functools import reduce +from typing import Dict, Optional, Tuple from blinkpy.common.memoized import memoized from blinkpy.web_tests.models import typ_types from typ import expectations_parser -from functools import reduce ResultType = typ_types.ResultType @@ -612,3 +612,15 @@ def update_expectations(self): self._test_expectations.commit_changes() + + +class TestExpectationsCache: + def __init__(self): + self._cache: Dict[Tuple[str, Optional[str]], TestExpectations] = {} + + def load(self, port: 'Port') -> TestExpectations: + cache_key = port.port_name, port.get_option('flag_specific') + expectations = self._cache.get(cache_key) + if not expectations: + self._cache[cache_key] = expectations = TestExpectations(port) + return expectations
diff --git a/third_party/blink/tools/run_wpt_tests.py b/third_party/blink/tools/run_wpt_tests.py index b8d4aeb..e00cbf9 100755 --- a/third_party/blink/tools/run_wpt_tests.py +++ b/third_party/blink/tools/run_wpt_tests.py
@@ -18,7 +18,6 @@ from blinkpy.common.host import Host from blinkpy.common.path_finder import PathFinder from blinkpy.web_tests.port.android import ( - ANDROID_WEBLAYER, ANDROID_WEBVIEW, CHROME_ANDROID, ) @@ -752,10 +751,9 @@ # Aliases for backwards compatibility. '--chrome-apk', '--system-webview-shell', - '--weblayer-shell', type=os.path.abspath, help=('Path to the browser APK to install and run. ' - '(For WebView and WebLayer, this value is the shell. ' + '(For WebView, this value is the shell. ' 'Defaults to an on-device APK if not provided.)')) group.add_argument('--webview-provider', type=os.path.abspath, @@ -763,8 +761,6 @@ '(WebView only.)')) group.add_argument( '--additional-apk', - # Aliases for backwards compatibility. - '--weblayer-support', type=os.path.abspath, action='append', default=[], @@ -994,7 +990,7 @@ def get_browser_package_name(self): """Get the name of the package to run tests against. - For WebView and WebLayer, this package is the shell. + For WebView, this package is the shell. Returns: Optional[str]: The name of a package installed on the devices or @@ -1056,28 +1052,6 @@ yield -class WebLayer(ChromeAndroidBase): - name = ANDROID_WEBLAYER - aliases = ['weblayer'] - - @property - def wpt_args(self): - args = list(super().wpt_args) - args.append('--test-type=testharness') - return args - - def get_browser_package_name(self): - return (super().get_browser_package_name() - or 'org.chromium.weblayer.shell') - - def get_version_provider_package_name(self): - if self._options.additional_apk: - support_apk = self._options.additional_apk[0] - with contextlib.suppress(apk_helper.ApkHelperError): - return apk_helper.GetPackageName(support_apk) - return super().get_version_provider_package_name() - - class WebView(ChromeAndroidBase): name = ANDROID_WEBVIEW aliases = ['webview'] @@ -1166,7 +1140,7 @@ product_registry = {} product_classes = [Chrome, ContentShell, ChromeiOS] if _ANDROID_ENABLED: - product_classes.extend([ChromeAndroid, WebView, WebLayer]) + product_classes.extend([ChromeAndroid, WebView]) for product_cls in product_classes: names = [product_cls.name] + product_cls.aliases product_registry.update((name, product_cls) for name in names)
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 9e3bc13..7d5186d 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1454,7 +1454,6 @@ external/wpt/web-nfc/NDEFReader-make-read-only-document-hidden-manual.https.html [ Skip ] external/wpt/web-nfc/NDEFReader-write-document-hidden-manual.https.html [ Skip ] external/wpt/web-nfc/nfc-prompt-manual.https.html [ Skip ] -external/wpt/screen-wake-lock/wakelock-document-hidden-manual.https.html [ Skip ] external/wpt/web-share/share-cancel-manual.https.html [ Skip ] external/wpt/web-share/share-extra-argument-manual.https.html [ Skip ] external/wpt/web-share/share-extra-field-manual.https.html [ Skip ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 036c34f..5f2d6bab 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -52,7 +52,8 @@ crbug.com/24182 http/tests/misc/acid3.html [ Slow ] crbug.com/24182 [ Release ] http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm [ Slow ] crbug.com/24182 http/tests/misc/uncacheable-script-repeated.html [ Slow ] -crbug.com/24182 http/tests/navigation/slowmetaredirect-basic.html [ Slow ] +crbug.com/24182 [ Debug Linux ] http/tests/navigation/slowmetaredirect-basic.html [ Slow ] +crbug.com/24182 [ Release ] http/tests/navigation/slowmetaredirect-basic.html [ Slow ] crbug.com/24182 [ Debug Mac12 ] http/tests/navigation/slowtimerredirect-basic.html [ Slow ] crbug.com/24182 [ Release ] http/tests/navigation/slowtimerredirect-basic.html [ Slow ] crbug.com/24182 http/tests/storage/callbacks-are-called-in-correct-context.html [ Slow ] @@ -569,7 +570,6 @@ crbug.com/874695 [ Debug Mac12 ] http/tests/misc/svg-image-delayed-size-negotiation.html [ Slow ] crbug.com/874695 [ Release ] http/tests/misc/svg-image-delayed-size-negotiation.html [ Slow ] crbug.com/874695 [ Release ] http/tests/multipart/multipart-main-resource.html [ Slow ] -crbug.com/874695 [ Debug Mac12 ] http/tests/multipart/stop-loading-after-onload2.html [ Slow ] crbug.com/874695 [ Release ] http/tests/multipart/stop-loading-after-onload2.html [ Slow ] crbug.com/874695 http/tests/notifications/permission-behaviour.html [ Slow ] crbug.com/874695 http/tests/permissions/chromium/test-request-multiple-sharedworker.html [ Slow ] @@ -1016,7 +1016,6 @@ crbug.com/1044425 [ Mac10.15 Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-1.js [ Slow ] crbug.com/1044425 [ Mac11 Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-1.js [ Slow ] crbug.com/1044425 [ Mac12 Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-1.js [ Slow ] -crbug.com/1044425 [ Mac12-arm64 Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-1.js [ Slow ] crbug.com/1044425 [ Release Win ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-1.js [ Slow ] crbug.com/1044429 [ Linux Release ] http/tests/devtools/oopif/oopif-navigator.js [ Slow ] crbug.com/1044429 [ Mac10.15 Release ] http/tests/devtools/oopif/oopif-navigator.js [ Slow ] @@ -1050,7 +1049,6 @@ crbug.com/1044545 [ Linux Release ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] crbug.com/1044545 [ Mac10.15 Release ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] crbug.com/1044545 [ Mac11 Release ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] -crbug.com/1044545 [ Mac11-arm64 Release ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] crbug.com/1044545 [ Mac12 Release ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] crbug.com/1044545 [ Release Win ] http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js [ Slow ] crbug.com/1044561 [ Linux Release ] http/tests/devtools/elements/styles/show-all-properties.js [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index b0f6e2c..948c325 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2988,6 +2988,7 @@ crbug.com/webrtc/10567 external/wpt/webrtc/simulcast/setParameters-encodings.https.html [ Failure Pass ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-overflow/overflow-overlay.tentative.html [ Failure ] crbug.com/626703 [ Win11 ] external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html [ Failure Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/url/IdnaTestV2.window.html [ Failure Timeout ] crbug.com/626703 external/wpt/css/css-box/margin-trim/block-container-non-adjoining-item.html [ Failure ] @@ -6944,9 +6945,3 @@ # Sheriff 2023-01-24 crbug.com/1409804 [ Mac ] fast/backgrounds/repeat/negative-offset-repeat-transformed.html [ Failure ] crbug.com/1409804 [ Mac ] fast/borders/border-image-rotate-transform.html [ Failure ] - -# These tests must be disabled for the next webrtc rollout (2023-01-25), and -# will be adjusted and reenabled afterwards. -crbug.com/webrtc/14653 external/wpt/webrtc-stats/outbound-rtp.https.html [ Failure Pass ] -crbug.com/webrtc/14653 external/wpt/webrtc-stats/rtp-stats-creation.html [ Failure Pass ] -crbug.com/webrtc/14653 external/wpt/webrtc-stats/supported-stats.https.html [ Failure Pass ]
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 31f96966..8b6f96fd 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
@@ -16157,15 +16157,6 @@ ] ] }, - "screen-wake-lock": { - "wakelock-document-hidden-manual.https.html": [ - "05368bdfb89b2fd9e4ea442b4124fa784babfc10", - [ - null, - {} - ] - ] - }, "selection": { "dir-manual.html": [ "39cf6555234b7b2e189412e97aed5a93b19ccea2", @@ -153075,6 +153066,19 @@ {} ] ], + "overflow-overlay.tentative.html": [ + "e3cb8d7180e4bc5ddb84506e401c0b8c90d81470", + [ + null, + [ + [ + "/css/css-overflow/overflow-overlay-ref.html", + "==" + ] + ], + {} + ] + ], "overflow-recalc-001.html": [ "9c5919a5044bdbac0e782fbb662f1ff3b81857fc", [ @@ -170083,6 +170087,32 @@ {} ] ], + "fit-content-block-size-abspos.html": [ + "d8ce91f9f626f8569bd9452c9fd90ead9a75ee4e", + [ + null, + [ + [ + "/css/css-sizing/fit-content-block-size-fixedpos-ref.html", + "==" + ] + ], + {} + ] + ], + "fit-content-block-size-fixedpos.html": [ + "1f08c6ab9f20747a3ab166a12654e106b5d51efd", + [ + null, + [ + [ + "/css/css-sizing/fit-content-block-size-fixedpos-ref.html", + "==" + ] + ], + {} + ] + ], "fit-content-contribution-001.html": [ "efe3d49f4c8e51e9a4d5c0354cf8a35678658f06", [ @@ -263066,6 +263096,16 @@ } }, "support": { + ".cache": { + "gitignore2.json": [ + "f9b0b4180d2c4674132652e6c8dc7bf314dbd0f8", + [] + ], + "mtime.json": [ + "c43d0da67738c0b2e400c2c1be1168be17aec4ed", + [] + ] + }, ".gitignore": [ "d93e645d547894b50149d3726de2654957b6e06f", [] @@ -263331,6 +263371,14 @@ "545f0bec6d9822e7862fc4010fb8d52d3dc4b768", [] ], + "back-forward-cache-open-connection.window.js.ini": [ + "e9ec6bf98544bbbf3bf03b0aca3ccbfdef063eb6", + [] + ], + "back-forward-cache-open-transaction.window.js.ini": [ + "6f0150ab787c0be71138e2a4d72992f5adb5e187", + [] + ], "database-names-by-origin.html.ini": [ "21e89fe0a7caf86946c6fe5d345b6fb4b68defa9", [] @@ -268662,6 +268710,10 @@ } }, "media-src": { + "media-src-7_1_2.sub.html.ini": [ + "5b6e5c6c89157f9b707a0f382e6e52243aa0b265", + [] + ], "media-src-7_2_2.sub.html.ini": [ "11a5776914ea360b1ab094da359aee88b79d7e6a", [] @@ -284620,7 +284672,7 @@ [] ], "color-computed-color-mix-function-expected.txt": [ - "7a0db87255b80b88aa5feb9cbd439085cedf1028", + "0678a638b56487dbe193b2e9504a27a2d097e288", [] ], "color-computed-color-mix-function.html.ini": [ @@ -303594,7 +303646,7 @@ [] ], "initial-letter-block-position-margins.html.ini": [ - "ca081035386879b52323ef148464adcb96c06986", + "a2522f6f773ce1e32195c79903b1598b248ac11a", [] ], "initial-letter-block-position-raise-over-ruby-ref.html": [ @@ -303770,7 +303822,7 @@ [] ], "initial-letter-raise-initial-vlr.html.ini": [ - "5a7a7c3f9535f1ae8fd2885f325d43aa8507513e", + "30b6e503d8e7ebfe738219623acf09ce21ac96a4", [] ], "initial-letter-raise-initial-vrl-ref.html": [ @@ -303782,7 +303834,7 @@ [] ], "initial-letter-raise-initial.html.ini": [ - "e37e026a1f13a8aa9ae6d202ea3592aa01932f60", + "49f8d162ee40fd2c72038eb86600715809932aef", [] ], "initial-letter-raised-sunken-caps-raise-ref.html": [ @@ -303798,7 +303850,7 @@ [] ], "initial-letter-raised-sunken-caps-sunken.html.ini": [ - "b0631f923a6cf89fe35ed7628a5a15b4d75443bf", + "1735b1a8829ad0fca645a30bfe10b64e852251ed", [] ], "initial-letter-short-para-initial-letter-clears-ref.html": [ @@ -307852,10 +307904,6 @@ "c2f7c669497d363e868cb96d2c2bb1ee315fff49", [] ], - "parsing-expected.txt": [ - "cba7633348beabb13a167f57dd130c194d0a7d63", - [] - ], "parsing.html.ini": [ "7d22b607a4fe843d7fd7609995aa2eb4a2bfb082", [] @@ -308078,6 +308126,14 @@ "e81f5c158a91b87f7c9d385331842ed56f09e4b3", [] ], + "overflow-overlay-ref.html": [ + "3d88b75890c0e20a6beda2f4607ed0ae6ef49d4a", + [] + ], + "overflow-overlay.tentative.html.ini": [ + "42e59c142ef7391427fa1df43e54ff9227197687", + [] + ], "overflow-padding.html.ini": [ "e636219ccc230db90c243820c768dae5bfe898c1", [] @@ -309961,7 +310017,7 @@ [] ], "at-property-expected.txt": [ - "ccc796b11dc6dceda78475b0f3ae764d13b2e481", + "152384c47f3770b477bc6bc027951ff753c28b32", [] ], "at-property-shadow-expected.txt": [ @@ -312023,6 +312079,10 @@ "f3eaa06ac9b7c48479d439041ce51575ad8cc072", [] ], + "scroll-snap-initial-layout-000.html.ini": [ + "16c83539b70190bb6ea44d62e5ec5e57ee3689df", + [] + ], "scroll-snap-writing-mode-000-ref.html": [ "26b622e718c1c38110d45bf99de598dfbc2492b6", [] @@ -313880,6 +313940,10 @@ "c8d67a8d27457acc6edaf3a60d31fc005791d6ed", [] ], + "fit-content-block-size-fixedpos-ref.html": [ + "0f9f8bd1b0352ea66763232f3a093eb569ca9511", + [] + ], "fit-content-length-percentage-001.html.ini": [ "bd89c37d30d3992f47e3a301965ad553be0954a3", [] @@ -325161,6 +325225,10 @@ [] ], "compute-kind-widget-generated": { + "kind-of-widget-fallback-color-input-border-bottom-color-001.html.ini": [ + "6342cc0e0590c033edbea9d80e6e32d6e7d535ba", + [] + ], "kind-of-widget-fallback-color-input-border-bottom-style-001.html.ini": [ "781e3a390720e3062919d91b8b872054bbd0548f", [] @@ -325205,6 +325273,10 @@ "29d7eabe6e824e5d8f5fc855959622524f3e6c1f", [] ], + "kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini": [ + "0cba5c3eb43506a7452ee5b98606a5e28003d047", + [] + ], "kind-of-widget-fallback-input-search-text-border-start-end-radius-001.html.ini": [ "71e3df2aca79ef1b9533880d6cb47dc43226c386", [] @@ -325445,6 +325517,14 @@ "10d4e093393272fd1fa437f1a4147d9af353598f", [] ], + "kind-of-widget-fallback-textarea-border-block-start-color-001.html.ini": [ + "51956159202416657a5ca91c3c721bbba5ef32b9", + [] + ], + "kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini": [ + "fe66ac81494eb5ca854368b84f9397709f111b0d", + [] + ], "kind-of-widget-fallback-textarea-border-bottom-width-001.html.ini": [ "ddeb070c64563f1c0545dbbfc26a2f318730b492", [] @@ -327630,10 +327710,6 @@ "a22882a9996b14afa942d3403fa1a873f526073a", [] ], - "acos-asin-atan-atan2-computed-expected.txt": [ - "9df27f1ecc7912c228b703e27f50805668ecedfa", - [] - ], "acos-asin-atan-atan2-computed.html.ini": [ "666ef4d99263fd8da9d36ea045fb516853d05639", [] @@ -327909,7 +327985,7 @@ [] ], "exp-log-compute-expected.txt": [ - "957334bd597735f39da1b79fbcd7c6108b7b70a8", + "497cf5feea9aacf6a927be6fffd90cc3dd6da6d6", [] ], "exp-log-compute.html.ini": [ @@ -329134,6 +329210,10 @@ "5cd617703dfca9153ba933dc815b40db9ea0dc2c", [] ], + "only-child-on-root-element-with-view-transition.html.ini": [ + "3a8bc30635507d06af947be525d175cb20fe487a", + [] + ], "only-child-view-transition.html.ini": [ "89418c9065bdcf6c948ab2873829b1f8a491021e", [] @@ -332901,7 +332981,7 @@ [] ], "cssom-getPropertyValue-common-checks-expected.txt": [ - "36e1cf228ac16984d365ed2f8dc3a657f0c09c53", + "3139f1893f3de74f8a5c8ea2b09d34d4a0530d52", [] ], "cssom-getPropertyValue-common-checks.html.ini": [ @@ -333412,6 +333492,10 @@ "436026016cfbbe9c4f2daafc34d35f20109f53b1", [] ], + "scroll-behavior-main-frame-window.html.ini": [ + "3ef649a337e2cac6a6a81e7d6afac4f0b037a80c", + [] + ], "scroll-behavior-scrollintoview-nested.html.ini": [ "2bfa1166f1dae5798d20be4cde49808b376cfd6d", [] @@ -352234,7 +352318,7 @@ [] ], "offscreencanvas.resize.html.ini": [ - "6685bb0261791e03a2a77d4d65cdc2b3e94c1d4d", + "961439ddbbe2a7ed509e0c82b67f90514d3e0be1", [] ], "offscreencanvas.transferrable-expected.txt": [ @@ -352519,8 +352603,12 @@ ] }, "tools": { + "PRESUBMIT.py": [ + "048e96b7012b70b276922ace2d7cdd811ebb3291", + [] + ], "gentest.py": [ - "cb1f720590ce8b41fe6bcb113ee24a60e173d263", + "bca7b9ecfcb72dccec216b5435f9071f47fde0be", [] ], "gentest_union.py": [ @@ -352528,11 +352616,11 @@ [] ], "gentestutils.py": [ - "1206aa91bfbe737b55a1ba500713e18cbf8e07fd", + "2517568a5a83c9e8539a7c93e69aaf8a085504f4", [] ], "gentestutilsunion.py": [ - "c6fba8453d0ebbe389f6b9103f6272869076e641", + "4c65d688c25f27d6d29f4732f1f250323385a945", [] ], "name2dir-canvas.yaml": [ @@ -352659,7 +352747,7 @@ [] ], "drawing-images-to-the-canvas.yaml": [ - "83de88113f23a5051bed0296db4ce17c2bec9ebe", + "e263bf0253dd121a97f32e3747c32e7799518ccd", [] ], "drawing-rectangles-to-the-canvas.yaml": [ @@ -353581,7 +353669,7 @@ [] ], "access-from-coop-page-to-other_coop-ro_cross-origin.https.html.ini": [ - "dd5c96b2e6d713af4e5402595b2b6e459a64352e", + "b646d8f03b54e8d469a0db410f97c110ff65572d", [] ], "access-to-coop-page-from-openee_coop-ro.https.html.ini": [ @@ -353653,11 +353741,11 @@ [] ], "property-opener-get.https.html.ini": [ - "e2fdfcf0ef094326e8f5b71b19eac42d1bcc2860", + "93713704d43d990592dd2189e8762e8f822a1c32", [] ], "property-postmessage-1.https.html.ini": [ - "80c54e425041a962415adcd795fa17dfa4e000d7", + "8103815e52fadac0ebf1a0dc8532e71d044adf94", [] ], "property-postmessage-2.https.html.ini": [ @@ -353944,12 +354032,8 @@ "a9f437575f66150f8fd2c836b899e3f0482b56e5", [] ], - "iframe-popup.https_1-2-expected.txt": [ - "85fef3c93db4e09f6777587aaaa655d356b40c1b", - [] - ], "iframe-popup.https_3-4-expected.txt": [ - "414431ce343913da131d9d0305c9946f320e34c8", + "71f4d09dd9c5b1901424d21f863b45744d1fbbc2", [] ], "iframe-popup.https_5-6-expected.txt": [ @@ -353968,10 +354052,6 @@ "451ebcb458c91701218196ed1555cca521c06dd9", [] ], - "named_targeting.https.html.headers": [ - "d5c99062d2bb8f9660b68c172754867b598ed43f", - [] - ], "named_targeting.https.html.ini": [ "0d8d8a1199f01e357198462451447f13ad1d4eb0", [] @@ -354025,7 +354105,7 @@ [] ], "popup-with-same-origin.https-expected.txt": [ - "c7d65ce9730008260d8afbc2377e6f1d12d8004f", + "7e0d37df7bace35a7b5657397987ca0a0ae747ca", [] ], "popup-with-same-origin.https.html.headers": [ @@ -354609,6 +354689,10 @@ "af0a222712ae6ba3b982f86cabdb1963585ac44a", [] ], + "remove-attr-script-keeps-blocking.tentative.html.ini": [ + "0d2530b93d6dfbfb05740910d63c609cef0c8a5d", + [] + ], "script-inserted-module-script.tentative.html.ini": [ "1300db71de88366d5e48d1fb7c620651e7ca4cd1", [] @@ -361315,7 +361399,7 @@ [] ], "sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini": [ - "35055d35d6f6cfe27703b0291525e13449e746bb", + "d55b004b546db9832f5e376ab8ef5ac0891a5d57", [] ], "sandbox-top-navigation-child.tentative.sub.window.js.ini": [ @@ -369200,7 +369284,7 @@ [] ], "payment-handler.idl": [ - "d0e5bd9fda832377e89a8b2b62fb4f597847a780", + "65b64bdf31c7dfed778ba475e154cd780ca44e86", [] ], "payment-request.idl": [ @@ -370006,7 +370090,7 @@ [] ], "image-upscaling-expected.txt": [ - "da3370fc1ce3f80aed71818059ba09d426fbc36e", + "051564acf63eff19e602dfa7f24a9d33a55238ad", [] ], "image-upscaling.html.ini": [ @@ -370047,7 +370131,7 @@ [] ], "largest-contentful-paint-helpers.js": [ - "043587ca654c44fb97ae41e32cff094852199365", + "b0fe1b08cb44b1871ba6dac4c1d25018c6032019", [] ], "lcp-sw-from-cache.js": [ @@ -370173,7 +370257,7 @@ ] }, "lint.ignore": [ - "11821957cf4db2a454da4f7b135198797ceb437f", + "011f05c607e24b53f0d1120dc9c8a6cf5fdf06d9", [] ], "loading": { @@ -370291,7 +370375,7 @@ [] ], "redirect-same-origin.h2.window.js.ini": [ - "767a4707158efbf32bf2db68b19f0bedaebbeefb", + "9e3b2210f7117fca10ca8005620d2ab90ccfd550", [] ], "referrer-policy-no-referrer.h2.window.js.ini": [ @@ -370307,7 +370391,7 @@ [] ], "referrer-policy-same-origin.h2.window.js.ini": [ - "c87d9d932d697b2bc9d7d875954889d53d95e1c4", + "b3b07ad35f0358085375962cf7c56b9106383e64", [] ], "referrer-policy-unsafe-url.h2.window.js.ini": [ @@ -374848,19 +374932,19 @@ [] ], "idlharness.https.any.js.ini": [ - "1aae22f455614b6d0e77c2f21120f84ec980c074", + "dc57fd5daeba4ea318ab14228c262fcdc08865d9", [] ], "idlharness.https.any.serviceworker-expected.txt": [ - "67988491ceee4a297288bd291dfe666eea7dcc18", + "90e3142f5a96dc812a5cbd21f2703f9f8b4aef04", [] ], "idlharness.https.any.sharedworker-expected.txt": [ - "2ee5817ecc3190f2284ce6f3d040ab589ebc5f94", + "28845dfb2c7b490e78e70948a71bf006d5cfd76e", [] ], "idlharness.https.any.worker-expected.txt": [ - "2ee5817ecc3190f2284ce6f3d040ab589ebc5f94", + "28845dfb2c7b490e78e70948a71bf006d5cfd76e", [] ], "manifest.json": [ @@ -374873,14 +374957,6 @@ [] ] }, - "payment-instruments.https-expected.txt": [ - "5ece796c5718f596e26071f5beb6cd8e9b04b069", - [] - ], - "payment-instruments.https.html.ini": [ - "d3aff8ef6aeb40d6c8097d44c88f14be81875d12", - [] - ], "payment-request-event-constructor.https.serviceworker.js": [ "1aea7000c1428e84f8e1d4ce1ccae63e97741122", [] @@ -374889,10 +374965,6 @@ "f97229762ce388ff0695d56684099b9286326a29", [] ], - "register-and-activate-service-worker.js": [ - "fb54c5c06488f319b0b4152837cc6a1b530cab7a", - [] - ], "supports-shipping-contact-delegation-manual-manifest.json": [ "fd6bc89ef6d38e0cee82bfadcc697e36a2952070", [] @@ -379217,7 +379289,7 @@ [] ], "entry-invariants.js": [ - "dc907533946b383ccadd62ce1c81135ee6c1d19c", + "bbc913b722903085963a133dab0a8a96f77b2506", [] ], "eventsource.py": [ @@ -379397,7 +379469,7 @@ [] ], "resource-loaders.js": [ - "70889b709f15a40f9cdc12cfeafb7a46c88b9a0c", + "37fea16b1750faa5df8983cc88ce197125c21490", [] ], "resource-timing-content-length.py": [ @@ -379469,10 +379541,6 @@ [] ] }, - "response-status-code.html.ini": [ - "cd9aff10210dc83476601b743d80ae930d6cad04", - [] - ], "sleep.py": [ "2e803b1b262423e219be592fab548ada982bc439", [] @@ -380053,6 +380121,10 @@ "66f07f4c1c3f106517d4e21f2edd613465ab1672", [] ], + "wakelock-document-hidden.https.html.ini": [ + "59e9a5ef4db2840fd40fd5af3e544cf04c90f840", + [] + ], "wakelock-enabled-by-permissions-policy-attribute-redirect-on-load.https.html.ini": [ "5e28dd5bda7c100751aa279f21ce9061032ef7af", [] @@ -389245,7 +389317,7 @@ [] ], "setters_tests.json": [ - "df75ab57c420dc18067c1ba6d601503a64e9422a", + "9c4eedc60893edc7adab53d85b88e76fe6b9e5a2", [] ], "toascii.json": [ @@ -389296,7 +389368,7 @@ [] ], "url-setters-a-area.window.js.ini": [ - "86f08514f273b55c713f6b32bed684e7bbc42525", + "cd504e5d2aaae0553b25ea3bb86144364e8e4200", [] ], "url-setters-a-area.window_include=javascript-expected.txt": [ @@ -389320,7 +389392,7 @@ [] ], "url-setters.any.js.ini": [ - "eb1c0e5515927cd3f7d8a3d05254a0a525909fcc", + "bdac88f44a65392b9ef8ef6f7508c5c79dc3a729", [] ], "url-setters.any.worker_include=javascript-expected.txt": [ @@ -438623,7 +438695,7 @@ ] ], "at-container-parsing.html": [ - "2fbd4b8b6f46185d97b2badf1a71129012cc7df4", + "d0aef94de55eca8c00cde4d3ddb7bd94105573c8", [ null, {} @@ -438636,6 +438708,13 @@ {} ] ], + "at-container-style-parsing.html": [ + "5bd9e018c1a317f5fe0dd055e04ef3f87d55f1cd", + [ + null, + {} + ] + ], "at-container-style-serialization.html": [ "9544463859106e2a4a3ca34cd80364139de29160", [ @@ -447209,6 +447288,13 @@ null, {} ] + ], + "baseline-source-vertical-align.html": [ + "32bbe434974df6bfab2a91c42dca3b8e4bf7f43f", + [ + null, + {} + ] ] }, "inheritance.html": [ @@ -448953,7 +449039,7 @@ ] ], "parsing.html": [ - "66d1566586cd7d94f3c1da014e1ef3e4134daeac", + "8e445faf1c9b8b0942f684d5093c5a7071d43a91", [ null, {} @@ -450626,7 +450712,7 @@ ] ], "at-property.html": [ - "d996091dc203eab079fff2d2b980d064300af39b", + "b91b143e368ff5371bce34d9b0e43ca78ed358cf", [ null, {} @@ -452039,6 +452125,13 @@ {} ] ], + "focus-element-no-snap.html": [ + "9ec004c6287008693e73bb51d0503f99e2f0b087", + [ + null, + {} + ] + ], "move-current-target.html": [ "ccadc884c5ba23f90b4b7d273e5aaf355cf648d1", [ @@ -462034,7 +462127,7 @@ ] ], "acos-asin-atan-atan2-computed.html": [ - "6fc8bdfe6af42bb53bbdfdaff71a9bb13135ccb4", + "2835e7a20abc917e111d22a9b04fca17493b4793", [ null, {} @@ -462288,7 +462381,7 @@ ] ], "exp-log-compute.html": [ - "8812253bf10bb940e855b9b0af5a57ab62fbf216", + "3fa240004426d6968f01808a4ab1f3fba3114522", [ null, {} @@ -463161,21 +463254,21 @@ ] ], "only-child-group.html": [ - "034df41dde165f7624effddf70209472ea74a322", + "c3e9d669a30e24c93cbe0dc20c211b8e3e92d9a8", [ null, {} ] ], "only-child-image-pair.html": [ - "830b37313eaaa3165d5739b39f2ccb415886e724", + "93fcc0a5ea8bcfce67c6f375ecd19602337949ef", [ null, {} ] ], "only-child-new.html": [ - "2f8a7a4023ec7ffde81a6eeda6a65ca4533540ce", + "62328f27cf259d5b50fbea43e02ba3200364b8e7", [ null, {} @@ -463189,7 +463282,14 @@ ] ], "only-child-old.html": [ - "4ca6fed20ce7b2f092de2c324ad6197caed22bc9", + "56dfa168e253eddc61e41db8bcd766c3282ae726", + [ + null, + {} + ] + ], + "only-child-on-root-element-with-view-transition.html": [ + "0bf6d8b84b397f6818b133374b4ba0446af70842", [ null, {} @@ -466406,6 +466506,13 @@ {} ] ], + "match-media-parsing.html": [ + "9d9aa3dd581579dfb6e14e2ad82ee54f8f575696", + [ + null, + {} + ] + ], "media-query-matches-in-iframe.html": [ "5828936732e7133d4365eb288b99e99cb428fb19", [ @@ -468546,7 +468653,7 @@ ] ], "form-disabled-callback.html": [ - "954c3f3f6eecc95b12ffb235ffe287675f734429", + "c61a7719fc628c21d380e7f16c8c19921e3ceb2b", [ null, {} @@ -535647,7 +535754,7 @@ ] ], "iframe-popup.https.html": [ - "2c6f0b62822f61bc4aac8a9bdd50cdbd724c07eb", + "17840724d9e342aa52cdcc474356b25d554dfd63", [ "html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html?1-2", { @@ -535732,7 +535839,7 @@ ] ], "popup-with-same-origin.https.html": [ - "491cbc3b9d091e91976624b807a76f254fa68958", + "c0020fa23a478fd75aa27b69edb95c84f3e3789a", [ null, { @@ -548823,6 +548930,13 @@ {} ] ], + "popover-target-element-disabled.tentative.html": [ + "3d139c5950eb6bc1048c10e0ea6053369cb93403", + [ + null, + {} + ] + ], "popover-top-layer-combinations.tentative.html": [ "001bf88a25ef851e6607dc6e0ba7a7cf3b8cf4f8", [ @@ -561197,7 +561311,7 @@ ] ], "image-upscaling.html": [ - "a4f7d8079d3b9a75f79b896743cbc018cc81c9ce", + "5cb3767ca7d29a30103797c8c8abe1c692787466", [ null, {} @@ -572103,7 +572217,7 @@ ] ], "idlharness.https.any.js": [ - "dfb0190abacb96c61cf5c125c68a1ad346f60205", + "d34e20630bf7d60faa5aa8333d1595754420c080", [ "payment-handler/idlharness.https.any.html", { @@ -572217,13 +572331,6 @@ } ] ], - "payment-instruments.https.html": [ - "121c131568852eafe1b9ce5f9ec148c2cbee3fb6", - [ - null, - {} - ] - ], "payment-request-event-constructor.https.html": [ "31ac8cafa78fb52fb7c02722003b5359ceadb7e2", [ @@ -572246,7 +572353,7 @@ ] ], "same-object-attributes.https.html": [ - "2e5dea3a4aed33378f25b09b6e58929e22f2f72c", + "27c204484359d6b1afbb3412ae4feabf1295d6b1", [ null, {} @@ -590025,7 +590132,7 @@ ] ], "cross-origin-start-end-time-with-redirects.html": [ - "1b107d3aef7764d9b9603ea2658cf469cf285980", + "8e368d13807745761083b090bc097217ff22e598", [ null, {} @@ -590476,7 +590583,7 @@ ] ], "object-not-found-after-cross-origin-redirect.html": [ - "4d5d121fe32c4232dc8094906f92b7c8ac8d2ef1", + "6990c6c06082e5d62ba3aa576eccd42d13246d2a", [ null, { @@ -590606,7 +590713,7 @@ ] ], "response-status-code.html": [ - "3c606c5496e6c7f9b0ecd5a7bfec9a611ad4f86f", + "3a184c6f016b28c7003ea4650b7827b74388faf8", [ null, { @@ -592682,6 +592789,15 @@ {} ] ], + "wakelock-document-hidden.https.html": [ + "c8c9712bdd95f65b292535df844634aedb5abb19", + [ + null, + { + "testdriver": true + } + ] + ], "wakelock-enabled-by-permissions-policy-attribute-redirect-on-load.https.html": [ "acfce43f96247949d7e4963970d0502d9c0b5d5d", [ @@ -623824,7 +623940,7 @@ ] ], "getcredential-prf.https.html": [ - "6f8670f64d19e1a7366eb6cf42a83a3b6eedd387", + "61b52ac5958c7b242168285ad5e83581b4c1497e", [ null, {
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js.ini new file mode 100644 index 0000000..e9ec6bf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-connection.window.js.ini
@@ -0,0 +1,3 @@ +[back-forward-cache-open-connection.window.html] + [Testing BFCache support for page with open IndexedDB connection, and eviction behavior when receiving versionchange event.] + expected: PRECONDITION_FAILED
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-transaction.window.js.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-transaction.window.js.ini new file mode 100644 index 0000000..6f0150a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/back-forward-cache-open-transaction.window.js.ini
@@ -0,0 +1,3 @@ +[back-forward-cache-open-transaction.window.html] + [BFCache support test for page with open IndexedDB transaction] + expected: PRECONDITION_FAILED
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/media-src/media-src-7_1_2.sub.html.ini b/third_party/blink/web_tests/external/wpt/content-security-policy/media-src/media-src-7_1_2.sub.html.ini new file mode 100644 index 0000000..5b6e5c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/media-src/media-src-7_1_2.sub.html.ini
@@ -0,0 +1,2 @@ +[media-src-7_1_2.sub.html] + expected: TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt index 7a0db87..0678a638 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-color-mix-function-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 450 tests; 400 PASS, 50 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 450 tests; 422 PASS, 28 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' PASS Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' PASS Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' @@ -54,8 +54,8 @@ PASS Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' PASS Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' PASS Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' -FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 143 +/- 0.0001, expected 143 but got 245 +PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' +PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' PASS Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' FAIL Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 1, expected 249 +/- 0.0001, expected 249 but got 255 FAIL Property color value 'color-mix(in hsl, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 1, expected 255 +/- 0.0001, expected 255 but got 150 @@ -120,8 +120,8 @@ PASS Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' PASS Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' -FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 147 +/- 0.0001, expected 147 but got 98 +PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' +PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' PASS Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' FAIL Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 1, expected 249 +/- 0.0001, expected 249 but got 255 FAIL Property color value 'color-mix(in hwb, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_array_approx_equals: Numeric parameters are approximately equal. property 1, expected 255 +/- 0.0001, expected 255 but got 150 @@ -186,8 +186,8 @@ PASS Property color value 'color-mix(in lch, lch(10 20 none), lch(50 60 70deg))' PASS Property color value 'color-mix(in lch, lch(10 20 30deg), lch(50 60 none))' PASS Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50 none 70deg))' -FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 30 +/- 0.0001, expected 30 but got 70 +PASS Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))' +PASS Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))' PASS Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / none))' PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 70deg))' PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg) 25%, oklch(50 60 70deg))' @@ -243,8 +243,8 @@ PASS Property color value 'color-mix(in oklch, oklch(10 20 none), oklch(50 60 70deg))' PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 none))' PASS Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50 none 70deg))' -FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 30 +/- 0.0001, expected 30 but got 70 +PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))' +PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))' PASS Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / none))' PASS Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 70))' PASS Property color value 'color-mix(in lab, lab(10 20 30) 25%, lab(50 60 70))' @@ -270,8 +270,8 @@ PASS Property color value 'color-mix(in lab, lab(10 20 none), lab(50 60 70))' PASS Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 none))' PASS Property color value 'color-mix(in lab, lab(none 20 30), lab(50 none 70))' -FAIL Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 30 +/- 0.0001, expected 30 but got 70 +PASS Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))' +PASS Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))' PASS Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / none))' PASS Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 70))' PASS Property color value 'color-mix(in oklab, oklab(10 20 30) 25%, oklab(50 60 70))' @@ -297,8 +297,8 @@ PASS Property color value 'color-mix(in oklab, oklab(10 20 none), oklab(50 60 70))' PASS Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 none))' PASS Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50 none 70))' -FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 30 +/- 0.0001, expected 30 but got 70 +PASS Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))' +PASS Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))' PASS Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / none))' PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' @@ -327,8 +327,8 @@ PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' PASS Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' -FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 0.3 +/- 0.0001, expected 0.3 but got 0.7 +PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' +PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' PASS Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' @@ -357,8 +357,8 @@ PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' -FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 0.3 +/- 0.0001, expected 0.3 but got 0.7 +PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' +PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' PASS Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' @@ -387,8 +387,8 @@ PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' PASS Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' -FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 0.3 +/- 0.0001, expected 0.3 but got 0.7 +PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' +PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' PASS Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' @@ -417,8 +417,8 @@ PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' -FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 0.3 +/- 0.0001, expected 0.3 but got 0.7 +PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' +PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' PASS Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' @@ -447,8 +447,8 @@ PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' -FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' assert_array_approx_equals: Numeric parameters are approximately equal. lengths differ, expected 3 got 4 -FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' assert_array_approx_equals: Numeric parameters are approximately equal. property 0, expected 0.3 +/- 0.0001, expected 0.3 but got 0.7 +PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' +PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' PASS Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-parsing.html index 2fbd4b8b..d0aef94 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-parsing.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-parsing.html
@@ -191,16 +191,4 @@ test_container_name_invalid('And'); test_container_name_invalid('oR'); test_container_name_invalid('nOt'); - - test_condition_known('style(--my-prop: foo)'); - test_condition_known('style(--my-prop: foo - bar ())'); - test_condition_known('style(not ((--foo: calc(10px + 2em)) and ((--foo: url(x)))))'); - test_condition_known('style((--foo: bar) or (--bar: 10px))'); - test_condition_known('style(--my-prop:)'); - test_condition_known('style(--my-prop: )'); - test_condition_known('style(--foo: bar !important)'); - - test_condition_unknown('style(--foo: bar;)'); - test_condition_unknown('style(--foo)'); - test_condition_unknown('style(style(--foo: bar))'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-style-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-style-parsing.html new file mode 100644 index 0000000..5bd9e018 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/at-container-style-parsing.html
@@ -0,0 +1,75 @@ +<!doctype html> +<title>@container: style queries parsing</title> +<link rel="help" href="https://drafts.csswg.org/css-contain-3/#container-rule"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/cq-testcommon.js"></script> +<div style="container-name:name;container-type:size; width:100px; height:100px"> + <main id=main></main> +</div> +<script> + setup(() => assert_implements_container_queries()); + + function cleanup_main() { + while (main.firstChild) + main.firstChild.remove(); + } + + function set_style(text) { + let style = document.createElement('style'); + style.innerText = text; + main.append(style); + return style; + } + + function test_rule_valid(query) { + test(t => { + t.add_cleanup(cleanup_main); + let style = set_style(`@container ${query} {}`); + assert_equals(style.sheet.rules.length, 1); + }, query); + } + + function test_condition_invalid(condition) { + test(t => { + t.add_cleanup(cleanup_main); + let style = set_style(`@container name ${condition} {}`); + assert_equals(style.sheet.rules.length, 0); + }, condition); + } + + // Tests that 1) the condition parses, and 2) is either "unknown" or not, as + // specified. + function test_condition_valid(condition, unknown) { + test(t => { + t.add_cleanup(cleanup_main); + let style = set_style(` + @container name ${condition} {} + @container name (${condition}) or (not (${condition})) { main { --match:true; } } + `); + assert_equals(style.sheet.rules.length, 2); + const expected = unknown ? '' : 'true'; + assert_equals(getComputedStyle(main).getPropertyValue('--match'), expected); + }, condition); + } + + function test_condition_known(condition) { + test_condition_valid(condition, false /* unknown */); + } + + function test_condition_unknown(condition) { + test_condition_valid(condition, true /* unknown */); + } + + test_condition_known('style(--my-prop: foo)'); + test_condition_known('style(--my-prop: foo - bar ())'); + test_condition_known('style(not ((--foo: calc(10px + 2em)) and ((--foo: url(x)))))'); + test_condition_known('style((--foo: bar) or (--bar: 10px))'); + test_condition_known('style(--my-prop:)'); + test_condition_known('style(--my-prop: )'); + test_condition_known('style(--foo: bar !important)'); + + test_condition_unknown('style(--foo: bar;)'); + test_condition_unknown('style(--foo)'); + test_condition_unknown('style(style(--foo: bar))'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/baseline-source/baseline-source-vertical-align.html b/third_party/blink/web_tests/external/wpt/css/css-inline/baseline-source/baseline-source-vertical-align.html new file mode 100644 index 0000000..32bbe43 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/baseline-source/baseline-source-vertical-align.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-inline-3/#baseline-source"> +<style> +#target { + baseline-source: first; + vertical-align: baseline; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="target"></div> +<script> +test(() => { + const target = document.getElementById('target'); + assert_equals(getComputedStyle(target).baselineSource, 'auto'); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html.ini index ca081035..a2522f6f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html.ini
@@ -1,3 +1,3 @@ [initial-letter-block-position-margins.html] expected: - if flag_specific == "disable-layout-ng": FAIL + if product == "chrome": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini index 5a7a7c3..30b6e50 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini
@@ -1,3 +1,3 @@ [initial-letter-raise-initial-vlr.html] expected: - if flag_specific == "disable-layout-ng": FAIL + if product == "chrome": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html.ini index e37e026..49f8d16 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html.ini
@@ -1,3 +1,3 @@ [initial-letter-raise-initial.html] expected: - if flag_specific == "disable-layout-ng": FAIL + if product == "chrome": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini index b0631f92..1735b1a8 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini
@@ -1,3 +1,3 @@ [initial-letter-raised-sunken-caps-sunken.html] expected: - if flag_specific == "disable-layout-ng": FAIL + if product == "chrome": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing-expected.txt deleted file mode 100644 index cba76333..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing-expected.txt +++ /dev/null
@@ -1,46 +0,0 @@ -This is a testharness.js-based test. -PASS .foo { - & { color: green; } -} -PASS .foo { - &.bar { color: green; } -} -PASS .foo { - & .bar { color: green; } -} -PASS .foo { - & > .bar { color: green; } -} -PASS .foo { - &:is(.bar, &.baz) { color: green; } -} -PASS .foo { - .bar& { color: green; } -} -PASS .foo { - .bar & { color: green; } -} -PASS .foo { - .bar > & { color: green; } -} -PASS .foo, .bar { - & + .baz, &.qux { color: green; } -} -PASS .foo { - & .bar & .baz & .qux { color: green; } -} -FAIL .foo { - @media (min-width: 50px) { - & { color: green; } -} -} assert_equals: expected ".foo {\n @media (min-width: 50px) {\n & { color: green; }\n}\n}" but got ".foo {\n @media (min-width: 50px) { color: green; }\n}" -PASS .foo { - @media (min-width: 50px) { color: green; } -} -PASS main { - & > section, & > article { - & > header { color: green; } -} -} -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing.html b/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing.html index 66d1566..8e445fa 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing.html +++ b/third_party/blink/web_tests/external/wpt/css/css-nesting/parsing.html
@@ -25,7 +25,6 @@ `.foo {\n .bar > & { color: green; }\n}`, `.foo, .bar {\n & + .baz, &.qux { color: green; }\n}`, `.foo {\n & .bar & .baz & .qux { color: green; }\n}`, - `.foo {\n @media (min-width: 50px) {\n & { color: green; }\n}\n}`, `.foo {\n @media (min-width: 50px) { color: green; }\n}`, `main {\n & > section, & > article {\n & > header { color: green; }\n}\n}`, ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay-ref.html new file mode 100644 index 0000000..3d88b75 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay-ref.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<style> + div { + width: 15em; + height: 10em; + overflow: auto; + } +</style> +<div> + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html new file mode 100644 index 0000000..e3cb8d7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8063"> +<link rel="match" href="overflow-overlay-ref.html"> +<style> + div { + width: 15em; + height: 10em; + overflow: overlay; + } +</style> +<div> + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html.ini b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html.ini new file mode 100644 index 0000000..42e59c14 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-overlay.tentative.html.ini
@@ -0,0 +1,2 @@ +[overflow-overlay.tentative.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property-expected.txt index ccc796b..152384c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 62 tests; 61 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 66 tests; 65 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Attribute 'syntax' returns expected value for ["<color>"] PASS Attribute 'syntax' returns expected value for ["<color> | none"] PASS Attribute 'syntax' returns expected value for ["<color># | <image> | none"] @@ -57,6 +57,10 @@ PASS Rule not applied [gandalf, grey, false] PASS Rule not applied [<color>, notacolor, false] PASS Rule not applied [<length>, 10em, false] +PASS Rule not applied [<transform-function>, translateX(1em), false] +PASS Rule not applied [<transform-function>, translateY(1lh), false] +PASS Rule not applied [<transform-list>, rotate(10deg) translateX(1em), false] +PASS Rule not applied [<transform-list>, rotate(10deg) translateY(1lh), false] PASS Non-inherited properties do not inherit PASS Inherited properties inherit PASS Initial values substituted as computed value
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property.html index d996091..b91b143e 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property.html +++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/at-property.html
@@ -148,6 +148,11 @@ test_not_applied('<color>', 'notacolor', false); test_not_applied('<length>', '10em', false); +test_not_applied('<transform-function>', 'translateX(1em)', false); +test_not_applied('<transform-function>', 'translateY(1lh)', false); +test_not_applied('<transform-list>', 'rotate(10deg) translateX(1em)', false); +test_not_applied('<transform-list>', 'rotate(10deg) translateY(1lh)', false); + // Inheritance test_with_at_property({
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html.ini b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html.ini new file mode 100644 index 0000000..16c8353 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html.ini
@@ -0,0 +1,2 @@ +[scroll-snap-initial-layout-000.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/focus-element-no-snap.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/focus-element-no-snap.html new file mode 100644 index 0000000..9ec004c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-relayout/focus-element-no-snap.html
@@ -0,0 +1,51 @@ +<!doctype html> +<title>Resnap to focused element after relayout</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + +#snapper { + width: 100px; + height: 200px; + overflow-x: scroll; + scroll-snap-type: x mandatory; + color: white; + background-color: oldlace; + display: flex; + align-items: center; +} +.child { + margin-right: 0.5rem; + height: 90%; + scroll-snap-align: start; + padding: 1rem; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + width: 100px; + height: 100px; + background-color: indigo; +} +</style> + +<link rel="help" href="https://drafts.csswg.org/css-scroll-snap/#re-snap"> + +<div id=snapper> + <div class="child no-snap" tabindex=-1></div> + <div class=child></div> + <div class="child" id ="focus" tabindex=-1></div> + <div class="child" tabindex=-1></div> + <div class=child></div> + <div class=child></div> +</div> + +<script> + +test(t => { + document.getElementById("focus").focus(); + const element = document.getElementById("snapper"); + element.style.width = "101px"; + assert_equals(element.scrollLeft, 0); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html new file mode 100644 index 0000000..d8ce91f9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#valdef-width-fit-content"> +<link rel="match" href="fit-content-block-size-fixedpos-ref.html"> +<style> +body { + overflow: hidden; +} +#container { + height: fit-content; + position: absolute; + top: 50%; + background-color: gold; + margin: auto; + bottom: 0; +} +</style> +<div id="container"> + <div style="height:90vh;width:50px;outline: 2px dotted red;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos-ref.html new file mode 100644 index 0000000..0f9f8bd1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos-ref.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<style> +#container { + height: 90vh; + position: fixed; + top: 50%; + background-color: gold; + margin: auto; + bottom: 0; +} +</style> +<div id="container"> + <div style="height:90vh;width:50px;outline: 2px dotted red;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html new file mode 100644 index 0000000..1f08c6ab --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#valdef-width-fit-content"> +<link rel="match" href="fit-content-block-size-fixedpos-ref.html"> +<style> +#container { + height: fit-content; + position: fixed; + top: 50%; + background-color: gold; + margin: auto; + bottom: 0; +} +</style> +<div id="container"> + <div style="height:90vh;width:50px;outline: 2px dotted red;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-color-001.html.ini new file mode 100644 index 0000000..6342cc0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-bottom-color-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-color-input-border-bottom-color-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini new file mode 100644 index 0000000..0cba5c3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-right-radius-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-input-search-border-top-right-radius-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-color-001.html.ini new file mode 100644 index 0000000..5195615 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-color-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-textarea-border-block-start-color-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini new file mode 100644 index 0000000..fe66ac8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-textarea-border-block-start-style-001.html.ini
@@ -0,0 +1,2 @@ +[kind-of-widget-fallback-textarea-border-block-start-style-001.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt deleted file mode 100644 index 9df27f1e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt +++ /dev/null
@@ -1,44 +0,0 @@ -This is a testharness.js-based test. -PASS acos(1) should be used-value-equivalent to 0deg -PASS atan(0) should be used-value-equivalent to 0deg -PASS asin(0) should be used-value-equivalent to 0deg -PASS atan2(0,0) should be used-value-equivalent to 0deg -PASS calc(asin(sin(pi/2))) should be used-value-equivalent to 90deg -PASS calc(acos(cos(pi - 3.14159265358979323846))) should be used-value-equivalent to 0deg -PASS calc(atan(e - 2.7182818284590452354) ) should be used-value-equivalent to 0deg -PASS calc(asin(sin(30deg + 1.0471967rad ) )) should be used-value-equivalent to 90deg -FAIL calc(acos(cos(30deg - 0.523599rad ) )) should be used-value-equivalent to 0deg assert_not_equals: calc(acos(cos(30deg - 0.523599rad ) )) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" -PASS calc(asin(sin(3.14159 / 2 + 1 - 1) )) should be used-value-equivalent to 90deg -PASS calc(asin(sin(100grad) )) should be used-value-equivalent to 90deg -PASS calc(acos(cos(0 / 2 + 1 - 1) )) should be used-value-equivalent to 0deg -PASS calc(atan(tan(30deg + 0.261799rad ) )) should be used-value-equivalent to 45deg -PASS calc(atan(tan(0.7853975rad ) )) should be used-value-equivalent to 45deg -PASS calc(atan(tan(3.14159 / 4 + 1 - 1) )) should be used-value-equivalent to 45deg -PASS calc(asin(sin(0.25turn)) ) should be used-value-equivalent to 90deg -PASS calc(atan2(0,1)) should be used-value-equivalent to 0deg -PASS calc(atan2(0,-1)) should be used-value-equivalent to -180deg -PASS calc(atan2(1,-1)) should be used-value-equivalent to 135deg -PASS calc(atan2(-1,1)) should be used-value-equivalent to -45deg -PASS calc(cos(sin(acos(cos(pi))))) should be used-value-equivalent to 1 -PASS calc(sin(atan(tan(pi/2)))) should be used-value-equivalent to 1 -PASS atan2(1px, -1px) should be used-value-equivalent to 135deg -PASS atan2(1cm, -1cm) should be used-value-equivalent to 135deg -PASS atan2(1mm, -1mm) should be used-value-equivalent to 135deg -PASS atan2(1Q, -1Q) should be used-value-equivalent to 135deg -PASS atan2(1in, -1in) should be used-value-equivalent to 135deg -PASS atan2(1pc, -1pc) should be used-value-equivalent to 135deg -PASS atan2(1pt, -1pt) should be used-value-equivalent to 135deg -PASS atan2(1em, -1em) should be used-value-equivalent to 135deg -PASS atan2(1ex, -1ex) should be used-value-equivalent to 135deg -PASS atan2(1ch, -1ch) should be used-value-equivalent to 135deg -PASS atan2(1rem, -1rem) should be used-value-equivalent to 135deg -PASS atan2(1vh, -1vh) should be used-value-equivalent to 135deg -PASS atan2(1vw, -1vw) should be used-value-equivalent to 135deg -PASS atan2(1deg, -1deg) should be used-value-equivalent to 135deg -PASS atan2(1grad, -1grad) should be used-value-equivalent to 135deg -PASS atan2(1turn, -1turn) should be used-value-equivalent to 135deg -PASS atan2(1rad, -1rad) should be used-value-equivalent to 135deg -PASS atan2(1s, -1s) should be used-value-equivalent to 135deg -PASS atan2(1ms, -1ms) should be used-value-equivalent to 135deg -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html index 6fc8bdf..2835e7a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-values/acos-asin-atan-atan2-computed.html
@@ -28,7 +28,7 @@ // General calculations test_math_used('calc(asin(sin(30deg + 1.0471967rad ) ))', '90deg', {type:'angle', approx:0.1}); -test_math_used('calc(acos(cos(30deg - 0.523599rad ) ))', '0deg'), {type:'angle', approx:0.1}; +test_math_used('calc(acos(cos(30deg - 0.523599rad ) ))', '0deg', {type:'angle', approx:0.1}); test_math_used('calc(asin(sin(3.14159 / 2 + 1 - 1) ))', '90deg', {type:'angle', approx:0.1}); test_math_used('calc(asin(sin(100grad) ))', '90deg', {type:'angle', approx:0.1}); test_math_used('calc(acos(cos(0 / 2 + 1 - 1) ))', '0deg', {type:'angle', approx:0.1}); @@ -66,4 +66,4 @@ test_math_used('atan2(1s, -1s)', '135deg', {type:'angle', approx:0.1}); test_math_used('atan2(1ms, -1ms)', '135deg', {type:'angle', approx:0.1}); -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt index 957334b..497cf5f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt
@@ -5,10 +5,10 @@ FAIL calc(log(e) ) should be used-value-equivalent to 1 assert_not_equals: calc(log(e) ) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(e - exp(1)) should be used-value-equivalent to 0 assert_not_equals: calc(e - exp(1)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(log( 1 + 1 + 2 /2 - 2) ) should be used-value-equivalent to 0 assert_not_equals: calc(log( 1 + 1 + 2 /2 - 2) ) isn't valid in 'transform'; got the default value instead. got disallowed value "none" -FAIL calc(log(1) + exp(0)) should be used-value-equivalent to 1 assert_not_equals: calc(log(1) + exp(0)) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" -FAIL calc(exp(log(1) + exp(0)*2)) should be used-value-equivalent to 7.4 assert_not_equals: calc(exp(log(1) + exp(0)*2)) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" -FAIL calc(log(log(1) + exp(0)*10)) should be used-value-equivalent to 2.3 assert_not_equals: calc(log(log(1) + exp(0)*10)) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" -FAIL calc(log(log(1) + exp(0)*20, 10)) should be used-value-equivalent to 1.3 assert_not_equals: calc(log(log(1) + exp(0)*20, 10)) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" +FAIL calc(log(1) + exp(0)) should be used-value-equivalent to 1 assert_not_equals: calc(log(1) + exp(0)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" +FAIL calc(exp(log(1) + exp(0)*2)) should be used-value-equivalent to 7.4 assert_not_equals: calc(exp(log(1) + exp(0)*2)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" +FAIL calc(log(log(1) + exp(0)*10)) should be used-value-equivalent to 2.3 assert_not_equals: calc(log(log(1) + exp(0)*10)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" +FAIL calc(log(log(1) + exp(0)*20, 10)) should be used-value-equivalent to 1.3 assert_not_equals: calc(log(log(1) + exp(0)*20, 10)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(log(e) / log(e) + exp(0)*2 * log(e)) should be used-value-equivalent to 3 assert_not_equals: calc(log(e) / log(e) + exp(0)*2 * log(e)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(log((1 + 1) /2) / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 2 assert_not_equals: calc(log((1 + 1) /2) / log(e) + exp(0*1)*2 * log(e)) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(log((3 + 1) /2, 2) / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 3 assert_not_equals: calc(log((3 + 1) /2, 2) / log(e) + exp(0*1)*2 * log(e)) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html index 8812253..3fa2400 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html +++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html
@@ -19,10 +19,10 @@ //General calculations test_math_used('calc(log( 1 + 1 + 2 /2 - 2) )', '0', {type:'number', approx:0.1}); -test_math_used('calc(log(1) + exp(0))', '1'), {type:'number', approx:0.1}; -test_math_used('calc(exp(log(1) + exp(0)*2))', '7.4'), {type:'number', approx:0.1}; -test_math_used('calc(log(log(1) + exp(0)*10))', '2.3'), {type:'number', approx:0.1}; -test_math_used('calc(log(log(1) + exp(0)*20, 10))', '1.3'), {type:'number', approx:0.1}; +test_math_used('calc(log(1) + exp(0))', '1', {type:'number', approx:0.1}); +test_math_used('calc(exp(log(1) + exp(0)*2))', '7.4', {type:'number', approx:0.1}); +test_math_used('calc(log(log(1) + exp(0)*10))', '2.3', {type:'number', approx:0.1}); +test_math_used('calc(log(log(1) + exp(0)*20, 10))', '1.3', {type:'number', approx:0.1}); test_math_used('calc(log(e) / log(e) + exp(0)*2 * log(e))', '3', {type:'number', approx:0.1}); test_math_used('calc(log((1 + 1) /2) / log(e) + exp(0*1)*2 * log(e))', '2', {type:'number', approx:0.1}); test_math_used('calc(log((3 + 1) /2, 2) / log(e) + exp(0*1)*2 * log(e))', '3', {type:'number', approx:0.1});
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-group.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-group.html index 034df41d..c3e9d669 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-group.html +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-group.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<html class=reftest-wait> +<html class="reftest-wait foo"> <title>View transitions: ensure :only-child is supported on view-transition-group</title> <link rel="help" href="https://github.com/WICG/view-transitions"> <link rel="author" href="mailto:khushalsagar@chromium.org"> @@ -8,6 +8,22 @@ <script src="/resources/testharnessreport.js"></script> <style> +::view-transition { + background-color: black; +} +html:only-child { + background-color: black; +} +:root:only-child { + background-color: black; +} +:only-child { + background-color: black; +} +.foo:only-child { + background-color: black; +} + ::view-transition-group(root) { background-color: blue; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-image-pair.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-image-pair.html index 830b373..93fcc0a5 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-image-pair.html +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-image-pair.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<html class=reftest-wait> +<html class="reftest-wait foo"> <title>View transitions: ensure :only-child is supported on view-transition-image-pair</title> <link rel="help" href="https://github.com/WICG/view-transitions"> <link rel="author" href="mailto:khushalsagar@chromium.org"> @@ -8,6 +8,22 @@ <script src="/resources/testharnessreport.js"></script> <style> +::view-transition { + background-color: black; +} +html:only-child { + background-color: black; +} +:root:only-child { + background-color: black; +} +:only-child { + background-color: black; +} +.foo:only-child { + background-color: black; +} + ::view-transition-image-pair(root):only-child { background-color: red; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-new.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-new.html index 2f8a7a40..62328f2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-new.html +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-new.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<html class=reftest-wait> +<html class="reftest-wait foo"> <title>View transitions: ensure :only-child is supported on view-transition-new</title> <link rel="help" href="https://github.com/WICG/view-transitions"> <link rel="author" href="mailto:khushalsagar@chromium.org"> @@ -8,6 +8,22 @@ <script src="/resources/testharnessreport.js"></script> <style> +::view-transition { + background-color: black; +} +html:only-child { + background-color: black; +} +:root:only-child { + background-color: black; +} +:only-child { + background-color: black; +} +.foo:only-child { + background-color: black; +} + ::view-transition-new(root) { background-color: blue; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-old.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-old.html index 4ca6fed..56dfa16 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-old.html +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-old.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<html class=reftest-wait> +<html class="reftest-wait foo"> <title>View transitions: ensure :only-child is supported on view-transition-old</title> <link rel="help" href="https://github.com/WICG/view-transitions"> <link rel="author" href="mailto:khushalsagar@chromium.org"> @@ -8,6 +8,22 @@ <script src="/resources/testharnessreport.js"></script> <style> +::view-transition { + background-color: black; +} +html:only-child { + background-color: black; +} +:root:only-child { + background-color: black; +} +:only-child { + background-color: black; +} +.foo:only-child { + background-color: black; +} + ::view-transition-old(root) { background-color: blue; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html new file mode 100644 index 0000000..0bf6d8b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html class="reftest-wait foo"> +<title>View transitions: ensure :only-child is supported on view-transition</title> +<link rel="help" href="https://github.com/WICG/view-transitions"> +<link rel="author" href="mailto:khushalsagar@chromium.org"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<style> +::view-transition { + background-color: red; +} + +html:only-child { + background-color: blue; +} + +:root:only-child { + background-color: blue; +} + +:only-child { + background-color: blue; +} + +.foo:only-child { + background-color: blue; +} +</style> + +<script> +promise_test(() => { + return new Promise(async (resolve, reject) => { + let transition = document.startViewTransition(); + transition.ready.then(() => { + let style = getComputedStyle( + document.documentElement, ":view-transition"); + if (style.backgroundColor == "rgb(255, 0, 0)") + resolve(); + else + reject(style.backgroundColor); + }); + }); +}, ":only-child is not supported on view-transition"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html.ini b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html.ini new file mode 100644 index 0000000..3a8bc30 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/only-child-on-root-element-with-view-transition.html.ini
@@ -0,0 +1,2 @@ +[only-child-on-root-element-with-view-transition.html] + expected: TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini new file mode 100644 index 0000000..3ef649a3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-window.html.ini
@@ -0,0 +1,36 @@ +[scroll-behavior-main-frame-window.html] + [Main frame with auto scroll-behavior ; scroll() with smooth behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scroll() with default behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scroll() with auto behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scroll() with smooth behavior] + expected: [FAIL, PASS] + + [Main frame with auto scroll-behavior ; scrollTo() with smooth behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollTo() with default behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollTo() with auto behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior] + expected: [FAIL, PASS] + + [Main frame with auto scroll-behavior ; scrollBy() with smooth behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollBy() with default behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollBy() with auto behavior] + expected: [FAIL, PASS] + + [Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/cssom-getPropertyValue-common-checks-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/cssom-getPropertyValue-common-checks-expected.txt index 36e1cf2..3139f189 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom/cssom-getPropertyValue-common-checks-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/cssom/cssom-getPropertyValue-common-checks-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. PASS All properties can serialize 'initial' -FAIL All properties (except 'all') can serialize their initial value (computed) assert_array_equals: lengths differ, expected array [] length 0, got [["background-repeat-x", ""], ["background-repeat-y", ""], ["grid", "none / none / none / row / auto / auto"], ["grid-template", "none / none / none"], ["page-orientation", ""], ["scroll-timeline", ""], ["size", ""], ["view-timeline", ""]] length 8 +FAIL All properties (except 'all') can serialize their initial value (computed) assert_array_equals: lengths differ, expected array [] length 0, got [["background-repeat-x", ""], ["background-repeat-y", ""], ["grid", "none / none / none / row / auto / auto"], ["grid-template", "none / none / none"], ["page-orientation", ""], ["size", ""]] length 6 FAIL All properties (except 'all') can serialize their initial value (specified) assert_array_equals: lengths differ, expected array [] length 0, got [["grid-column-gap", "normal", ""], ["grid-gap", "normal normal", ""], ["grid-row-gap", "normal", ""]] length 3 PASS All shorthands can serialize their longhands set to 'initial' FAIL All shorthands (except 'all') can serialize their longhands set to their initial value assert_array_equals: lengths differ, expected array [] length 0, got [["border", ""], ["grid-gap", ""]] length 2
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/match-media-parsing.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/match-media-parsing.html new file mode 100644 index 0000000..9d9aa3d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/match-media-parsing.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-syntax-3/#parse-comma-separated-list-of-component-values"> +<script type="text/javascript" src="/resources/testharness.js"></script> +<script type="text/javascript" src="/resources/testharnessreport.js"></script> + +<script> +function test_parsing(query, expected) { + test(() => { + const match = window.matchMedia(query); + assert_equals(match.media, expected) + }, "Test parsing '" + query + "' with matchMedia"); +} +test_parsing("", ""); +test_parsing(" ", ""); +test_parsing("all", "all"); +test_parsing(" all", "all"); +test_parsing(" all ", "all"); +test_parsing("all,all", "all, all"); +test_parsing(" all , all ", "all, all"); +test_parsing("(color)", "(color)"); +test_parsing("(color", "(color)"); +test_parsing(" (color)", "(color)"); +test_parsing(" ( color ) ", "(color)"); +test_parsing(" ( color ", "(color)"); +test_parsing("color)", "not all"); +test_parsing(" color)", "not all"); +test_parsing(" color ), ( color", "not all, (color)"); +test_parsing(" foo ", "foo"); +test_parsing(",", "not all, not all"); +test_parsing(" , ", "not all, not all"); +test_parsing(",,", "not all, not all, not all"); +test_parsing(" , , ", "not all, not all, not all"); +test_parsing(" foo,", "foo, not all"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/form-disabled-callback.html b/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/form-disabled-callback.html index 954c3f3..c61a771 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/form-disabled-callback.html +++ b/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/form-disabled-callback.html
@@ -110,5 +110,27 @@ container.innerHTML = '<fieldset disabled><my-control>'; assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); }, 'Upgrading an element with disabled content attribute'); + +test(() => { + const container = document.createElement('div'); + document.body.appendChild(container); + container.innerHTML = '<fieldset disabled><my-control></my-control></fieldset>'; + + const control = container.querySelector('my-control'); + control.setAttribute('disabled', ''); + control.removeAttribute('disabled'); + assert_array_equals(control.disabledHistory(), [true]); +}, 'Toggling "disabled" attribute on a custom element inside disabled <fieldset> does not trigger a callback'); + +test(() => { + const container = document.createElement('div'); + document.body.appendChild(container); + container.innerHTML = '<fieldset><my-control disabled></my-control></fieldset>'; + + const fieldset = container.firstElementChild; + fieldset.disabled = true; + fieldset.disabled = false; + assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); +}, 'Toggling "disabled" attribute on a <fieldset> does not trigger a callback on disabled custom element descendant'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scroll_support.js b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scroll_support.js index 847a9891..de23b6f8 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scroll_support.js +++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scroll_support.js
@@ -58,6 +58,17 @@ }); }); } + +// Please don't remove this. This is necessary for chromium-based browsers. +// This shouldn't be necessary if the test harness deferred running the tests +// until after paint holding. This can be a no-op on user-agents that do not +// have a separate compositor thread. +async function waitForCompositorReady() { + const animation = + document.body.animate({ opacity: [ 1, 1 ] }, {duration: 1 }); + return animation.finished; +} + function waitForNextFrame() { const startTime = performance.now(); return new Promise(resolve => { @@ -71,7 +82,6 @@ }); } - // TODO(crbug.com/1400399): Deprecate as frame rates may vary greatly in // different test environments. function waitForAnimationEnd(getValue) {
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html index e9be7c9..d51472fc 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html
@@ -45,8 +45,8 @@ window.addEventListener('scrollend', callback); } -async function createScrollendPromise(test) { - return waitForScrollendEvent(test, target_div).then(evt => { +async function createScrollendPromise(test, timeoutMs = 500) { + return waitForScrollendEvent(test, target_div, timeoutMs).then(evt => { assert_false(evt.cancelable, 'Event is not cancelable'); assert_false(evt.bubbles, 'Event targeting element does not bubble'); }); @@ -60,11 +60,21 @@ return; await resetTargetScrollState(t); - await waitForCompositorCommit(); + await waitForCompositorReady(); - const targetScrollendPromise = createScrollendPromise(t); + const timeout = 1000; // Because we have two pauses we need longer timeout + const targetScrollendPromise = createScrollendPromise(t, timeout); verifyNoScrollendOnDocument(t); + let scrollend_count = 0; + const scrollend_listener = () => { + scrollend_count += 1; + }; + target_div.addEventListener("scrollend", scrollend_listener); + t.add_cleanup(() => { + target_div.removeEventListener('scrollend', scrollend_listener); + }); + // Perform a touch drag on target div and wait for target_div to get // a scrollend event. await new test_driver.Actions() @@ -75,6 +85,9 @@ .pointerMove(0, -40, {origin: target_div}) // Drag up to move down. .addTick() .pause(200) // Prevent inertial scroll. + .pointerMove(0, -60, {origin: target_div}) + .addTick() + .pause(200) // Prevent inertial scroll. .pointerUp() .send(); @@ -82,6 +95,7 @@ assert_true(target_div.scrollTop > 0); await verifyScrollStopped(t, target_div); + assert_equals(scrollend_count, 1); }, 'Tests that the target_div gets scrollend event when touch dragging.'); promise_test(async (t) => { @@ -92,7 +106,7 @@ return; await resetTargetScrollState(t); - await waitForCompositorCommit(); + await waitForCompositorReady(); const targetScrollendPromise = createScrollendPromise(t); verifyNoScrollendOnDocument(t); @@ -122,7 +136,9 @@ if (scrollbar_width == 0) return; - resetTargetScrollState(t); + await resetTargetScrollState(t); + await waitForCompositorReady(); + const targetScrollendPromise = createScrollendPromise(t); verifyNoScrollendOnDocument(t); @@ -146,7 +162,9 @@ 'scrollbar thumb.'); promise_test(async (t) => { - resetTargetScrollState(t); + await resetTargetScrollState(t); + await waitForCompositorReady(); + const targetScrollendPromise = createScrollendPromise(t); verifyNoScrollendOnDocument(t); @@ -167,7 +185,7 @@ promise_test(async (t) => { await resetTargetScrollState(t); - await waitForCompositorCommit(); + await waitForCompositorReady(); verifyNoScrollendOnDocument(t); const targetScrollendPromise = createScrollendPromise(t);
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini index 6685bb02..961439d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini
@@ -1,14 +1,15 @@ [offscreencanvas.resize.html] [Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously.] expected: - if (product == "content_shell") and (os == "win") and (processor == "x86_64"): FAIL - if product == "chrome": FAIL + if (flag_specific == "") and (processor == "x86_64") and (os == "linux") and (product == "chrome"): FAIL + if (flag_specific == "") and (processor == "x86_64") and (os == "win"): FAIL + if flag_specific == "disable-site-isolation-trials": FAIL [Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas.] expected: FAIL [Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously.] expected: - if (processor == "x86_64") and (os == "linux") and (version == "Ubuntu 18.04"): [FAIL, PASS] - if (processor == "x86_64") and (os == "win"): PASS + if (flag_specific == "") and (os == "win") and (processor == "x86_64"): PASS + if flag_specific == "disable-site-isolation-trials": PASS FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/PRESUBMIT.py b/third_party/blink/web_tests/external/wpt/html/canvas/tools/PRESUBMIT.py new file mode 100644 index 0000000..048e96b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/PRESUBMIT.py
@@ -0,0 +1,22 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Presubmit script for t/b/web_tests/external/wpt/html/canvas/tools. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into depot_tools. +""" + +USE_PYTHON3 = True + + +def CommonChecks(input_api, output_api): + return input_api.canned_checks.RunPylint(input_api, output_api) + + +def CheckChangeOnUpload(input_api, output_api): + return CommonChecks(input_api, output_api) + + +def CheckChangeOnCommit(input_api, output_api): + return CommonChecks(input_api, output_api)
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentest.py b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentest.py index cb1f720..bca7b9e 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentest.py +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentest.py
@@ -1,6 +1,8 @@ from gentestutils import genTestUtils from gentestutilsunion import genTestUtils_union -genTestUtils('../element', '../element', 'templates.yaml', 'name2dir-canvas.yaml', False) -genTestUtils('../offscreen', '../offscreen', 'templates.yaml', 'name2dir-offscreen.yaml', True) -genTestUtils_union('templates-new.yaml', 'name2dir.yaml') \ No newline at end of file +genTestUtils('../element', '../element', 'templates.yaml', + 'name2dir-canvas.yaml', False) +genTestUtils('../offscreen', '../offscreen', 'templates.yaml', + 'name2dir-offscreen.yaml', True) +genTestUtils_union('templates-new.yaml', 'name2dir.yaml')
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutils.py b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutils.py index 1206aa9..2517568a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutils.py +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutils.py
@@ -6,19 +6,20 @@ # It has been adapted for use with the Web Platform Test Suite suite at # https://github.com/web-platform-tests/wpt/ # -# The original version had a number of now-removed features (multiple versions of -# each test case of varying verbosity, Mozilla mochitests, semi-automated test -# harness). It also had a different directory structure. +# The original version had a number of now-removed features (multiple versions +# of each test case of varying verbosity, Mozilla mochitests, semi-automated +# test harness). It also had a different directory structure. # To update or add test cases: # # * Modify the tests*.yaml files. -# 'name' is an arbitrary hierarchical name to help categorise tests. -# 'desc' is a rough description of what behaviour the test aims to test. -# 'code' is JavaScript code to execute, with some special commands starting with '@' -# 'expected' is what the final canvas output should be: a string 'green' or 'clear' -# (100x50 images in both cases), or a string 'size 100 50' (or any other size) -# followed by Python code using Pycairo to generate the image. +# - 'name' is an arbitrary hierarchical name to help categorise tests. +# - 'desc' is a rough description of what behaviour the test aims to test. +# - 'code' is JavaScript code to execute, with some special commands starting +# with '@' +# - 'expected' is what the final canvas output should be: a string 'green' or +# 'clear' (100x50 images in both cases), or a string 'size 100 50' (or any +# other size) followed by Python code using Pycairo to generate the image. # # * Run "./build.sh". # This requires a few Python modules which might not be ubiquitous. @@ -27,350 +28,327 @@ # # * Test the tests, add new ones to Git, remove deleted ones from Git, etc. -from __future__ import print_function +from typing import List, Mapping import re import codecs -import time +import importlib import os -import shutil import sys -import xml.dom.minidom -from xml.dom.minidom import Node try: - import cairocffi as cairo + import cairocffi as cairo # type: ignore except ImportError: import cairo try: - import syck as yaml # compatible and lots faster + # Compatible and lots faster. + import syck as yaml # type: ignore except ImportError: import yaml -def genTestUtils(TESTOUTPUTDIR, IMAGEOUTPUTDIR, TEMPLATEFILE, NAME2DIRFILE, ISOFFSCREENCANVAS): - MISCOUTPUTDIR = './output' +class Error(Exception): + """Base class for all exceptions raised by this module""" - def simpleEscapeJS(str): - return str.replace('\\', '\\\\').replace('"', '\\"') - def escapeJS(str): - str = simpleEscapeJS(str) - str = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', str) # kind of an ugly hack, for nicer failure-message output - return str +class InvalidTestDefinitionError(Error): + """Raised on invalid test definition.""" - def escapeHTML(str): - return str.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') - def expand_nonfinite(method, argstr, tail): - """ - >>> print expand_nonfinite('f', '<0 a>, <0 b>', ';') - f(a, 0); - f(0, b); - f(a, b); - >>> print expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';') - f(a, 0, 0); - f(0, b, 0); - f(0, c, 0); - f(0, 0, d); - f(a, b, 0); - f(a, b, d); - f(a, 0, d); - f(0, b, d); - """ - # argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually - # 'invalid' is Infinity/-Infinity/NaN) - args = [] - for arg in argstr.split(', '): - a = re.match('<(.*)>', arg).group(1) - args.append(a.split(' ')) - calls = [] - # Start with the valid argument list - call = [ args[j][0] for j in range(len(args)) ] - # For each argument alone, try setting it to all its invalid values: - for i in range(len(args)): - for a in args[i][1:]: - c2 = call[:] +def _simpleEscapeJS(string: str) -> str: + return string.replace('\\', '\\\\').replace('"', '\\"') + + +def _escapeJS(string: str) -> str: + string = _simpleEscapeJS(string) + # Kind of an ugly hack, for nicer failure-message output. + string = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', string) + return string + + +def _expand_nonfinite(method: str, argstr: str, tail: str) -> str: + """ + >>> print _expand_nonfinite('f', '<0 a>, <0 b>', ';') + f(a, 0); + f(0, b); + f(a, b); + >>> print _expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';') + f(a, 0, 0); + f(0, b, 0); + f(0, c, 0); + f(0, 0, d); + f(a, b, 0); + f(a, b, d); + f(a, 0, d); + f(0, b, d); + """ + # argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually + # 'invalid' is Infinity/-Infinity/NaN). + args = [] + for arg in argstr.split(', '): + match = re.match('<(.*)>', arg) + if match is None: + raise InvalidTestDefinitionError( + f"Expected arg to match format '<(.*)>', but was: {arg}") + a = match.group(1) + args.append(a.split(' ')) + calls = [] + # Start with the valid argument list. + call = [args[j][0] for j in range(len(args))] + # For each argument alone, try setting it to all its invalid values: + for i in range(len(args)): + for a in args[i][1:]: + c2 = call[:] + c2[i] = a + calls.append(c2) + # For all combinations of >= 2 arguments, try setting them to their + # first invalid values. (Don't do all invalid values, because the + # number of combinations explodes.) + def f(c: List[str], start: int, depth: int) -> None: + for i in range(start, len(args)): + if len(args[i]) > 1: + a = args[i][1] + c2 = c[:] c2[i] = a - calls.append(c2) - # For all combinations of >= 2 arguments, try setting them to their - # first invalid values. (Don't do all invalid values, because the - # number of combinations explodes.) - def f(c, start, depth): - for i in range(start, len(args)): - if len(args[i]) > 1: - a = args[i][1] - c2 = c[:] - c2[i] = a - if depth > 0: calls.append(c2) - f(c2, i+1, depth+1) - f(call, 0, 0) + if depth > 0: + calls.append(c2) + f(c2, i + 1, depth + 1) - return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls) + f(call, 0, 0) + return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls) + + +def _get_test_sub_dir(name: str, name_to_sub_dir: Mapping[str, str]) -> str: + for prefix in sorted(name_to_sub_dir.keys(), key=len, reverse=True): + if name.startswith(prefix): + return name_to_sub_dir[prefix] + raise InvalidTestDefinitionError( + 'Test "%s" has no defined target directory mapping' % name) + + +def _expand_test_code(code: str) -> str: + code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: + _expand_nonfinite(m.group(1), m.group(2), m.group(3)), + code) # Must come before '@assert throws'. + + code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', + r'_assertPixel(canvas, \1, \2);', code) + + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', + r'_assertPixelApprox(canvas, \1, \2, 2);', code) + + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', + r'_assertPixelApprox(canvas, \1, \2, \3);', code) + + code = re.sub(r'@assert throws (\S+_ERR) (.*);', + r'assert_throws_dom("\1", function() { \2; });', code) + + code = re.sub(r'@assert throws (\S+Error) (.*);', + r'assert_throws_js(\1, function() { \2; });', code) + + code = re.sub( + r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");' + % (m.group(1), m.group(2), _escapeJS(m.group(1)), _escapeJS(m.group(2)) + ), code) + + code = re.sub( + r'@assert (.*) !== (.*);', lambda m: + '_assertDifferent(%s, %s, "%s", "%s");' % (m.group(1), m.group( + 2), _escapeJS(m.group(1)), _escapeJS(m.group(2))), code) + + code = re.sub( + r'@assert (.*) =~ (.*);', lambda m: 'assert_regexp_match(%s, %s);' % ( + m.group(1), m.group(2)), code) + + code = re.sub( + r'@assert (.*);', lambda m: '_assert(%s, "%s");' % (m.group( + 1), _escapeJS(m.group(1))), code) + + code = re.sub(r' @moz-todo', '', code) + + code = re.sub(r'@moz-UniversalBrowserRead;', '', code) + + assert ('@' not in code) + + return code + + +def _generate_test(test: Mapping[str, str], templates: Mapping[str, str], + sub_dir: str, test_output_dir: str, image_output_dir: str, + is_offscreen_canvas: bool): + name = test['name'] + + if test.get('expected', '') == 'green' and re.search( + r'@assert pixel .* 0,0,0,0;', test['code']): + print('Probable incorrect pixel test in %s' % name) + + code = _expand_test_code(test['code']) + + expectation_html = '' + if 'expected' in test and test['expected'] is not None: + expected = test['expected'] + expected_img = None + if expected == 'green': + expected_img = '/images/green-100x50.png' + elif expected == 'clear': + expected_img = '/images/clear-100x50.png' + else: + if ';' in expected: + print('Found semicolon in %s' % name) + expected = re.sub( + r'^size (\d+) (\d+)', + r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)' + r'\ncr = cairo.Context(surface)', expected) + + expected += ("\nsurface.write_to_png('%s.png')\n" % + os.path.join(image_output_dir, sub_dir, name)) + eval(compile(expected, '<test %s>' % name, 'exec'), {}, + {'cairo': cairo}) + expected_img = '%s.png' % name + + if expected_img: + expectation_html = ( + '<p class="output expectedtext">Expected output:<p>' + '<img src="%s" class="output expected" id="expected" ' + 'alt="">' % expected_img) + + canvas = test.get('canvas', 'width="100" height="50"') + + notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else '' + + timeout = ('\n<meta name="timeout" content="%s">' % + test['timeout'] if 'timeout' in test else '') + + scripts = '' + for s in test.get('scripts', []): + scripts += '<script src="%s"></script>\n' % (s) + + images = '' + for src in test.get('images', []): + img_id = src.split('/')[-1] + if '/' not in src: + src = '../images/%s' % src + images += '<img src="%s" id="%s" class="resource">\n' % (src, img_id) + for src in test.get('svgimages', []): + img_id = src.split('/')[-1] + if '/' not in src: + src = '../images/%s' % src + images += ('<svg><image xlink:href="%s" id="%s" class="resource">' + '</svg>\n' % (src, img_id)) + images = images.replace('../images/', '/images/') + + fonts = '' + fonthack = '' + for font in test.get('fonts', []): + fonts += ('@font-face {\n font-family: %s;\n' + ' src: url("/fonts/%s.ttf");\n}\n' % (font, font)) + # Browsers require the font to actually be used in the page. + if test.get('fonthack', 1): + fonthack += ('<span style="font-family: %s; position: ' + 'absolute; visibility: hidden">A</span>\n' % font) + if fonts: + fonts = '<style>\n%s</style>\n' % fonts + + fallback = test.get('fallback', + '<p class="fallback">FAIL (fallback content)</p>') + + desc = test.get('desc', '') + escaped_desc = _simpleEscapeJS(desc) + + attributes = test.get('attributes', '') + if attributes: + context_args = "'2d', %s" % attributes.strip() + attributes = ', ' + attributes.strip() + else: + context_args = "'2d'" + + template_params = { + 'name': name, + 'desc': desc, + 'escaped_desc': escaped_desc, + 'notes': notes, + 'images': images, + 'fonts': fonts, + 'fonthack': fonthack, + 'timeout': timeout, + 'canvas': canvas, + 'expected': expectation_html, + 'code': code, + 'scripts': scripts, + 'fallback': fallback, + 'attributes': attributes, + 'context_args': context_args + } + + test_path = os.path.join(test_output_dir, sub_dir, name) + if 'manual' in test: + test_path += '-manual' + + if is_offscreen_canvas: + f = codecs.open(f'{test_path}.html', 'w', 'utf-8') + f.write(templates['w3coffscreencanvas'] % template_params) + timeout = ('// META: timeout=%s\n' % + test['timeout'] if 'timeout' in test else '') + template_params['timeout'] = timeout + f = codecs.open(f'{test_path}.worker.js', 'w', 'utf-8') + f.write(templates['w3cworker'] % template_params) + else: + f = codecs.open(f'{test_path}.html', 'w', 'utf-8') + f.write(templates['w3ccanvas'] % template_params) + + +def genTestUtils(TESTOUTPUTDIR: str, IMAGEOUTPUTDIR: str, TEMPLATEFILE: str, + NAME2DIRFILE: str, ISOFFSCREENCANVAS: bool) -> None: # Run with --test argument to run unit tests if len(sys.argv) > 1 and sys.argv[1] == '--test': - import doctest + doctest = importlib.import_module('doctest') doctest.testmod() sys.exit() - templates = yaml.safe_load(open(TEMPLATEFILE, "r").read()) - name_mapping = yaml.safe_load(open(NAME2DIRFILE, "r").read()) + templates = yaml.safe_load(open(TEMPLATEFILE, 'r').read()) + name_to_sub_dir = yaml.safe_load(open(NAME2DIRFILE, 'r').read()) tests = [] - test_yaml_directory = "yaml/element" + test_yaml_directory = 'yaml/element' if ISOFFSCREENCANVAS: - test_yaml_directory = "yaml/offscreen" + test_yaml_directory = 'yaml/offscreen' TESTSFILES = [ - os.path.join(test_yaml_directory, f) for f in os.listdir(test_yaml_directory) - if f.endswith(".yaml")] - for t in sum([ yaml.safe_load(open(f, "r").read()) for f in TESTSFILES], []): + os.path.join(test_yaml_directory, f) + for f in os.listdir(test_yaml_directory) if f.endswith('.yaml') + ] + for t in sum([yaml.safe_load(open(f, 'r').read()) for f in TESTSFILES], + []): if 'DISABLED' in t: continue if 'meta' in t: - eval(compile(t['meta'], '<meta test>', 'exec'), {}, {'tests':tests}) + eval(compile(t['meta'], '<meta test>', 'exec'), {}, + {'tests': tests}) else: tests.append(t) - category_names = [] - category_contents_direct = {} - category_contents_all = {} - - def backref_html(name): - backrefs = [] - c = '' - for p in name.split('.')[:-1]: - c += '.'+p - backrefs.append('<a href="index%s.html">%s</a>.' % (c, p)) - backrefs.append(name.split('.')[-1]) - return ''.join(backrefs) - - def make_flat_image(filename, w, h, r,g,b,a): - if os.path.exists('%s/%s' % (IMAGEOUTPUTDIR, filename)): - return filename - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) - cr = cairo.Context(surface) - cr.set_source_rgba(r, g, b, a) - cr.rectangle(0, 0, w, h) - cr.fill() - surface.write_to_png('%s/%s' % (IMAGEOUTPUTDIR, filename)) - return filename - - # Ensure the test output directories exist - testdirs = [TESTOUTPUTDIR, IMAGEOUTPUTDIR, MISCOUTPUTDIR] - for map_dir in set(name_mapping.values()): - testdirs.append("%s/%s" % (TESTOUTPUTDIR, map_dir)) + # Ensure the test output directories exist. + testdirs = [TESTOUTPUTDIR, IMAGEOUTPUTDIR] + for sub_dir in set(name_to_sub_dir.values()): + testdirs.append('%s/%s' % (TESTOUTPUTDIR, sub_dir)) for d in testdirs: - try: os.mkdir(d) - except: pass # ignore if it already exists - - used_images = {} - - def map_name(name): - mapped_name = None - for mn in sorted(name_mapping.keys(), key=len, reverse=True): - if name.startswith(mn): - mapped_name = "%s/%s" % (name_mapping[mn], name) - break - if not mapped_name: - print("LIKELY ERROR: %s has no defined target directory mapping" % name) - if 'manual' in test: - mapped_name += "-manual" - return mapped_name - - def expand_test_code(code): - code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: expand_nonfinite(m.group(1), m.group(2), m.group(3)), code) # must come before '@assert throws' - - code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', - r'_assertPixel(canvas, \1, \2);', - code) - - code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', - r'_assertPixelApprox(canvas, \1, \2, 2);', - code) - - code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', - r'_assertPixelApprox(canvas, \1, \2, \3);', - code) - - code = re.sub(r'@assert throws (\S+_ERR) (.*);', - r'assert_throws_dom("\1", function() { \2; });', - code) - - code = re.sub(r'@assert throws (\S+Error) (.*);', - r'assert_throws_js(\1, function() { \2; });', - code) - - code = re.sub(r'@assert (.*) === (.*);', - lambda m: '_assertSame(%s, %s, "%s", "%s");' - % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) - , code) - - code = re.sub(r'@assert (.*) !== (.*);', - lambda m: '_assertDifferent(%s, %s, "%s", "%s");' - % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) - , code) - - code = re.sub(r'@assert (.*) =~ (.*);', - lambda m: 'assert_regexp_match(%s, %s);' - % (m.group(1), m.group(2)) - , code) - - code = re.sub(r'@assert (.*);', - lambda m: '_assert(%s, "%s");' - % (m.group(1), escapeJS(m.group(1))) - , code) - - code = re.sub(r' @moz-todo', '', code) - - code = re.sub(r'@moz-UniversalBrowserRead;', - "" - , code) - - assert('@' not in code) - - return code + try: + os.mkdir(d) + except FileExistsError: + pass # Ignore if it already exists. used_tests = {} - for i in range(len(tests)): - test = tests[i] - + for test in tests: name = test['name'] - print("\r(%s)" % name, " "*32, "\t") + print('\r(%s)' % name, ' ' * 32, '\t') if name in used_tests: - print("Test %s is defined twice" % name) + print('Test %s is defined twice' % name) used_tests[name] = 1 - mapped_name = map_name(name) - if not mapped_name: - if ISOFFSCREENCANVAS: - continue - else: - mapped_name = name - - - cat_total = '' - for cat_part in [''] + name.split('.')[:-1]: - cat_total += cat_part+'.' - if not cat_total in category_names: category_names.append(cat_total) - category_contents_all.setdefault(cat_total, []).append(name) - category_contents_direct.setdefault(cat_total, []).append(name) - - if test.get('expected', '') == 'green' and re.search(r'@assert pixel .* 0,0,0,0;', test['code']): - print("Probable incorrect pixel test in %s" % name) - - code = expand_test_code(test['code']) - - expectation_html = '' - if 'expected' in test and test['expected'] is not None: - expected = test['expected'] - expected_img = None - if expected == 'green': - expected_img = "/images/green-100x50.png" - elif expected == 'clear': - expected_img = "/images/clear-100x50.png" - else: - if ';' in expected: - print("Found semicolon in %s" % name) - expected = re.sub(r'^size (\d+) (\d+)', - r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)\ncr = cairo.Context(surface)', - expected) - - if mapped_name.endswith("-manual"): - png_name = mapped_name[:-len("-manual")] - else: - png_name = mapped_name - expected += "\nsurface.write_to_png('%s/%s.png')\n" % (IMAGEOUTPUTDIR, png_name) - eval(compile(expected, '<test %s>' % test['name'], 'exec'), {}, {'cairo':cairo}) - expected_img = "%s.png" % name - - if expected_img: - expectation_html = ('<p class="output expectedtext">Expected output:' + - '<p><img src="%s" class="output expected" id="expected" alt="">' % (expected_img)) - - canvas = test.get('canvas', 'width="100" height="50"') - - prev = tests[i-1]['name'] if i != 0 else 'index' - next = tests[i+1]['name'] if i != len(tests)-1 else 'index' - - name_wrapped = name.replace('.', '.​') - - notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else '' - - timeout = '\n<meta name="timeout" content="%s">' % test['timeout'] if 'timeout' in test else '' - - scripts = '' - for s in test.get('scripts', []): - scripts += '<script src="%s"></script>\n' % (s) - - variants = test.get('script-variants', {}) - script_variants = [(v, '<script src="%s"></script>\n' % (s)) for (v, s) in variants.items()] - if not script_variants: - script_variants = [('', '')] - - images = '' - for i in test.get('images', []): - id = i.split('/')[-1] - if '/' not in i: - used_images[i] = 1 - i = '../images/%s' % i - images += '<img src="%s" id="%s" class="resource">\n' % (i,id) - for i in test.get('svgimages', []): - id = i.split('/')[-1] - if '/' not in i: - used_images[i] = 1 - i = '../images/%s' % i - images += '<svg><image xlink:href="%s" id="%s" class="resource"></svg>\n' % (i,id) - images = images.replace("../images/", "/images/") - - fonts = '' - fonthack = '' - for i in test.get('fonts', []): - fonts += '@font-face {\n font-family: %s;\n src: url("/fonts/%s.ttf");\n}\n' % (i, i) - # Browsers require the font to actually be used in the page - if test.get('fonthack', 1): - fonthack += '<span style="font-family: %s; position: absolute; visibility: hidden">A</span>\n' % i - if fonts: - fonts = '<style>\n%s</style>\n' % fonts - - fallback = test.get('fallback', '<p class="fallback">FAIL (fallback content)</p>') - - desc = test.get('desc', '') - escaped_desc = simpleEscapeJS(desc) - - attributes = test.get('attributes', '') - if attributes: - context_args = "'2d', %s" % attributes.strip() - attributes = ', ' + attributes.strip() - else: - context_args = "'2d'" - - for (variant, extra_script) in script_variants: - name_variant = '' if not variant else '.' + variant - - template_params = { - 'name':name + name_variant, - 'name_wrapped':name_wrapped, 'backrefs':backref_html(name), - 'mapped_name':mapped_name, - 'desc':desc, 'escaped_desc':escaped_desc, - 'prev':prev, 'next':next, 'notes':notes, 'images':images, - 'fonts':fonts, 'fonthack':fonthack, 'timeout': timeout, - 'canvas':canvas, 'expected':expectation_html, 'code':code, - 'scripts':scripts + extra_script, - 'fallback':fallback, 'attributes':attributes, - 'context_args': context_args - } - if ISOFFSCREENCANVAS: - f = codecs.open('%s/%s%s.html' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f.write(templates['w3coffscreencanvas'] % template_params) - timeout = '// META: timeout=%s\n' % test['timeout'] if 'timeout' in test else '' - template_params['timeout'] = timeout - f = codecs.open('%s/%s%s.worker.js' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f.write(templates['w3cworker'] % template_params) - else: - f = codecs.open('%s/%s%s.html' % (TESTOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f.write(templates['w3ccanvas'] % template_params) + sub_dir = _get_test_sub_dir(name, name_to_sub_dir) + _generate_test(test, templates, sub_dir, TESTOUTPUTDIR, IMAGEOUTPUTDIR, + ISOFFSCREENCANVAS) print()
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutilsunion.py b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutilsunion.py index c6fba84..4c65d68 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutilsunion.py +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/gentestutilsunion.py
@@ -6,19 +6,20 @@ # It has been adapted for use with the Web Platform Test Suite suite at # https://github.com/web-platform-tests/wpt/ # -# The original version had a number of now-removed features (multiple versions of -# each test case of varying verbosity, Mozilla mochitests, semi-automated test -# harness). It also had a different directory structure. +# The original version had a number of now-removed features (multiple versions +# of each test case of varying verbosity, Mozilla mochitests, semi-automated +# test harness). It also had a different directory structure. # To update or add test cases: # # * Modify the tests*.yaml files. -# 'name' is an arbitrary hierarchical name to help categorise tests. -# 'desc' is a rough description of what behaviour the test aims to test. -# 'code' is JavaScript code to execute, with some special commands starting with '@' -# 'expected' is what the final canvas output should be: a string 'green' or 'clear' -# (100x50 images in both cases), or a string 'size 100 50' (or any other size) -# followed by Python code using Pycairo to generate the image. +# - 'name' is an arbitrary hierarchical name to help categorise tests. +# - 'desc' is a rough description of what behaviour the test aims to test. +# - 'code' is JavaScript code to execute, with some special commands starting +# with '@'. +# - 'expected' is what the final canvas output should be: a string 'green' or +# 'clear' (100x50 images in both cases), or a string 'size 100 50' (or any +# other size) followed by Python code using Pycairo to generate the image. # # * Run "./build.sh". # This requires a few Python modules which might not be ubiquitous. @@ -27,361 +28,387 @@ # # * Test the tests, add new ones to Git, remove deleted ones from Git, etc. -from __future__ import print_function +from typing import List, Mapping import re import codecs -import time +import collections +import dataclasses +import enum +import importlib import os -import shutil import sys -import xml.dom.minidom -from xml.dom.minidom import Node try: - import cairocffi as cairo + import cairocffi as cairo # type: ignore except ImportError: import cairo try: - import syck as yaml # compatible and lots faster + # Compatible and lots faster. + import syck as yaml # type: ignore except ImportError: import yaml -def genTestUtils_union(TEMPLATEFILE, NAME2DIRFILE): + +class Error(Exception): + """Base class for all exceptions raised by this module""" + + +class InvalidTestDefinitionError(Error): + """Raised on invalid test definition.""" + + +def _simpleEscapeJS(string: str) -> str: + return string.replace('\\', '\\\\').replace('"', '\\"') + + +def _escapeJS(string: str) -> str: + string = _simpleEscapeJS(string) + # Kind of an ugly hack, for nicer failure-message output. + string = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', string) + return string + + +def _expand_nonfinite(method: str, argstr: str, tail: str) -> str: + """ + >>> print _expand_nonfinite('f', '<0 a>, <0 b>', ';') + f(a, 0); + f(0, b); + f(a, b); + >>> print _expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';') + f(a, 0, 0); + f(0, b, 0); + f(0, c, 0); + f(0, 0, d); + f(a, b, 0); + f(a, b, d); + f(a, 0, d); + f(0, b, d); + """ + # argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually + # 'invalid' is Infinity/-Infinity/NaN). + args = [] + for arg in argstr.split(', '): + match = re.match('<(.*)>', arg) + if match is None: + raise InvalidTestDefinitionError( + f"Expected arg to match format '<(.*)>', but was: {arg}") + a = match.group(1) + args.append(a.split(' ')) + calls = [] + # Start with the valid argument list. + call = [args[j][0] for j in range(len(args))] + # For each argument alone, try setting it to all its invalid values: + for i in range(len(args)): + for a in args[i][1:]: + c2 = call[:] + c2[i] = a + calls.append(c2) + # For all combinations of >= 2 arguments, try setting them to their + # first invalid values. (Don't do all invalid values, because the + # number of combinations explodes.) + def f(c: List[str], start: int, depth: int) -> None: + for i in range(start, len(args)): + if len(args[i]) > 1: + a = args[i][1] + c2 = c[:] + c2[i] = a + if depth > 0: + calls.append(c2) + f(c2, i + 1, depth + 1) + + f(call, 0, 0) + + return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls) + + +def _get_test_sub_dir(name: str, name_to_sub_dir: Mapping[str, str]) -> str: + for prefix in sorted(name_to_sub_dir.keys(), key=len, reverse=True): + if name.startswith(prefix): + return name_to_sub_dir[prefix] + raise InvalidTestDefinitionError( + 'Test "%s" has no defined target directory mapping' % name) + + +def _expand_test_code(code: str) -> str: + code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: + _expand_nonfinite(m.group(1), m.group(2), m.group(3)), + code) # Must come before '@assert throws'. + + code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', + r'_assertPixel(canvas, \1, \2);', code) + + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', + r'_assertPixelApprox(canvas, \1, \2, 2);', code) + + code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', + r'_assertPixelApprox(canvas, \1, \2, \3);', code) + + code = re.sub(r'@assert throws (\S+_ERR) (.*);', + r'assert_throws_dom("\1", function() { \2; });', code) + + code = re.sub(r'@assert throws (\S+Error) (.*);', + r'assert_throws_js(\1, function() { \2; });', code) + + code = re.sub( + r'@assert (.*) === (.*);', lambda m: '_assertSame(%s, %s, "%s", "%s");' + % (m.group(1), m.group(2), _escapeJS(m.group(1)), _escapeJS(m.group(2)) + ), code) + + code = re.sub( + r'@assert (.*) !== (.*);', lambda m: + '_assertDifferent(%s, %s, "%s", "%s");' % (m.group(1), m.group( + 2), _escapeJS(m.group(1)), _escapeJS(m.group(2))), code) + + code = re.sub( + r'@assert (.*) =~ (.*);', lambda m: 'assert_regexp_match(%s, %s);' % ( + m.group(1), m.group(2)), code) + + code = re.sub( + r'@assert (.*);', lambda m: '_assert(%s, "%s");' % (m.group( + 1), _escapeJS(m.group(1))), code) + + code = re.sub(r' @moz-todo', '', code) + + code = re.sub(r'@moz-UniversalBrowserRead;', '', code) + + assert ('@' not in code) + + return code + + +class CanvasType(str, enum.Enum): + HTML_CANVAS = 'htmlcanvas' + OFFSCREEN_CANVAS = 'offscreencanvas' + + +def _get_enabled_canvas_types(test: Mapping[str, str]) -> List[CanvasType]: + return [CanvasType(t.lower()) for t in test.get('canvasType', CanvasType)] + + +@dataclasses.dataclass +class TestConfig: + out_dir: str + image_out_dir: str + enabled: bool + + +def _generate_test(test: Mapping[str, str], templates: Mapping[str, str], + sub_dir: str, html_canvas_cfg: TestConfig, + offscreen_canvas_cfg: TestConfig) -> None: + name = test['name'] + + if test.get('expected', '') == 'green' and re.search( + r'@assert pixel .* 0,0,0,0;', test['code']): + print('Probable incorrect pixel test in %s' % name) + + code_canvas = _expand_test_code(test['code']).strip() + + expectation_html = '' + if 'expected' in test and test['expected'] is not None: + expected = test['expected'] + expected_img = None + if expected == 'green': + expected_img = '/images/green-100x50.png' + elif expected == 'clear': + expected_img = '/images/clear-100x50.png' + else: + if ';' in expected: + print('Found semicolon in %s' % name) + expected = re.sub( + r'^size (\d+) (\d+)', + r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)' + r'\ncr = cairo.Context(surface)', expected) + + expected_canvas = ( + expected + "\nsurface.write_to_png('%s.png')\n" % + os.path.join(html_canvas_cfg.image_out_dir, sub_dir, name)) + eval(compile(expected_canvas, '<test %s>' % name, 'exec'), {}, + {'cairo': cairo}) + + expected_offscreencanvas = ( + expected + "\nsurface.write_to_png('%s.png')\n" % os.path.join( + offscreen_canvas_cfg.image_out_dir, sub_dir, name)) + eval(compile(expected_offscreencanvas, '<test %s>' % name, 'exec'), + {}, {'cairo': cairo}) + + expected_img = '%s.png' % name + + if expected_img: + expectation_html = ( + '<p class="output expectedtext">Expected output:<p>' + '<img src="%s" class="output expected" id="expected" ' + 'alt="">' % expected_img) + + canvas = test.get('canvas', 'width="100" height="50"') + + notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else '' + + timeout = ('\n<meta name="timeout" content="%s">' % + test['timeout'] if 'timeout' in test else '') + + scripts = '' + for s in test.get('scripts', []): + scripts += '<script src="%s"></script>\n' % (s) + + images = '' + for src in test.get('images', []): + img_id = src.split('/')[-1] + if '/' not in src: + src = '../images/%s' % src + images += '<img src="%s" id="%s" class="resource">\n' % (src, img_id) + for src in test.get('svgimages', []): + img_id = src.split('/')[-1] + if '/' not in src: + src = '../images/%s' % src + images += ('<svg><image xlink:href="%s" id="%s" class="resource">' + '</svg>\n' % (src, img_id)) + images = images.replace('../images/', '/images/') + + fonts = '' + fonthack = '' + for font in test.get('fonts', []): + fonts += ('@font-face {\n font-family: %s;\n' + ' src: url("/fonts/%s.ttf");\n}\n' % (font, font)) + # Browsers require the font to actually be used in the page. + if test.get('fonthack', 1): + fonthack += ('<span style="font-family: %s; position: ' + 'absolute; visibility: hidden">A</span>\n' % font) + if fonts: + fonts = '<style>\n%s</style>\n' % fonts + + fallback = test.get('fallback', + '<p class="fallback">FAIL (fallback content)</p>') + + desc = test.get('desc', '') + escaped_desc = _simpleEscapeJS(desc) + + attributes = test.get('attributes', '') + if attributes: + context_args = "'2d', %s" % attributes.strip() + attributes = ', ' + attributes.strip() + else: + context_args = "'2d'" + + template_params = { + 'name': name, + 'desc': desc, + 'escaped_desc': escaped_desc, + 'notes': notes, + 'images': images, + 'fonts': fonts, + 'fonthack': fonthack, + 'timeout': timeout, + 'canvas': canvas, + 'expected': expectation_html, + 'code': code_canvas, + 'scripts': scripts, + 'fallback': fallback, + 'attributes': attributes, + 'context_args': context_args + } + + canvas_path = os.path.join(html_canvas_cfg.out_dir, sub_dir, name) + offscreen_path = os.path.join(offscreen_canvas_cfg.out_dir, sub_dir, name) + if 'manual' in test: + canvas_path += '-manual' + offscreen_path += '-manual' + + # Create test cases for canvas and offscreencanvas. + if html_canvas_cfg.enabled: + f = codecs.open(f'{canvas_path}.html', 'w', 'utf-8') + f.write(templates['w3ccanvas'] % template_params) + if offscreen_canvas_cfg.enabled: + f_html = codecs.open(f'{offscreen_path}.html', 'w', 'utf-8') + f_worker = codecs.open(f'{offscreen_path}.worker.js', 'w', 'utf-8') + if ('then(t_pass, t_fail);' in code_canvas): + temp_offscreen = templates['w3coffscreencanvas'].replace( + 't.done();\n', '') + temp_worker = templates['w3cworker'].replace('t.done();\n', '') + f_html.write(temp_offscreen % template_params) + timeout = ('// META: timeout=%s\n' % + test['timeout'] if 'timeout' in test else '') + template_params['timeout'] = timeout + f_worker.write(temp_worker % template_params) + else: + f_html.write(templates['w3coffscreencanvas'] % template_params) + timeout = ('// META: timeout=%s\n' % + test['timeout'] if 'timeout' in test else '') + template_params['timeout'] = timeout + f_worker.write(templates['w3cworker'] % template_params) + + +def genTestUtils_union(TEMPLATEFILE: str, NAME2DIRFILE: str) -> None: CANVASOUTPUTDIR = '../element' CANVASIMAGEOUTPUTDIR = '../element' OFFSCREENCANVASOUTPUTDIR = '../offscreen' OFFSCREENCANVASIMAGEOUTPUTDIR = '../offscreen' - MISCOUTPUTDIR = './output' - def simpleEscapeJS(str): - return str.replace('\\', '\\\\').replace('"', '\\"') - - def escapeJS(str): - str = simpleEscapeJS(str) - str = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', str) # kind of an ugly hack, for nicer failure-message output - return str - - def escapeHTML(str): - return str.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') - - def expand_nonfinite(method, argstr, tail): - """ - >>> print expand_nonfinite('f', '<0 a>, <0 b>', ';') - f(a, 0); - f(0, b); - f(a, b); - >>> print expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';') - f(a, 0, 0); - f(0, b, 0); - f(0, c, 0); - f(0, 0, d); - f(a, b, 0); - f(a, b, d); - f(a, 0, d); - f(0, b, d); - """ - # argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually - # 'invalid' is Infinity/-Infinity/NaN) - args = [] - for arg in argstr.split(', '): - a = re.match('<(.*)>', arg).group(1) - args.append(a.split(' ')) - calls = [] - # Start with the valid argument list - call = [ args[j][0] for j in range(len(args)) ] - # For each argument alone, try setting it to all its invalid values: - for i in range(len(args)): - for a in args[i][1:]: - c2 = call[:] - c2[i] = a - calls.append(c2) - # For all combinations of >= 2 arguments, try setting them to their - # first invalid values. (Don't do all invalid values, because the - # number of combinations explodes.) - def f(c, start, depth): - for i in range(start, len(args)): - if len(args[i]) > 1: - a = args[i][1] - c2 = c[:] - c2[i] = a - if depth > 0: calls.append(c2) - f(c2, i+1, depth+1) - f(call, 0, 0) - - return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls) - - # Run with --test argument to run unit tests + # Run with --test argument to run unit tests. if len(sys.argv) > 1 and sys.argv[1] == '--test': - import doctest + doctest = importlib.import_module('doctest') doctest.testmod() sys.exit() - templates = yaml.safe_load(open(TEMPLATEFILE, "r").read()) - name_mapping = yaml.safe_load(open(NAME2DIRFILE, "r").read()) + templates = yaml.safe_load(open(TEMPLATEFILE, 'r').read()) + name_to_sub_dir = yaml.safe_load(open(NAME2DIRFILE, 'r').read()) tests = [] - test_yaml_directory = "yaml-new" + test_yaml_directory = 'yaml-new' TESTSFILES = [ - os.path.join(test_yaml_directory, f) for f in os.listdir(test_yaml_directory) - if f.endswith(".yaml")] - for t in sum([ yaml.safe_load(open(f, "r").read()) for f in TESTSFILES], []): + os.path.join(test_yaml_directory, f) + for f in os.listdir(test_yaml_directory) if f.endswith('.yaml') + ] + for t in sum([yaml.safe_load(open(f, 'r').read()) for f in TESTSFILES], + []): if 'DISABLED' in t: continue if 'meta' in t: - eval(compile(t['meta'], '<meta test>', 'exec'), {}, {'tests':tests}) + eval(compile(t['meta'], '<meta test>', 'exec'), {}, + {'tests': tests}) else: tests.append(t) - category_names = [] - category_contents_direct = {} - category_contents_all = {} - - def backref_html(name): - backrefs = [] - c = '' - for p in name.split('.')[:-1]: - c += '.'+p - backrefs.append('<a href="index%s.html">%s</a>.' % (c, p)) - backrefs.append(name.split('.')[-1]) - return ''.join(backrefs) - - # Ensure the test output directories exist - testdirs = [CANVASOUTPUTDIR, OFFSCREENCANVASOUTPUTDIR, CANVASIMAGEOUTPUTDIR, OFFSCREENCANVASIMAGEOUTPUTDIR, MISCOUTPUTDIR] - for map_dir in set(name_mapping.values()): - testdirs.append("%s/%s" % (CANVASOUTPUTDIR, map_dir)) - testdirs.append("%s/%s" % (OFFSCREENCANVASOUTPUTDIR, map_dir)) + # Ensure the test output directories exist. + testdirs = [ + CANVASOUTPUTDIR, OFFSCREENCANVASOUTPUTDIR, CANVASIMAGEOUTPUTDIR, + OFFSCREENCANVASIMAGEOUTPUTDIR + ] + for sub_dir in set(name_to_sub_dir.values()): + testdirs.append('%s/%s' % (CANVASOUTPUTDIR, sub_dir)) + testdirs.append('%s/%s' % (OFFSCREENCANVASOUTPUTDIR, sub_dir)) for d in testdirs: - try: os.mkdir(d) - except: pass # ignore if it already exists + try: + os.mkdir(d) + except FileExistsError: + pass # Ignore if it already exists, - used_images = {} - - def map_name(name): - mapped_name = None - for mn in sorted(name_mapping.keys(), key=len, reverse=True): - if name.startswith(mn): - mapped_name = "%s/%s" % (name_mapping[mn], name) - break - if not mapped_name: - print("LIKELY ERROR: %s has no defined target directory mapping" % name) - if 'manual' in test: - mapped_name += "-manual" - return mapped_name - - def expand_test_code(code): - code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: expand_nonfinite(m.group(1), m.group(2), m.group(3)), code) # must come before '@assert throws' - - code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);', - r'_assertPixel(canvas, \1, \2);', - code) - - code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);', - r'_assertPixelApprox(canvas, \1, \2, 2);', - code) - - code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);', - r'_assertPixelApprox(canvas, \1, \2, \3);', - code) - - code = re.sub(r'@assert throws (\S+_ERR) (.*);', - r'assert_throws_dom("\1", function() { \2; });', - code) - - code = re.sub(r'@assert throws (\S+Error) (.*);', - r'assert_throws_js(\1, function() { \2; });', - code) - - code = re.sub(r'@assert (.*) === (.*);', - lambda m: '_assertSame(%s, %s, "%s", "%s");' - % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) - , code) - - code = re.sub(r'@assert (.*) !== (.*);', - lambda m: '_assertDifferent(%s, %s, "%s", "%s");' - % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2))) - , code) - - code = re.sub(r'@assert (.*) =~ (.*);', - lambda m: 'assert_regexp_match(%s, %s);' - % (m.group(1), m.group(2)) - , code) - - code = re.sub(r'@assert (.*);', - lambda m: '_assert(%s, "%s");' - % (m.group(1), escapeJS(m.group(1))) - , code) - - code = re.sub(r' @moz-todo', '', code) - - code = re.sub(r'@moz-UniversalBrowserRead;', - "" - , code) - - assert('@' not in code) - - return code - - used_tests = {} - for i in range(len(tests)): - test = tests[i] - HTMLCanvas_test = True - OffscreenCanvas_test = True - if test.get('canvasType', []): - HTMLCanvas_test = False - OffscreenCanvas_test = False - for type in test.get('canvasType'): - if type.lower() == 'htmlcanvas': - HTMLCanvas_test = True - elif type.lower() == 'offscreencanvas': - OffscreenCanvas_test = True - + used_tests = collections.defaultdict(set) + for test in tests: name = test['name'] - print("\r(%s)" % name, " "*32, "\t") + print('\r(%s)' % name, ' ' * 32, '\t') - if name in used_tests: - print("Test %s is defined twice" % name) - used_tests[name] = 1 + enabled_canvas_types = _get_enabled_canvas_types(test) - mapped_name = map_name(name) - if not mapped_name: - mapped_name = name + already_tested = used_tests[name].intersection(enabled_canvas_types) + if already_tested: + raise InvalidTestDefinitionError( + f'Test {name} is defined twice for types {already_tested}') + used_tests[name].update(enabled_canvas_types) + sub_dir = _get_test_sub_dir(name, name_to_sub_dir) + _generate_test( + test, + templates, + sub_dir, + html_canvas_cfg=TestConfig( + out_dir=CANVASOUTPUTDIR, + image_out_dir=CANVASIMAGEOUTPUTDIR, + enabled=CanvasType.HTML_CANVAS in enabled_canvas_types), + offscreen_canvas_cfg=TestConfig( + out_dir=OFFSCREENCANVASOUTPUTDIR, + image_out_dir=OFFSCREENCANVASIMAGEOUTPUTDIR, + enabled=CanvasType.OFFSCREEN_CANVAS in enabled_canvas_types)) - cat_total = '' - for cat_part in [''] + name.split('.')[:-1]: - cat_total += cat_part+'.' - if not cat_total in category_names: category_names.append(cat_total) - category_contents_all.setdefault(cat_total, []).append(name) - category_contents_direct.setdefault(cat_total, []).append(name) - - if test.get('expected', '') == 'green' and re.search(r'@assert pixel .* 0,0,0,0;', test['code']): - print("Probable incorrect pixel test in %s" % name) - - code_canvas = expand_test_code(test['code']).strip() - - expectation_html = '' - if 'expected' in test and test['expected'] is not None: - expected = test['expected'] - expected_img = None - if expected == 'green': - expected_img = "/images/green-100x50.png" - elif expected == 'clear': - expected_img = "/images/clear-100x50.png" - else: - if ';' in expected: - print("Found semicolon in %s" % name) - expected = re.sub(r'^size (\d+) (\d+)', - r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)\ncr = cairo.Context(surface)', - expected) - - if mapped_name.endswith("-manual"): - png_name = mapped_name[:-len("-manual")] - else: - png_name = mapped_name - expected_canvas = expected + "\nsurface.write_to_png('%s/%s.png')\n" % (CANVASIMAGEOUTPUTDIR, png_name) - eval(compile(expected_canvas, '<test %s>' % test['name'], 'exec'), {}, {'cairo':cairo}) - - expected_offscreencanvas = expected + "\nsurface.write_to_png('%s/%s.png')\n" % (OFFSCREENCANVASIMAGEOUTPUTDIR, png_name) - eval(compile(expected_offscreencanvas, '<test %s>' % test['name'], 'exec'), {}, {'cairo':cairo}) - - expected_img = "%s.png" % name - - if expected_img: - expectation_html = ('<p class="output expectedtext">Expected output:' + - '<p><img src="%s" class="output expected" id="expected" alt="">' % (expected_img)) - - canvas = test.get('canvas', 'width="100" height="50"') - - prev = tests[i-1]['name'] if i != 0 else 'index' - next = tests[i+1]['name'] if i != len(tests)-1 else 'index' - - name_wrapped = name.replace('.', '.​') - - notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else '' - - timeout = '\n<meta name="timeout" content="%s">' % test['timeout'] if 'timeout' in test else '' - - scripts = '' - for s in test.get('scripts', []): - scripts += '<script src="%s"></script>\n' % (s) - - variants = test.get('script-variants', {}) - script_variants = [(v, '<script src="%s"></script>\n' % (s)) for (v, s) in variants.items()] - if not script_variants: - script_variants = [('', '')] - - images = '' - for i in test.get('images', []): - id = i.split('/')[-1] - if '/' not in i: - used_images[i] = 1 - i = '../images/%s' % i - images += '<img src="%s" id="%s" class="resource">\n' % (i,id) - for i in test.get('svgimages', []): - id = i.split('/')[-1] - if '/' not in i: - used_images[i] = 1 - i = '../images/%s' % i - images += '<svg><image xlink:href="%s" id="%s" class="resource"></svg>\n' % (i,id) - images = images.replace("../images/", "/images/") - - fonts = '' - fonthack = '' - for i in test.get('fonts', []): - fonts += '@font-face {\n font-family: %s;\n src: url("/fonts/%s.ttf");\n}\n' % (i, i) - # Browsers require the font to actually be used in the page - if test.get('fonthack', 1): - fonthack += '<span style="font-family: %s; position: absolute; visibility: hidden">A</span>\n' % i - if fonts: - fonts = '<style>\n%s</style>\n' % fonts - - fallback = test.get('fallback', '<p class="fallback">FAIL (fallback content)</p>') - - desc = test.get('desc', '') - escaped_desc = simpleEscapeJS(desc) - - attributes = test.get('attributes', '') - if attributes: - context_args = "'2d', %s" % attributes.strip() - attributes = ', ' + attributes.strip() - else: - context_args = "'2d'" - - for (variant, extra_script) in script_variants: - name_variant = '' if not variant else '.' + variant - - template_params = { - 'name':name + name_variant, - 'name_wrapped':name_wrapped, 'backrefs':backref_html(name), - 'mapped_name':mapped_name, - 'desc':desc, 'escaped_desc':escaped_desc, - 'prev':prev, 'next':next, 'notes':notes, 'images':images, - 'fonts':fonts, 'fonthack':fonthack, 'timeout': timeout, - 'canvas':canvas, 'expected':expectation_html, 'code':code_canvas, - 'scripts':scripts + extra_script, - 'fallback':fallback, 'attributes':attributes, - 'context_args': context_args - } - - # Create test cases for canvas and offscreencanvas. - if HTMLCanvas_test: - f = codecs.open('%s/%s%s.html' % (CANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f.write(templates['w3ccanvas'] % template_params) - if OffscreenCanvas_test: - f_html = codecs.open('%s/%s%s.html' % (OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - f_worker = codecs.open('%s/%s%s.worker.js' % (OFFSCREENCANVASOUTPUTDIR, mapped_name, name_variant), 'w', 'utf-8') - if ("then(t_pass, t_fail);" in code_canvas): - temp_offscreen = templates['w3coffscreencanvas'].replace("t.done();\n", "") - temp_worker = templates['w3cworker'].replace("t.done();\n", "") - f_html.write(temp_offscreen % template_params) - timeout = '// META: timeout=%s\n' % test['timeout'] if 'timeout' in test else '' - template_params['timeout'] = timeout - f_worker.write(temp_worker % template_params) - else: - f_html.write(templates['w3coffscreencanvas'] % template_params) - timeout = '// META: timeout=%s\n' % test['timeout'] if 'timeout' in test else '' - template_params['timeout'] = timeout - f_worker.write(templates['w3cworker'] % template_params) print()
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml index 83de881..e263bf0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml
@@ -424,6 +424,7 @@ - name: 2d.drawImage.zerocanvas desc: drawImage with zero-sized canvas as the source shoud throw exception + canvasType: ['HTMLCanvas'] code: | var canvas2 = document.createElement('canvas'); canvas2.width = 0; @@ -523,6 +524,7 @@ expected: green - name: 2d.drawImage.clip + canvasType: ['HTMLCanvas'] images: - red.png code: | @@ -1330,4 +1332,3 @@ @assert pixel 50,25 == 0,255,0,255; }, t_fail); }).then(t_pass, t_fail); -
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html.ini index dd5c96b2..b646d8f 100644 --- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-other_coop-ro_cross-origin.https.html.ini
@@ -1,3 +1,5 @@ [access-from-coop-page-to-other_coop-ro_cross-origin.https.html] expected: - if product == "chrome": ERROR + if product == "chrome": [OK, ERROR] + [access-from-coop-page-to-other (COOP-RO)] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html.ini index e2fdfcf..9371370 100644 --- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-get.https.html.ini
@@ -1,6 +1,6 @@ [property-opener-get.https.html] expected: - if (product == "chrome") and (processor == "x86"): ERROR + if product == "chrome": [ERROR, OK] [cross-origin > w => w.opener] expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini index 80c54e425..8103815e 100644 --- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini
@@ -1,6 +1,6 @@ [property-postmessage-1.https.html] expected: - if (product == "chrome") and (processor == "x86"): ERROR + if product == "chrome": [ERROR, OK] [cross-origin > w => w.postMessage("", "")] expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini new file mode 100644 index 0000000..0d2530b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini
@@ -0,0 +1,3 @@ +[remove-attr-script-keeps-blocking.tentative.html] + [Rendering is blocked before render-blocking resources are loaded] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini index 35055d35..d55b004b 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
@@ -1,5 +1,7 @@ [sandbox-top-navigation-child-special-cases.tentative.sub.window.html] expected: - if (product == "content_shell") and (flag_specific == "") and (os == "win"): [OK, TIMEOUT] - if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [TIMEOUT, OK] - if product == "chrome": ERROR + if (os == "linux") and (flag_specific == "") and (product == "content_shell") and (version == "Ubuntu 18.04"): [TIMEOUT, OK] + if (os == "linux") and (flag_specific == "") and (product == "chrome"): ERROR + if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): TIMEOUT + [Allow top with user activation + user activation] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-target-element-disabled.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-target-element-disabled.tentative.html new file mode 100644 index 0000000..3d139c5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-target-element-disabled.tentative.html
@@ -0,0 +1,126 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://github.com/whatwg/html/pull/8221#discussion_r1049379113"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id=outerpopover popover=auto> + <button popovertoggletarget=innerpopover disabled>toggle popover</button> +</div> +<div id=innerpopover popover=auto>popover</div> +<script> +test(() => { + outerpopover.showPopover(); + innerpopover.showPopover(); + assert_true(innerpopover.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_false(outerpopover.matches(':open'), + 'The outer popover should be closed by opening the inner one.'); +}, 'Disabled popover*target buttons should not affect the popover heirarchy.'); +</script> + +<div id=outerpopover2 popover=auto> + <button id=togglebutton2 popovertoggletarget=innerpopover2>toggle popover</button> +</div> +<div id=innerpopover2 popover=auto>popover</div> +<script> +test(() => { + outerpopover2.showPopover(); + innerpopover2.showPopover(); + assert_true(innerpopover2.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_true(outerpopover2.matches(':open'), + 'The outer popover should stay open when opening the inner one.'); + + togglebutton2.disabled = true; + assert_false(innerpopover2.matches(':open'), + 'The inner popover should be closed when the hierarchy is broken.'); + assert_false(outerpopover2.matches(':open'), + 'The outer popover should be closed when the hierarchy is broken.'); +}, 'Disabling popover*target buttons when popovers are open should still cause all popovers to be closed when the formerly outer popover is closed.'); +</script> + +<div id=outerpopover3 popover=auto> + <button id=togglebutton3 popovertoggletarget=innerpopover3>toggle popover</button> +</div> +<div id=innerpopover3 popover=auto>popover</div> +<script> +test(() => { + outerpopover3.showPopover(); + innerpopover3.showPopover(); + assert_true(innerpopover3.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_true(outerpopover3.matches(':open'), + 'The outer popover should stay open when opening the inner one.'); + + togglebutton3.disabled = true; + assert_false(innerpopover3.matches(':open'), + 'The inner popover be should be closed when the hierarchy is broken.'); + assert_false(outerpopover3.matches(':open'), + 'The outer popover be should be closed when the hierarchy is broken.'); +}, 'Disabling popover*target buttons when popovers are open should still cause all popovers to be closed when the formerly inner popover is closed.'); +</script> + +<div id=outerpopover4 popover=auto> + <button id=togglebutton4 popovertoggletarget=innerpopover4>toggle popover</button> +</div> +<div id=innerpopover4 popover=auto>popover</div> +<form id=submitform>form</form> +<script> +test(() => { + outerpopover4.showPopover(); + innerpopover4.showPopover(); + assert_true(innerpopover4.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_true(outerpopover4.matches(':open'), + 'The outer popover should stay open when opening the inner one.'); + + togglebutton4.setAttribute('form', 'submitform'); + assert_false(innerpopover4.matches(':open'), + 'The inner popover be should be closed when the hierarchy is broken.'); + assert_false(outerpopover4.matches(':open'), + 'The outer popover be should be closed when the hierarchy is broken.'); +}, 'Setting the form attribute on popover*target buttons when popovers are open should close all popovers.'); +</script> + +<div id=outerpopover5 popover=auto> + <input type=button id=togglebutton5 popovertoggletarget=innerpopover5>toggle popover</button> +</div> +<div id=innerpopover5 popover=auto>popover</div> +<script> +test(() => { + outerpopover5.showPopover(); + innerpopover5.showPopover(); + assert_true(innerpopover5.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_true(outerpopover5.matches(':open'), + 'The outer popover should stay open when opening the inner one.'); + + togglebutton5.setAttribute('type', 'text'); + assert_false(innerpopover5.matches(':open'), + 'The inner popover be should be closed when the hierarchy is broken.'); + assert_false(outerpopover5.matches(':open'), + 'The outer popover be should be closed when the hierarchy is broken.'); +}, 'Changing the input type on a popover*target button when popovers are open should close all popovers.'); +</script> + +<div id=outerpopover6 popover=auto> + <button id=togglebutton6 popovertoggletarget=innerpopover6>toggle popover</button> +</div> +<div id=innerpopover6 popover=auto>popover</div> +<script> +test(() => { + outerpopover6.showPopover(); + innerpopover6.showPopover(); + assert_true(innerpopover6.matches(':open'), + 'The inner popover should be able to open successfully.'); + assert_true(outerpopover6.matches(':open'), + 'The outer popover should stay open when opening the inner one.'); + + togglebutton6.remove(); + assert_false(innerpopover6.matches(':open'), + 'The inner popover be should be closed when the hierarchy is broken.'); + assert_false(outerpopover6.matches(':open'), + 'The outer popover be should be closed when the hierarchy is broken.'); +}, 'Disconnecting popover*target buttons when popovers are open should close all popovers.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore index 011f05c60..f6776a6 100644 --- a/third_party/blink/web_tests/external/wpt/lint.ignore +++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -299,7 +299,7 @@ GENERATE_TESTS: mediacapture-image/MediaStreamTrack-getCapabilities.https.html GENERATE_TESTS: mediacapture-image/MediaStreamTrack-getConstraints.https.html GENERATE_TESTS: mediacapture-image/MediaStreamTrack-getSettings.https.html -GENERATE_TESTS: mediacapture-image/setOptions-reject.html +GENERATE_TESTS: mediacapture-image/takePhoto-reject.html GENERATE_TESTS: html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html GENERATE_TESTS: html/syntax/parsing/Document.getElementsByTagName-foreign-01.html GENERATE_TESTS: html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/redirect-same-origin.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/redirect-same-origin.h2.window.js.ini index 767a4707..9e3b221 100644 --- a/third_party/blink/web_tests/external/wpt/loading/early-hints/redirect-same-origin.h2.window.js.ini +++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/redirect-same-origin.h2.window.js.ini
@@ -1,6 +1,6 @@ [redirect-same-origin.h2.window.html] expected: - if product == "chrome": OK + if product == "chrome": [ERROR, OK] ERROR [Redirect to the same origin keeps early hints preload] expected: [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-same-origin.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-same-origin.h2.window.js.ini index c87d9d9..b3b07ad 100644 --- a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-same-origin.h2.window.js.ini +++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-same-origin.h2.window.js.ini
@@ -1,4 +1,4 @@ [referrer-policy-same-origin.h2.window.html] expected: - if product == "chrome": OK + if product == "chrome": [ERROR, OK] ERROR
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-image/setOptions-reject.html b/third_party/blink/web_tests/external/wpt/mediacapture-image/takePhoto-reject.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/mediacapture-image/setOptions-reject.html rename to third_party/blink/web_tests/external/wpt/mediacapture-image/takePhoto-reject.html
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js index 97d45d4..5753b7e 100644 --- a/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/mock-imagecapture.js
@@ -153,7 +153,7 @@ return Promise.resolve(newState); } - async setOptions(source_id, settings) { + async setPhotoOptions(source_id, settings) { const isAllowedToControlPanTiltZoom = await this.isPanTiltZoomPermissionGranted(); if (!isAllowedToControlPanTiltZoom && (settings.hasPan || settings.hasTilt || settings.hasZoom)) {
diff --git a/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden-manual.https.html b/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden-manual.https.html deleted file mode 100644 index 05368bdf..0000000 --- a/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden-manual.https.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<meta name="timeout" content="long"> -<title>Screen wake locks respect page visibility changes</title> -<link rel="help" href="https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-visibility"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> - -promise_test(async t => { - const screenWakeLock = await navigator.wakeLock.request('screen'); - assert_false(screenWakeLock.released, "The released attribute is initially false") - const screenWakeLockReleased = - new EventWatcher(t, screenWakeLock, "release").wait_for("release"); - - const eventWatcher = new EventWatcher(t, document, "visibilitychange"); - await eventWatcher.wait_for("visibilitychange"); - assert_true(document.hidden, "document is hidden after the visibilitychange event"); - await screenWakeLockReleased; - assert_true(screenWakeLock.released, "The released attribute is true after the lock is released"); - await promise_rejects_dom(t, "NotAllowedError", navigator.wakeLock.request('screen'), - "new screen locks are not allowed when the page is not visible"); - - await eventWatcher.wait_for("visibilitychange"); - assert_false(document.hidden, "document is no longer hidden after the visibilitychange event"); -}, "Test screen locks respect page visibility changes"); - -</script> - -<p>Switch the page to the background, then switch back to it.</p>
diff --git a/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html b/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html new file mode 100644 index 0000000..c8c9712b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html
@@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> +<title>Screen wake locks respect page visibility changes</title> +<link rel="help" href="https://w3c.github.io/screen-wake-lock/#handling-document-loss-of-visibility"> +<body> +<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="/page-visibility/resources/window_state_context.js"></script> +<script> +'use strict'; + +promise_test(async t => { + await test_driver.set_permission({ name: 'screen-wake-lock' }, 'granted'); + + const {minimize, restore} = window_state_context(t); + await minimize(); + + assert_true(document.hidden); + await promise_rejects_dom(t, "NotAllowedError", navigator.wakeLock.request('screen'), + "new screen locks are not allowed when the page is not visible"); +}, "navigator.wakeLock.request('screen') fails when the document is hidden"); + +promise_test(async t => { + await test_driver.set_permission({ name: 'screen-wake-lock' }, 'granted'); + + const { minimize, restore } = window_state_context(t); + + const screenLock1 = await navigator.wakeLock.request('screen'); + const screenLock2 = await navigator.wakeLock.request('screen'); + + assert_false(screenLock1.released, "The released attribute is initially false"); + assert_false(screenLock2.released, "The released attribute is initially false"); + + const wait1 = new EventWatcher(t, screenLock1, 'release').wait_for('release'); + const wait2 = new EventWatcher(t, screenLock2, 'release').wait_for('release'); + + await minimize(); + assert_true(document.hidden); + + await Promise.all([wait1, wait2]); + + assert_true(screenLock1.released, "The released attribute is true after the lock is released"); + assert_true(screenLock2.released, "The released attribute is true after the lock is released"); +}, "Screen wake locks are released when the document the page is hidden"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html.ini b/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html.ini new file mode 100644 index 0000000..59e9a5ef --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen-wake-lock/wakelock-document-hidden.https.html.ini
@@ -0,0 +1,6 @@ +[wakelock-document-hidden.https.html] + [navigator.wakeLock.request('screen') fails when the document is hidden] + expected: FAIL + + [Screen wake locks are released when the document the page is hidden] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-animation-range-update.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-animation-range-update.tentative.html new file mode 100644 index 0000000..41386bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/view-timeline-animation-range-update.tentative.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>Change animation-range after creation</title> +<link rel="help" src="https://www.w3.org/TR/scroll-animations-1/#named-range-animation-declaration"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="support/testcommon.js"></script> +<style> + @keyframes anim { + from { z-index: 0; background-color: skyblue;} + to { z-index: 100; background-color: coral; } + } + #scroller { + border: 10px solid lightgray; + overflow-y: scroll; + width: 200px; + height: 200px; + } + #target { + margin: 800px 0px; + width: 100px; + height: 100px; + z-index: -1; + background-color: green; + animation: anim auto both linear; + animation-timeline: t1; + view-timeline: t1 block; + } + .restrict-range { + animation-range-start: contain 0%; + animation-range-end: contain 100%; + } +</style> +<body> + <div id=scroller> + <div id=target></div> + </div> +</body> +<script type="text/javascript"> + setup(assert_implements_animation_timeline); + + async function scrollTop(e, value) { + e.scrollTop = value; + await waitForNextFrame(); + } + async function waitForAnimationReady(target) { + await waitForNextFrame(); + await Promise.all(target.getAnimations().map(x => x.promise)); + } + async function assertValueAt(scroller, target, position, expected) { + await waitForAnimationReady(target); + await scrollTop(scroller, position); + assert_equals(getComputedStyle(target).zIndex, expected.toString()); + } + + promise_test(async t => { + const scroller = document.getElementById('scroller'); + const target = document.getElementById('target'); + waitForAnimationReady(target); + + await assertValueAt(scroller, target, 600, 0); + await assertValueAt(scroller, target, 700, 33); + await assertValueAt(scroller, target, 750, 50); + await assertValueAt(scroller, target, 800, 67); + + target.classList.toggle('restrict-range'); + await waitForNextFrame(); + + await assertValueAt(scroller, target, 700, 0); + await assertValueAt(scroller, target, 750, 50); + await assertValueAt(scroller, target, 800, 100); + }, 'Ensure that animation is updated on a style change'); +</script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/inline-view-timeline-current-time.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/inline-view-timeline-current-time.tentative.html index 412145b..5b37798f 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/inline-view-timeline-current-time.tentative.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/inline-view-timeline-current-time.tentative.html
@@ -48,7 +48,10 @@ await waitForNextFrame(); const anim = CreateViewTimelineOpacityAnimation(t, target, - {axis: 'inline'}); + { + timeline: + {axis: 'inline'} + }); const timeline = anim.timeline; await anim.ready; @@ -119,7 +122,10 @@ await waitForNextFrame(); const anim = CreateViewTimelineOpacityAnimation(t, target, - {axis: 'inline'}); + { + timeline: + {axis: 'inline'} + }); const timeline = anim.timeline; await anim.ready; @@ -176,7 +182,10 @@ await waitForNextFrame(); const anim = CreateViewTimelineOpacityAnimation(t, target, - {axis: 'inline'}); + { + timeline: + {axis: 'inline'} + }); const timeline = anim.timeline; await anim.ready; @@ -229,7 +238,10 @@ await waitForNextFrame(); const anim = CreateViewTimelineOpacityAnimation(t, target, - {axis: 'inline'}); + { + timeline: + {axis: 'inline'} + }); const timeline = anim.timeline; await anim.ready;
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/testcommon.js b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/testcommon.js index 12693c3..65301215 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/testcommon.js +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/testcommon.js
@@ -8,20 +8,26 @@ } function CreateViewTimelineOpacityAnimation(test, target, options) { - const viewTimelineOptions = { + const timeline_options = { subject: target, axis: 'block' }; - if (options) { - for (let key in options) { - viewTimelineOptions[key] = options[key]; + if (options && 'timeline' in options) { + for (let key in options.timeline) { + timeline_options[key] = options.timeline[key]; + } + } + const animation_options = { + timeline: new ViewTimeline(timeline_options) + }; + if (options && 'animation' in options) { + for (let key in options.animation) { + animation_options[key] = options.animation[key]; } } const anim = - target.animate( - { opacity: [0.3, 0.7] }, - { timeline: new ViewTimeline(viewTimelineOptions) }); + target.animate({ opacity: [0.3, 0.7] }, animation_options); test.add_cleanup(() => { anim.cancel(); }); @@ -44,7 +50,7 @@ const anim = options.anim || - CreateViewTimelineOpacityAnimation(t, target, options.timeline); + CreateViewTimelineOpacityAnimation(t, target, options); if (options.timing) anim.effect.updateTiming(options.timing); @@ -99,9 +105,11 @@ options.timeline = { axis: 'inline' }; - options.timing = { + options.animation = { rangeStart: options.rangeStart, rangeEnd: options.rangeEnd, + }; + options.timing = { // Set fill to accommodate floating point precision errors at the // endpoints. fill: 'both'
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html index 8f385e7..09714b57 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-get-current-time-range-name.html
@@ -53,7 +53,10 @@ // 900 px cover end, exit end const anim = CreateViewTimelineOpacityAnimation(t, target, - { axis: 'inline', fill: 'both' }); + { + timeline: { axis: 'inline' }, + animation: { fill: 'both' } + }); let timeline = anim.timeline; container.scrollLeft = 600;
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-subject-size-changes.html b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-subject-size-changes.html index 553facb..a47fed8 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-subject-size-changes.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/view-timelines/view-timeline-subject-size-changes.html
@@ -35,11 +35,12 @@ <script type="text/javascript"> promise_test(async t => { const options = { - axis: 'vertical', - timing: { + timeline: { axis: 'vertical' }, + animation: { rangeStart: { rangeName: 'enter', offset: CSS.percent(0) }, rangeEnd: { rangeName: 'enter', offset: CSS.percent(100) }, - // Set fill to accommodate floating point precision errors at the endpoints. + // Set fill to accommodate floating point precision errors at the + // endpoints. fill: 'both' } };
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/helpers.js b/third_party/blink/web_tests/external/wpt/storage-access-api/helpers.js index 337a92c..e6071241 100644 --- a/third_party/blink/web_tests/external/wpt/storage-access-api/helpers.js +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/helpers.js
@@ -75,20 +75,27 @@ return test_driver.bless('run callback with user gesture', callback); } -// Sends a message to the given target window, and waits for the provided -// promise to resolve. -function PostMessageAndAwait(message, targetWindow, promise) { - targetWindow.postMessage(message, "*"); - return promise; +// Sends a message to the given target window and returns a promise that +// resolves when a reply was sent. +function PostMessageAndAwaitReply(message, targetWindow) { + const timestamp = window.performance.now(); + const reply = ReplyPromise(timestamp); + targetWindow.postMessage({timestamp, ...message}, "*"); + return reply; } // Returns a promise that resolves when the next "reply" is received via -// postMessage. -function ReplyPromise() { +// postMessage. Takes a "timestamp" argument to validate that the received +// message belongs to its original counterpart. +function ReplyPromise(timestamp) { return new Promise((resolve) => { - window.addEventListener("message", (event) => { - resolve(event.data); - }, { once: true }); + const listener = (event) => { + if (event.data.timestamp == timestamp) { + window.removeEventListener("message", listener); + resolve(event.data.data); + } + }; + window.addEventListener("message", listener); }); } @@ -103,34 +110,48 @@ // Reads cookies via document.cookie in the given frame. function GetJSCookiesFromFrame(frame) { - return PostMessageAndAwait({ command: "document.cookie" }, frame.contentWindow, ReplyPromise()); + return PostMessageAndAwaitReply( + { command: "document.cookie" }, frame.contentWindow); } // Reads cookies via the `httpCookies` variable in the given frame. function GetHTTPCookiesFromFrame(frame) { - return PostMessageAndAwait({ command: "httpCookies" }, frame.contentWindow, ReplyPromise()); + return PostMessageAndAwaitReply( + { command: "httpCookies" }, frame.contentWindow); } // Executes document.hasStorageAccess in the given frame. function FrameHasStorageAccess(frame) { - return PostMessageAndAwait({ command: "hasStorageAccess" }, frame.contentWindow, ReplyPromise()); + return PostMessageAndAwaitReply( + { command: "hasStorageAccess" }, frame.contentWindow); } // Executes document.requestStorageAccess in the given frame. function RequestStorageAccessInFrame(frame) { - return PostMessageAndAwait({ command: "requestStorageAccess" }, frame.contentWindow, ReplyPromise()); + return PostMessageAndAwaitReply( + { command: "requestStorageAccess" }, frame.contentWindow); } // Executes test_driver.set_permission in the given frame, with the provided // arguments. function SetPermissionInFrame(frame, args = []) { - return PostMessageAndAwait({ command: "set_permission", args }, frame.contentWindow, ReplyPromise()); + return PostMessageAndAwaitReply( + { command: "set_permission", args }, frame.contentWindow); +} + +// Waits for a storage-access permission change and resolves with the current +// state. +function ObservePermissionChange(frame, args = []) { + return PostMessageAndAwaitReply( + { command: "observe_permission_change", args }, frame.contentWindow); } // Executes `location.reload()` in the given frame. The returned promise // resolves when the frame has finished reloading. function FrameInitiatedReload(frame) { - return PostMessageAndAwait({ command: "reload" }, frame.contentWindow, ReloadPromise(frame)); + const reload = ReloadPromise(frame); + frame.contentWindow.postMessage({ command: "reload" }, "*"); + return reload; } // Tries to set storage access policy, ignoring any errors.
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js index 958b609..a469d1b 100644 --- a/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe-navigation.sub.https.window.js
@@ -5,7 +5,7 @@ 'use strict'; (async function() { - // This is on the www subdomain, so it's cross-origin from the current document. + // This is cross-domain from the current document. const wwwAlt = "https://{{hosts[alt][www]}}:{{ports[https][0]}}"; promise_test(async (t) => {
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js b/third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js index 0d563e6..0ff599d0 100644 --- a/third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/resources/embedded_responder.js
@@ -6,7 +6,8 @@ window.addEventListener("message", async (event) => { function reply(data) { - event.source.postMessage(data, event.origin); + event.source.postMessage( + {timestamp: event.data.timestamp, data}, event.origin); } switch (event.data["command"]) { @@ -26,6 +27,12 @@ await test_driver.set_permission(...event.data.args); reply(undefined); break; + case "observe_permission_change": + const status = await navigator.permissions.query({name: "storage-access"}); + status.addEventListener("change", (event) => { + reply(event.target.state) + }, { once: true }); + break; case "reload": window.location.reload(); break;
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/resources/permissions-iframe.https.html b/third_party/blink/web_tests/external/wpt/storage-access-api/resources/permissions-iframe.https.html new file mode 100644 index 0000000..b83a05c3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/resources/permissions-iframe.https.html
@@ -0,0 +1,10 @@ +<!doctype html> +<meta charset=utf-8> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<!-- no testharnessreport.js --> +<script src="../helpers.js"></script> +<div id=log></div> +<script src="/storage-access-api/storage-access-permission.sub.https.window.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window-expected.txt new file mode 100644 index 0000000..f902c5b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window-expected.txt
@@ -0,0 +1,8 @@ +This is a testharness.js-based test. +PASS Permissions grants are observable across same-origin iframes +FAIL Permission default state can be queried assert_equals: expected "prompt" but got "denied" +PASS Permission granted state can be queried +PASS Permission denied state can be queried +PASS Permission state can be observed +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window.js b/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window.js new file mode 100644 index 0000000..88473ce --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/storage-access-api/storage-access-permission.sub.https.window.js
@@ -0,0 +1,87 @@ +// META: script=helpers.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +'use strict'; + +(async function() { + // This is cross-domain from the current document. + const wwwAlt = "https://{{hosts[alt][www]}}:{{ports[https][0]}}"; + + if (window === window.top) { + // Test the interaction between two (same-origin) iframes. + promise_test(async (t) => { + const responder_html = `${wwwAlt}/storage-access-api/resources/script-with-cookie-header.py?script=embedded_responder.js`; + const [frame1, frame2] = await Promise.all([ + CreateFrame(responder_html), + CreateFrame(responder_html), + ]); + + t.add_cleanup(async () => { + await SetPermissionInFrame(frame1, [{ name: 'storage-access' }, 'prompt']); + }); + + const observed = ObservePermissionChange(frame2); + await SetPermissionInFrame(frame1, [{ name: 'storage-access' }, 'granted']); + + const state = await observed; + assert_equals(state, "granted"); + }, "Permissions grants are observable across same-origin iframes"); + + // Finally run the simple tests below in a separate cross-origin iframe. + RunTestsInIFrame('https://{{domains[www]}}:{{ports[https][0]}}/storage-access-api/resources/permissions-iframe.https.html'); + return; + } + + // We're in an iframe test now. + test_driver.set_test_context(window.top); + + promise_test(async t => { + const permission = await navigator.permissions.query({name: "storage-access"}); + assert_equals(permission.name, "storage_access"); + assert_equals(permission.state, "prompt"); + }, "Permission default state can be queried"); + + promise_test(async t => { + t.add_cleanup(async () => { + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + }); + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); + + const permission = await navigator.permissions.query({name: "storage-access"}); + assert_equals(permission.name, "storage_access"); + assert_equals(permission.state, "granted"); + }, "Permission granted state can be queried"); + + promise_test(async t => { + t.add_cleanup(async () => { + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + }); + await test_driver.set_permission({ name: 'storage-access' }, 'denied'); + + const permission = await navigator.permissions.query({name: "storage-access"}); + assert_equals(permission.name, "storage_access"); + assert_equals(permission.state, "denied"); + + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + }, "Permission denied state can be queried"); + + promise_test(async t => { + t.add_cleanup(async () => { + await test_driver.set_permission({ name: 'storage-access' }, 'prompt'); + }); + + const permission = await navigator.permissions.query({name: "storage-access"}); + + const p = new Promise(resolve => { + permission.addEventListener("change", (event) => resolve(event), { once: true }); + }); + + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); + await RunCallbackWithGesture(() => document.requestStorageAccess()); + + const event = await p; + + assert_equals(event.target.name, "storage_access"); + assert_equals(event.target.state, "granted"); + }, "Permission state can be observed"); +})();
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json index df75ab5..9c4eedc 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json +++ b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json
@@ -273,7 +273,7 @@ { "comment": "Tab and newline are stripped", "href": "http://test/", - "new_value": "h\u000A\u000Att\u0009ps", + "new_value": "h\u000D\u000Att\u0009ps", "expected": { "href": "https://test/", "protocol": "https:", @@ -281,6 +281,14 @@ } }, { + "href": "http://test/", + "new_value": "https\u000D", + "expected": { + "href": "https://test/", + "protocol": "https:" + } + }, + { "comment": "Non-tab/newline C0 controls result in no-op", "href": "http://test/", "new_value": "https\u0000", @@ -299,7 +307,7 @@ }, { "href": "http://test/", - "new_value": "https\u000D", + "new_value": "https\u000E", "expected": { "href": "http://test/", "protocol": "http:"
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini b/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini index 86f0851..cd504e5 100644 --- a/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini +++ b/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini
@@ -1165,6 +1165,18 @@ [<a>: Setting <http://test/>.protocol = 'h\n\ntt\tps' Tab and newline are stripped] expected: FAIL + [<a>: Setting <http://test/>.protocol = 'https\r'] + expected: FAIL + + [<a>: Setting <http://test/>.protocol = 'h\r\ntt\tps' Tab and newline are stripped] + expected: FAIL + + [<area>: Setting <http://test/>.protocol = 'https\r'] + expected: FAIL + + [<area>: Setting <http://test/>.protocol = 'h\r\ntt\tps' Tab and newline are stripped] + expected: FAIL + [url-setters-a-area.window.html?include=javascript] expected:
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters.any.js.ini b/third_party/blink/web_tests/external/wpt/url/url-setters.any.js.ini index eb1c0e5..bdac88f 100644 --- a/third_party/blink/web_tests/external/wpt/url/url-setters.any.js.ini +++ b/third_party/blink/web_tests/external/wpt/url/url-setters.any.js.ini
@@ -846,6 +846,12 @@ [URL: Setting <http://test/>.protocol = 'h\n\ntt\tps' Tab and newline are stripped] expected: FAIL + [URL: Setting <http://test/>.protocol = 'h\r\ntt\tps' Tab and newline are stripped] + expected: FAIL + + [URL: Setting <http://test/>.protocol = 'https\r'] + expected: FAIL + [url-setters.any.worker.html?exclude=(file|javascript|mailto)] [URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged.] @@ -1119,6 +1125,12 @@ [URL: Setting <http://test/>.protocol = 'h\n\ntt\tps' Tab and newline are stripped] expected: FAIL + [URL: Setting <http://test/>.protocol = 'h\r\ntt\tps' Tab and newline are stripped] + expected: FAIL + + [URL: Setting <http://test/>.protocol = 'https\r'] + expected: FAIL + [url-setters.any.worker.html?include=file] [URL: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host]
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html index 6f8670f6..61b52ac5 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html +++ b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-prf.https.html
@@ -131,7 +131,7 @@ first: new Uint8Array([1,2,3,4]).buffer, }; return promise_rejects_dom( - t, "NotSupportedError", assert(id, {evalByCredential: byCred })); + t, "SyntaxError", assert(id, {evalByCredential: byCred })); }, "navigator.credentials.get() using invalid base64url credential ID"); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/set-metadata.https.html b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/set-metadata.https.html index 3840bfc7..ad346c1 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/set-metadata.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc-encoded-transform/set-metadata.https.html
@@ -35,6 +35,8 @@ 'spatialIndex'); assert_equals(cloneMetadata.temporalIndex, metadata.temporalIndex, 'temporalIndex'); + assert_equals(cloneMetadata.frameType, metadata.frameType, + 'frameType'); // RTCEncodedVideoFrameAdditionalMetadata-only fields. assert_array_equals(cloneMetadata.decodeTargetIndications, metadata.decodeTargetIndications,
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/rtp-stats-creation.html b/third_party/blink/web_tests/external/wpt/webrtc-stats/rtp-stats-creation.html index c12f266..df672a7f 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-stats/rtp-stats-creation.html +++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/rtp-stats-creation.html
@@ -94,7 +94,7 @@ while (true) { const report = await remotePc.getStats(); const audioPlayout = - [...report.values()].filter(({type}) => type == "audio-playout"); + [...report.values()].filter(({type}) => type == "media-playout"); if (audioPlayout.length == 1) { break; }
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt index 369a0a7..6920be49 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 248 tests; 232 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 248 tests; 240 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS getStats succeeds PASS Validating stats PASS codec's payloadType @@ -171,14 +171,14 @@ PASS media-source's timestamp PASS media-source's type PASS media-source's id -FAIL media-playout's synthesizedSamplesDuration assert_true: Is synthesizedSamplesDuration present expected true got false -FAIL media-playout's synthesizedSamplesEvents assert_true: Is synthesizedSamplesEvents present expected true got false -FAIL media-playout's totalSamplesDuration assert_true: Is totalSamplesDuration present expected true got false -FAIL media-playout's totalPlayoutDelay assert_true: Is totalPlayoutDelay present expected true got false -FAIL media-playout's totalSamplesCount assert_true: Is totalSamplesCount present expected true got false -FAIL media-playout's timestamp assert_true: Is timestamp present expected true got false -FAIL media-playout's type assert_true: Is type present expected true got false -FAIL media-playout's id assert_true: Is id present expected true got false +PASS media-playout's synthesizedSamplesDuration +PASS media-playout's synthesizedSamplesEvents +PASS media-playout's totalSamplesDuration +PASS media-playout's totalPlayoutDelay +PASS media-playout's totalSamplesCount +PASS media-playout's timestamp +PASS media-playout's type +PASS media-playout's id PASS transport's packetsSent PASS transport's packetsReceived PASS transport's bytesSent
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https.html b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https.html index 2fdd3ad..24b4d3f0 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/supported-stats.https.html
@@ -107,7 +107,8 @@ // `roundTripTime` is missing in this test, but awaiting for any // remote-outbound-rtp avoids flaky failures. const hasRemoteOutbound = remoteOutboundAudio || remoteOutboundVideo; - if (hasRemoteInbound && hasRemoteOutbound) { + const hasMediaPlayout = values.find(({type}) => type == "media-playout") != undefined; + if (hasRemoteInbound && hasRemoteOutbound && hasMediaPlayout) { return stats; } await new Promise(r => t.step_timeout(r, 1000));
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt index 857a2f9..a7997a99 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -351,6 +351,7 @@ toggle-trigger: none toggle-visibility: normal top: auto +top-layer: none touch-action: auto transform: none transform-origin: 384.5px 0px
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt index c8fcaac3..85073e7 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -351,6 +351,7 @@ toggle-trigger: none toggle-visibility: normal top: auto +top-layer: none touch-action: auto transform: none transform-origin: 50% 50%
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js index 027a5674..657bcf03 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js
@@ -49,18 +49,15 @@ events = []; } - let observedBids = 0; - let resolveWaitForTwoBidsPromise; - const waitForTwoBidsPromise = new Promise((resolve, reject)=>{ - resolveWaitForTwoBidsPromise = resolve; + let resolveWaitForWinPromise; + const waitForWinPromise = new Promise((resolve, reject)=>{ + resolveWaitForWinPromise = resolve; }); dp.Storage.onInterestGroupAccessed((messageObject)=>{ events.push(messageObject.params); - if (messageObject.params.type == 'bid') { - ++observedBids; - if (observedBids == 2) - resolveWaitForTwoBidsPromise(); + if (messageObject.params.type == 'win') { + resolveWaitForWinPromise(); } }); await page.navigate(base + 'empty.html'); @@ -73,12 +70,12 @@ // Need to navigate a fenced frame to the winning ad for the bids to be // recorded. await runAdAuctionAndNavigateFencedFrame(); - // Have to wait for the bids to be received, since there's no way to wait - // for the fenced frame navigation to complete directly. Only do this if - // FLEDGE is enabled and has sent events already, to avoid waiting for events - // that will never occur. + // Have to wait for the win to be received, which happens after commit + // (which also can't be waited for). Only do this if FLEDGE is enabled + // and has sent events already, to avoid waiting for events that will + // never occur. if (events.length > 0) - await waitForTwoBidsPromise; + await waitForWinPromise; await logAndClearEvents(); // Disable interest group logging, and run the same set of events. No new
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt index 60ee1d6..d4fa687 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
@@ -2,11 +2,18 @@ Attached to page target: about:blank (title: ) (waiting: false) -Dettached: about:blank +Detached: about:blank Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) (waiting: false) Auction winner:undefined +Attached to page target: about:blank + (title: ) + (waiting: false) +Detached: about:blank +Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html + (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) + (waiting: false) Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) (waiting: false)
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js index d17e2a6..8f159760 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js
@@ -18,6 +18,11 @@ return input; } + let detachedBidderWorklets = 0; + let resolveWaitForSecondBidderWorkletDetachedPromise; + const waitForSecondBidderWorkletDetachedPromise = new Promise((resolve, reject)=>{ + resolveWaitForSecondBidderWorkletDetachedPromise = resolve; + }); bp.Target.onAttachedToTarget(event => { const params = event.params; testRunner.log( @@ -28,7 +33,13 @@ }); bp.Target.onDetachedFromTarget(event => { - testRunner.log('Dettached: ' + urlForSession.get(event.params.sessionId)); + let url = urlForSession.get(event.params.sessionId); + testRunner.log('Detached: ' + url); + if (url.endsWith("fledge_bidding_logic.js.php")) { + ++detachedBidderWorklets; + if (detachedBidderWorklets == 2) + resolveWaitForSecondBidderWorkletDetachedPromise(); + } }); const base = 'https://a.test:8443/inspector-protocol/resources/' @@ -46,11 +57,18 @@ const winner1 = await page1_session.evaluateAsync(auctionJs); testRunner.log('Auction winner:' + handleUrn(winner1)); - // Ask to auto-attach related before re-running the auction. + // Ask to auto-attach related before re-running the auction. Use another page to + // avoid reporting events that happen after the auction completes. + const page2 = await testRunner.createPage({url: base + 'fledge_join.html'}); + const page2_session = await page2.createSession(); await bp.Target.autoAttachRelated( - {targetId: page1.targetId(), waitForDebuggerOnStart: false}); + {targetId: page2.targetId(), waitForDebuggerOnStart: false}); - const winner2 = await page1_session.evaluateAsync(auctionJs); + const winner2 = await page2_session.evaluateAsync(auctionJs); + // If FLEDGE is enabled, need to wait for post-auction scripts to run, to + // ensure a consistent number of FLEDGE scripts have been invoked. + if (detachedBidderWorklets > 0) + await waitForSecondBidderWorkletDetachedPromise; testRunner.log('Auction winner:' + handleUrn(winner2)); testRunner.log('DONE'); testRunner.completeTest();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js index ac9b726..7f17618 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js
@@ -11,6 +11,12 @@ return input; } + let attachedWorklets = 0; + let resolveWaitForThirdWorkletPromise; + const waitForThirdWorkletPromise = new Promise((resolve, reject)=>{ + resolveWaitForThirdWorkletPromise = resolve; + }); + bp.Target.onAttachedToTarget(async event => { const params = event.params; testRunner.log(`Attached to target ${params.targetInfo.url}`); @@ -18,6 +24,9 @@ const targetSession = new TestRunner.Session(testRunner, event.params.sessionId); if (params.targetInfo.type === 'auction_worklet') { + ++attachedWorklets; + if (attachedWorklets == 3) + resolveWaitForThirdWorkletPromise(); testRunner.log(' Bidder instrumentation breakpoint set attempted'); targetSession.protocol.Debugger.enable(); targetSession.protocol.Runtime.enable(); @@ -53,6 +62,16 @@ {targetId: page.targetId(), waitForDebuggerOnStart: true}); const winner = await session.evaluateAsync(auctionJs); + + // Have to wait for the third worklet to be attached (first the seller + // is attached, then the bidder is attached to bid, and then the + // bidder worklet is reloaded to call reportWin()), as reportWin() + // is invoked racily with reporting auction completion. Only do this + // if FLEDGE is enabled and has sent events already, to avoid waiting + // for events that will never occur. + if (attachedWorklets > 0) + await waitForThirdWorkletPromise; + testRunner.log('Auction winner:' + handleUrn(winner)); testRunner.log('DONE'); testRunner.completeTest();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt index ad9475b..913ef94 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -7,5 +7,4 @@ Saw process assignment for bidder for host:nope Saw process assignment for seller for host:nope Saw process release for bidder for host:nope -Saw process release for seller for host:nope
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js index bcfc14c3..a725f13 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js
@@ -61,7 +61,7 @@ } } - const sortedRequestInfo = [...requestIdToInfo.values()].sort((a, b) => { + let sortedRequestInfo = [...requestIdToInfo.values()].sort((a, b) => { if (a.url < b.url) return -1; else if (a.url === b.url) @@ -69,6 +69,15 @@ return +1; }); + // There may racily be two bidding logic loads, depending on how far along running reportings scripts + // has advanced, which is done after auction completion is signalled. If there are two such loads, + // ignore the second one. + if (sortedRequestInfo.length > 2 && + sortedRequestInfo[0].endsWith("fledge_bidding_logic.js.php") && + sortedRequestInfo[1].endsWith("fledge_bidding_logic.js.php")) { + sortedRequestInfo = sortedRequestInfo.splice(1); + } + for (let requestInfo of sortedRequestInfo) { testRunner.log(requestInfo.url + ':'); for (let ev of requestInfo.events) {
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js index 717bbebb..1de8236 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
@@ -50,7 +50,6 @@ let sawBidderRunningInProcess = 'nope'; let sawSellerRunningInProcess = 'nope'; let sawBidderDoneWithProcess = 'nope'; - let sawSellerDoneWithProcess = 'nope'; for (ev of devtoolsEvents) { if (ev.name === 'AuctionWorkletRunningInProcess') { let data = ev.args.data; @@ -65,9 +64,9 @@ let data = ev.args.data; if (data.type === 'bidder') { sawBidderDoneWithProcess = data.host; - } else if (data.type === 'seller') { - sawSellerDoneWithProcess = data.host; } + // Note that seller unload is not guaranteed to be observed, as it can + // happen after auction completion. verifyAuctionProcessEventData(data); } if (ev.name === 'generate_bid') @@ -95,8 +94,8 @@ sawSellerRunningInProcess); testRunner.log( 'Saw process release for bidder for host:' + sawBidderDoneWithProcess); - testRunner.log( - 'Saw process release for seller for host:' + sawSellerDoneWithProcess); + // Note that seller unload is not guaranteed to be observed, as it can happen + // after auction completion. testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 9954001..0753e26e 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3147,8 +3147,33 @@ method releaseLock method write [NAMESPACES] +namespace console + attribute @@toStringTag + method assert + method clear + method context + method count + method countReset + method createTask + method debug + method dir + method dirxml + method error + method group + method groupCollapsed + method groupEnd + method info + method log + method profile + method profileEnd + method table + method time + method timeEnd + method timeLog + method timeStamp + method trace + method warn [GLOBAL OBJECT] - attribute console attribute globalThis attribute internals getter clients
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-animation-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-animation-worklet-expected.txt index 8f90835d..c57a9e2 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-animation-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-animation-worklet-expected.txt
@@ -106,8 +106,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerAnimator @@ -218,8 +243,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerAnimator
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt index 0adcda78..a3749e8 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt
@@ -156,8 +156,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: getter currentFrame CONSOLE MESSAGE: getter currentTime
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt index 2708f35e..f5b36de 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-layout-worklet-expected.txt
@@ -353,8 +353,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerLayout @@ -712,8 +737,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: method gc CONSOLE MESSAGE: method registerLayout
diff --git a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index cdbc7ea..9d5ec11 100644 --- a/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/blink/web_tests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -411,8 +411,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: getter devicePixelRatio CONSOLE MESSAGE: method gc @@ -829,8 +854,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: getter devicePixelRatio CONSOLE MESSAGE: method gc
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles-expected.txt new file mode 100644 index 0000000..0565049 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles-expected.txt
@@ -0,0 +1,23 @@ +The test verifies functionality of protocol methods working correctly with CSS nesting. +*div* { user-agent readonly + display: block; @[undefined-undefined] +} +*#nested* { regular + width: 42px; @[2:4-2:16] + width: 42px; @[undefined-undefined] +} +==== Style sheet text ==== +#parent { + #nested { + width: 41px; + } +} + +*div* { user-agent readonly + display: block; @[undefined-undefined] +} +*#nested* { regular + width: 41px; @[2:4-2:16] + width: 41px; @[undefined-undefined] +} +
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles.js b/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles.js new file mode 100644 index 0000000..1cc2ec90 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/css/css-nested-styles.js
@@ -0,0 +1,41 @@ +(async function(testRunner) { + var {dp} = await testRunner.startHTML(` + <link rel='stylesheet' href='${testRunner.url('resources/nested-styles.css')}'/> + <div id='parent'> + <div id='nested'></div> + </div>`, + 'The test verifies functionality of protocol methods working correctly with CSS nesting.'); + + await dp.DOM.enable(); + await dp.CSS.enable(); + + const CSSHelper = await testRunner.loadScript('../resources/css-helper.js'); + const cssHelper = new CSSHelper(testRunner, dp); + + const document = await dp.DOM.getDocument({}); + const documentNodeId = document.result.root.nodeId; + const nestedNode = await dp.DOM.querySelector({ + nodeId: documentNodeId, + selector: '#nested', + }); + const nestedNodeId = nestedNode.result.nodeId; + + const matchedStyles = await dp.CSS.getMatchedStylesForNode({nodeId: nestedNodeId}); + for (const ruleMatch of matchedStyles.result.matchedCSSRules) { + cssHelper.dumpRuleMatch(ruleMatch); + } + + const styleSheetId = matchedStyles.result.matchedCSSRules.at(-1).rule.styleSheetId; + await cssHelper.setStyleTexts(styleSheetId, false, [{ + styleSheetId, + range: { startLine: 1, startColumn: 11, endLine: 3, endColumn: 2 }, + text: "\n width: 41px;\n ", + }]); + + const updatedStyles = await dp.CSS.getMatchedStylesForNode({nodeId: nestedNodeId}); + for (const ruleMatch of updatedStyles.result.matchedCSSRules) { + cssHelper.dumpRuleMatch(ruleMatch); + } + + testRunner.completeTest(); +});
diff --git a/third_party/blink/web_tests/inspector-protocol/css/resources/nested-styles.css b/third_party/blink/web_tests/inspector-protocol/css/resources/nested-styles.css new file mode 100644 index 0000000..14f04e5e --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/css/resources/nested-styles.css
@@ -0,0 +1,5 @@ +#parent { + #nested { + width: 42px; + } +}
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" index d7a08e9..0f533a0b 100644 --- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 405 tests; 259 PASS, 146 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 407 tests; 259 PASS, 148 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS <area>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. @@ -47,18 +47,18 @@ PASS <area>: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS <a>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. PASS <area>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL <a>: Setting <http://test/>.protocol = 'h - +FAIL <a>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" -FAIL <area>: Setting <http://test/>.protocol = 'h - +FAIL <area>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL <a>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" +FAIL <area>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS <a>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <area>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <a>: Setting <http://test/>.protocol = 'https' PASS <area>: Setting <http://test/>.protocol = 'https' -PASS <a>: Setting <http://test/>.protocol = 'https\r' -PASS <area>: Setting <http://test/>.protocol = 'https\r' +PASS <a>: Setting <http://test/>.protocol = 'https' +PASS <area>: Setting <http://test/>.protocol = 'https' PASS <a>: Setting <http://test/>.protocol = 'https ' PASS <area>: Setting <http://test/>.protocol = 'https ' PASS <a>: Setting <unix:/run/foo.socket>.username = 'me' No host means no username
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" index b49fe417..7f97527 100644 --- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 126 PASS, 77 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 126 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" index b49fe417..7f97527 100644 --- "a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 126 PASS, 77 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 126 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.png index cccddff6..d2a95947 100644 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.png +++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.txt index ec0df8b..3340f53 100644 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.txt +++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/exs-display-none-expected.txt
@@ -1,12 +1,12 @@ { "layers": [ { - "name": "Scrolling background of LayoutView #document", + "name": "Scrolling background of LayoutNGView #document", "bounds": [800, 600], "contentsOpaque": true, "backgroundColor": "#FFFFFF", "invalidations": [ - [50, 52, 571, 84] + [50, 50, 571, 84] ] } ]
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" index 9dba2975..35c23a4 100644 --- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 405 tests; 257 PASS, 148 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 407 tests; 257 PASS, 150 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS <area>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. @@ -47,18 +47,18 @@ PASS <area>: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS <a>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. PASS <area>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL <a>: Setting <http://test/>.protocol = 'h - +FAIL <a>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" -FAIL <area>: Setting <http://test/>.protocol = 'h - +FAIL <area>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL <a>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" +FAIL <area>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS <a>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <area>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <a>: Setting <http://test/>.protocol = 'https' PASS <area>: Setting <http://test/>.protocol = 'https' -PASS <a>: Setting <http://test/>.protocol = 'https\r' -PASS <area>: Setting <http://test/>.protocol = 'https\r' +PASS <a>: Setting <http://test/>.protocol = 'https' +PASS <area>: Setting <http://test/>.protocol = 'https' PASS <a>: Setting <http://test/>.protocol = 'https ' PASS <area>: Setting <http://test/>.protocol = 'https ' PASS <a>: Setting <unix:/run/foo.socket>.username = 'me' No host means no username
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" index fa5107c..b400a7f 100644 --- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 125 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 125 PASS, 79 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" index fa5107c..b400a7f 100644 --- "a/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/linux/virtual/idna-2008/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 125 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 125 PASS, 79 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" index b49fe417..7f97527 100644 --- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 126 PASS, 77 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 126 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" index b49fe417..7f97527 100644 --- "a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 126 PASS, 77 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 126 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. PASS URL: Setting <a://example.net>.protocol = 'b' @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/exs-display-none-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/exs-display-none-expected.txt index b83f468..11c0df2 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/exs-display-none-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/exs-display-none-expected.txt
@@ -1,12 +1,12 @@ { "layers": [ { - "name": "Scrolling background of LayoutView #document", + "name": "Scrolling background of LayoutNGView #document", "bounds": [800, 600], "contentsOpaque": true, "backgroundColor": "#FFFFFF", "invalidations": [ - [50, 50, 571, 82] + [50, 49, 571, 83] ] } ]
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" index f1c0b7e..b041b2d 100644 --- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-a-area.window_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 405 tests; 239 PASS, 166 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 407 tests; 239 PASS, 168 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… FAIL <a>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" FAIL <area>: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" @@ -47,18 +47,18 @@ PASS <area>: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS <a>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. PASS <area>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL <a>: Setting <http://test/>.protocol = 'h - +FAIL <a>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" -FAIL <area>: Setting <http://test/>.protocol = 'h - +FAIL <area>: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL <a>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" +FAIL <area>: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS <a>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <area>: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS <a>: Setting <http://test/>.protocol = 'https' PASS <area>: Setting <http://test/>.protocol = 'https' -PASS <a>: Setting <http://test/>.protocol = 'https\r' -PASS <area>: Setting <http://test/>.protocol = 'https\r' +PASS <a>: Setting <http://test/>.protocol = 'https' +PASS <area>: Setting <http://test/>.protocol = 'https' PASS <a>: Setting <http://test/>.protocol = 'https ' PASS <area>: Setting <http://test/>.protocol = 'https ' PASS <a>: Setting <unix:/run/foo.socket>.username = 'me' No host means no username
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" index 87ef63f..691f6e7 100644 --- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any.worker_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 116 PASS, 87 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 116 PASS, 88 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… FAIL URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" FAIL URL: Setting <a://example.net>.protocol = 'b' assert_equals: expected "b://example.net" but got "file:///B:///A://example.net" @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" index 87ef63f..691f6e7 100644 --- "a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt" +++ "b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters.any_exclude=\050file_javascript_mailto\051-expected.txt"
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 203 tests; 116 PASS, 87 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 204 tests; 116 PASS, 88 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… FAIL URL: Setting <a://example.net>.protocol = '' The empty string is not a valid scheme. Setter leaves the URL unchanged. assert_equals: expected "a://example.net" but got "file:///A://example.net" FAIL URL: Setting <a://example.net>.protocol = 'b' assert_equals: expected "b://example.net" but got "file:///B:///A://example.net" @@ -24,12 +24,12 @@ PASS URL: Setting <http://example.net>.protocol = 'https:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <data:text/html,<p>Test>.protocol = 'view-source+data:foo : bar' Stuff after the first ':' is ignored PASS URL: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme. -FAIL URL: Setting <http://test/>.protocol = 'h - +FAIL URL: Setting <http://test/>.protocol = 'h\r tt ps' Tab and newline are stripped assert_equals: expected "https://test/" but got "http://test/" +FAIL URL: Setting <http://test/>.protocol = 'https\r' assert_equals: expected "https://test/" but got "http://test/" PASS URL: Setting <http://test/>.protocol = 'https\0' Non-tab/newline C0 controls result in no-op PASS URL: Setting <http://test/>.protocol = 'https' -PASS URL: Setting <http://test/>.protocol = 'https\r' +PASS URL: Setting <http://test/>.protocol = 'https' PASS URL: Setting <http://test/>.protocol = 'https ' PASS URL: Setting <unix:/run/foo.socket>.username = 'me' No host means no username PASS URL: Setting <http://example.net>.username = 'me'
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.png index 14c230e..bd6b5c00 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.png +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.txt index 750a26f7..d5dc2e0 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/exs-display-none-expected.txt
@@ -1,12 +1,12 @@ { "layers": [ { - "name": "Scrolling background of LayoutView #document", + "name": "Scrolling background of LayoutNGView #document", "bounds": [800, 600], "contentsOpaque": true, "backgroundColor": "#FFFFFF", "invalidations": [ - [50, 52, 560, 84] + [50, 50, 560, 83] ] } ]
diff --git a/third_party/blink/web_tests/resources/global-interface-listing.js b/third_party/blink/web_tests/resources/global-interface-listing.js index ca42b20..0a60a73 100644 --- a/third_party/blink/web_tests/resources/global-interface-listing.js +++ b/third_party/blink/web_tests/resources/global-interface-listing.js
@@ -88,6 +88,17 @@ } function isWebIDLNamespace(propertyKey) { + // As a WebIDL namespace, console's class string should be "console", + // however since console is implemented directly inside v8 and does not + // follow the WebIDL binding norms, its class string is currently "Object". + // This means we accidentally skip it here, and fail to enumerate all of its + // attributes and properties. To ensure we don't skip it, we make a special + // exception for console, manually considering it as a namespace. This will + // no longer be necessary once https://crrev.com/c/4193308 lands, which + // fixes console's implementation. + if (propertyKey === 'console') + return true; + if (jsBuiltins.has(propertyKey)) return false; let object =
diff --git a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt index ac83fa8..24e2f1b 100644 --- a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt +++ b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
@@ -351,6 +351,7 @@ toggle-trigger: none toggle-visibility: normal top: auto +top-layer: none touch-action: auto transform: none transform-origin: 0px 0px
diff --git a/third_party/blink/web_tests/svg/custom/zoomed-ex-em-font-sizes.html b/third_party/blink/web_tests/svg/custom/zoomed-ex-em-font-sizes.html index dfe98d4..2023636 100644 --- a/third_party/blink/web_tests/svg/custom/zoomed-ex-em-font-sizes.html +++ b/third_party/blink/web_tests/svg/custom/zoomed-ex-em-font-sizes.html
@@ -28,7 +28,7 @@ zoomLevels.forEach(function (zoom) { html.style.zoom = zoom; test(function () { - assert_approx_equals(elm.getStartPositionOfChar(0).y, reference_y, 1); + assert_approx_equals(elm.getStartPositionOfChar(0).y, reference_y, 2); }, "Unit " + elm.id + " not affected by zoom level " + zoom); });
diff --git a/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt b/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt index 4135567..0319d98 100644 --- a/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt +++ b/third_party/blink/web_tests/virtual/css-trigonometric-functions-disabled/external/wpt/css/css-values/acos-asin-atan-atan2-computed-expected.txt
@@ -7,7 +7,7 @@ FAIL calc(acos(cos(pi - 3.14159265358979323846))) should be used-value-equivalent to 0deg assert_not_equals: calc(acos(cos(pi - 3.14159265358979323846))) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(atan(e - 2.7182818284590452354) ) should be used-value-equivalent to 0deg assert_not_equals: calc(atan(e - 2.7182818284590452354) ) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(asin(sin(30deg + 1.0471967rad ) )) should be used-value-equivalent to 90deg assert_not_equals: calc(asin(sin(30deg + 1.0471967rad ) )) isn't valid in 'transform'; got the default value instead. got disallowed value "none" -FAIL calc(acos(cos(30deg - 0.523599rad ) )) should be used-value-equivalent to 0deg assert_not_equals: calc(acos(cos(30deg - 0.523599rad ) )) isn't valid in 'margin-left'; got the default value instead. got disallowed value "0px" +FAIL calc(acos(cos(30deg - 0.523599rad ) )) should be used-value-equivalent to 0deg assert_not_equals: calc(acos(cos(30deg - 0.523599rad ) )) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(asin(sin(3.14159 / 2 + 1 - 1) )) should be used-value-equivalent to 90deg assert_not_equals: calc(asin(sin(3.14159 / 2 + 1 - 1) )) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(asin(sin(100grad) )) should be used-value-equivalent to 90deg assert_not_equals: calc(asin(sin(100grad) )) isn't valid in 'transform'; got the default value instead. got disallowed value "none" FAIL calc(acos(cos(0 / 2 + 1 - 1) )) should be used-value-equivalent to 0deg assert_not_equals: calc(acos(cos(0 / 2 + 1 - 1) )) isn't valid in 'transform'; got the default value instead. got disallowed value "none"
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt index 4ae5935..a34d5f858 100644 --- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt +++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
@@ -2,11 +2,18 @@ Attached to page target: about:blank (title: ) (waiting: false) -Dettached: about:blank +Detached: about:blank Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) (waiting: false) Auction winner:urn:uuid:(randomized) +Attached to page target: about:blank + (title: ) + (waiting: false) +Detached: about:blank +Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html + (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) + (waiting: false) Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html) (waiting: false) @@ -16,12 +23,12 @@ Attached to auction_worklet target: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php (title: FLEDGE bidder worklet for https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php) (waiting: false) -Dettached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php -Dettached: https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php +Detached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php +Detached: https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php Attached to auction_worklet target: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php (title: FLEDGE bidder worklet for https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php) (waiting: false) -Dettached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php +Detached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php Auction winner:urn:uuid:(randomized) DONE
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt index 8441ca2..90d905a 100644 --- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt +++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -7,5 +7,4 @@ Saw process assignment for bidder for host:a.test Saw process assignment for seller for host:a.test Saw process release for bidder for host:a.test -Saw process release for seller for host:a.test
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt index 9d9581a..d587f50 100644 --- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt +++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt
@@ -43,47 +43,6 @@ } -https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php: -ResourceSendRequest { - requestId : <string> - url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php -} -ResourceReceiveResponse { - encodedDataLength : 229 - fromCache : false - fromServiceWorker : false - mimeType : application/javascript - requestId : <string> - responseTime : <absolute timestamp> - statusCode : 200 - timing : { - connectEnd : <relative timestamp> - connectStart : <relative timestamp> - dnsEnd : <relative timestamp> - dnsStart : <relative timestamp> - proxyEnd : -1 - proxyStart : -1 - pushEnd : 0 - pushStart : 0 - receiveHeadersEnd : <relative timestamp> - requestTime : <number> - sendEnd : <relative timestamp> - sendStart : <relative timestamp> - sslEnd : <relative timestamp> - sslStart : <relative timestamp> - workerReady : -1 - workerStart : -1 - } -} -ResourceFinish { - decodedBodyLength : 598 - didFail : false - encodedDataLength : 229 - finishTime : <number> - requestId : <string> -} - - https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php: ResourceSendRequest { requestId : <string>
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index db26a19f..6ca077b 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -2987,8 +2987,33 @@ method releaseLock method write [NAMESPACES] +namespace console + attribute @@toStringTag + method assert + method clear + method context + method count + method countReset + method createTask + method debug + method dir + method dirxml + method error + method group + method groupCollapsed + method groupEnd + method info + method log + method profile + method profileEnd + method table + method time + method timeEnd + method timeLog + method timeStamp + method trace + method warn [GLOBAL OBJECT] - attribute console attribute globalThis attribute internals getter clients
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index b5b28d84..739eab52 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -368,8 +368,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: getter devicePixelRatio CONSOLE MESSAGE: method gc @@ -743,8 +768,33 @@ CONSOLE MESSAGE: method releaseLock CONSOLE MESSAGE: method write CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method createTask +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn CONSOLE MESSAGE: [GLOBAL OBJECT] -CONSOLE MESSAGE: attribute console CONSOLE MESSAGE: attribute globalThis CONSOLE MESSAGE: getter devicePixelRatio CONSOLE MESSAGE: method gc
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt index 9a5d21f..773487f 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -1022,6 +1022,7 @@ property width html element template property content + property shadowRootMode html element textarea property autocomplete property checkValidity
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 77dc7b3..dee430f 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -3291,8 +3291,33 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] [NAMESPACES] +[Worker] namespace console +[Worker] attribute @@toStringTag +[Worker] method assert +[Worker] method clear +[Worker] method context +[Worker] method count +[Worker] method countReset +[Worker] method createTask +[Worker] method debug +[Worker] method dir +[Worker] method dirxml +[Worker] method error +[Worker] method group +[Worker] method groupCollapsed +[Worker] method groupEnd +[Worker] method info +[Worker] method log +[Worker] method profile +[Worker] method profileEnd +[Worker] method table +[Worker] method time +[Worker] method timeEnd +[Worker] method timeLog +[Worker] method timeStamp +[Worker] method trace +[Worker] method warn [Worker] [GLOBAL OBJECT] -[Worker] attribute console [Worker] attribute globalThis [Worker] attribute internals [Worker] getter name
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 c05bbea..c51d1430 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
@@ -3993,7 +3993,9 @@ attribute @@toStringTag getter content getter shadowRoot + getter shadowRootMode method constructor + setter shadowRootMode interface HTMLTextAreaElement : HTMLElement attribute @@toStringTag getter autocomplete @@ -10706,11 +10708,38 @@ method vmax method vmin method vw +namespace console + attribute @@toStringTag + getter memory + method assert + method clear + method context + method count + method countReset + method createTask + method debug + method dir + method dirxml + method error + method group + method groupCollapsed + method groupEnd + method info + method log + method profile + method profileEnd + method table + method time + method timeEnd + method timeLog + method timeStamp + method trace + method warn + setter memory [GLOBAL OBJECT] attribute GCController attribute accessibilityController attribute chrome - attribute console attribute eventSender attribute gamepadController attribute globalThis
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index f68f8f1..71440fa 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -2923,8 +2923,33 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] [NAMESPACES] +[Worker] namespace console +[Worker] attribute @@toStringTag +[Worker] method assert +[Worker] method clear +[Worker] method context +[Worker] method count +[Worker] method countReset +[Worker] method createTask +[Worker] method debug +[Worker] method dir +[Worker] method dirxml +[Worker] method error +[Worker] method group +[Worker] method groupCollapsed +[Worker] method groupEnd +[Worker] method info +[Worker] method log +[Worker] method profile +[Worker] method profileEnd +[Worker] method table +[Worker] method time +[Worker] method timeEnd +[Worker] method timeLog +[Worker] method timeStamp +[Worker] method trace +[Worker] method warn [Worker] [GLOBAL OBJECT] -[Worker] attribute console [Worker] attribute globalThis [Worker] attribute internals [Worker] getter name
diff --git a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html b/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html deleted file mode 100644 index 03246a3..0000000 --- a/third_party/blink/web_tests/wake-lock/wakelock-document-hidden.https.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> -<body> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="../resources/visibility.js"></script> -<script> -'use strict'; - -promise_test(async t => { - await internals.setPermission({name: 'screen-wake-lock'}, 'granted', - location.origin, location.origin); - - await setMainWindowHidden(true); - - assert_true(document.hidden); - return promise_rejects_dom(t, "NotAllowedError", navigator.wakeLock.request('screen')); -}, "navigator.wakeLock.request('screen') fails when the document is hidden"); - -promise_test(async t => { - await internals.setPermission({name: 'screen-wake-lock'}, 'granted', - location.origin, location.origin); - - await setMainWindowHidden(false); - - const screenLock1 = await navigator.wakeLock.request('screen'); - const screenLock2 = await navigator.wakeLock.request('screen'); - - assert_false(screenLock1.released); - assert_false(screenLock2.released); - - const wait1 = new EventWatcher(t, screenLock1, 'release').wait_for('release'); - const wait2 = new EventWatcher(t, screenLock2, 'release').wait_for('release'); - - await setMainWindowHidden(true); - - await Promise.all([wait1, wait2]); - - assert_true(screenLock1.released); - assert_true(screenLock2.released); -}, "Screen wake locks are released when the document the page is hidden"); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/wake-lock/wakelockpermissiondescriptor.https.html b/third_party/blink/web_tests/wake-lock/wakelockpermissiondescriptor.https.html deleted file mode 100644 index 76ad2835..0000000 --- a/third_party/blink/web_tests/wake-lock/wakelockpermissiondescriptor.https.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -promise_test(async t => { - await internals.setPermission({name: 'system-wake-lock'}, 'denied', - location.origin, location.origin); - - return navigator.permissions.query({ name: 'system-wake-lock' }).then(status => { - assert_class_string(status, "PermissionStatus"); - assert_equals(status.state, "denied"); - }); -}, "PermissionDescriptor with name='system-wake-lock' works"); -</script>
diff --git a/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/construction-new-in-process.js b/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/construction-new-in-process.js new file mode 100644 index 0000000..4e2cadc --- /dev/null +++ b/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/construction-new-in-process.js
@@ -0,0 +1,16 @@ +class NewInProcess extends AudioWorkletProcessor { + constructor() { + super(); + this.message = {threw: false}; + } + process(inputs, outputs, parameters){ + try { + new AudioWorkletProcessor(); + } catch (e) { + this.message.threw = true; + this.message.errorName = e.name; + this.port.postMessage(this.message); + } + } +} +registerProcessor("new-in-process", NewInProcess);
diff --git a/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/invalid-audioworkletprocessor-constructor.html b/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/invalid-audioworkletprocessor-constructor.html new file mode 100644 index 0000000..d2183f1 --- /dev/null +++ b/third_party/blink/web_tests/webaudio/AudioWorkletProcessor/invalid-audioworkletprocessor-constructor.html
@@ -0,0 +1,21 @@ +<!doctype html> +<title>Test invalid usage of AudioWorkletProcessor constructor</title> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> +<script> + // A TypeError should be thrown when the AudioWorkletProcessor constructor is + // directly invoked in AudioWorkletGlobalScope without a matching + // AudioWorkletNode. See crbug.com/1234763 for more details. + + promise_test(async () => { + const context = new AudioContext(); + await context.audioWorklet.addModule('construction-new-in-process.js'); + const node = new AudioWorkletNode(context, 'new-in-process'); + const event = await new Promise((resolve) => { + node.port.onmessage = resolve; + }); + assert_true(event.data.threw, `The AudioWorkletProcessor constructor should throw.`); + assert_equals(event.data.errorName, "TypeError"); + }, 'Invoking the AudioWorkletProcessor constructor directly in AudioWorkletGlobalScope.'); + +</script>
diff --git a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt index 611d0d6..36c2ff1 100644 --- a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
@@ -448,6 +448,7 @@ toggleTrigger toggleVisibility top +topLayer touchAction transform transformBox
diff --git a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt index bb59aca..ad6bf36 100644 --- a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
@@ -387,6 +387,7 @@ toggle-trigger toggle-visibility top + top-layer touch-action transform transform-box
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 52baa54..1a20612 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -3502,8 +3502,33 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] [NAMESPACES] +[Worker] namespace console +[Worker] attribute @@toStringTag +[Worker] method assert +[Worker] method clear +[Worker] method context +[Worker] method count +[Worker] method countReset +[Worker] method createTask +[Worker] method debug +[Worker] method dir +[Worker] method dirxml +[Worker] method error +[Worker] method group +[Worker] method groupCollapsed +[Worker] method groupEnd +[Worker] method info +[Worker] method log +[Worker] method profile +[Worker] method profileEnd +[Worker] method table +[Worker] method time +[Worker] method timeEnd +[Worker] method timeLog +[Worker] method timeStamp +[Worker] method trace +[Worker] method warn [Worker] [GLOBAL OBJECT] -[Worker] attribute console [Worker] attribute globalThis [Worker] attribute internals [Worker] getter name
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 2fe020f..55757c11 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -11864,11 +11864,38 @@ method vmax method vmin method vw +namespace console + attribute @@toStringTag + getter memory + method assert + method clear + method context + method count + method countReset + method createTask + method debug + method dir + method dirxml + method error + method group + method groupCollapsed + method groupEnd + method info + method log + method profile + method profileEnd + method table + method time + method timeEnd + method timeLog + method timeStamp + method trace + method warn + setter memory [GLOBAL OBJECT] attribute GCController attribute accessibilityController attribute chrome - attribute console attribute eventSender attribute gamepadController attribute globalThis
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index 04be4fca..4a7492d 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3073,8 +3073,33 @@ [Worker] attribute @@toStringTag [Worker] method constructor [Worker] [NAMESPACES] +[Worker] namespace console +[Worker] attribute @@toStringTag +[Worker] method assert +[Worker] method clear +[Worker] method context +[Worker] method count +[Worker] method countReset +[Worker] method createTask +[Worker] method debug +[Worker] method dir +[Worker] method dirxml +[Worker] method error +[Worker] method group +[Worker] method groupCollapsed +[Worker] method groupEnd +[Worker] method info +[Worker] method log +[Worker] method profile +[Worker] method profileEnd +[Worker] method table +[Worker] method time +[Worker] method timeEnd +[Worker] method timeLog +[Worker] method timeStamp +[Worker] method trace +[Worker] method warn [Worker] [GLOBAL OBJECT] -[Worker] attribute console [Worker] attribute globalThis [Worker] attribute internals [Worker] getter name
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html index 1b99d10c..75b371d 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-deduplication.sub.https.html
@@ -25,9 +25,6 @@ }); const trigger = { - // Create event-level report to avoid verbose debug report created for - // event-level attribution. - event_trigger_data: [{}], aggregatable_trigger_data: [{ key_piece: '0x400', source_keys: ['campaignCounts'],
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-insufficient-budget.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-insufficient-budget.sub.https.html index a81095b..de162832 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-insufficient-budget.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-insufficient-budget.sub.https.html
@@ -23,9 +23,6 @@ }); const trigger = { - // Create event-level report to avoid verbose debug report created for - // event-level attribution. - event_trigger_data: [{}], aggregatable_trigger_data: [{ key_piece: '0x400', source_keys: ['campaignCounts'],
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-no-contributions.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-no-contributions.sub.https.html index 285f43a..06f800c8 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-no-contributions.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/aggregatable-report-no-contributions.sub.https.html
@@ -23,9 +23,6 @@ await registerAttributionSrc(t, { trigger : { - // Create event-level report to avoid verbose debug report created for - // event-level attribution. - event_trigger_data: [{}], aggregatable_values: { geoValue: 32768, },
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-verbose-debug-report.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-verbose-debug-report.sub.https.html index 4fd1a31..512e9d4 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-verbose-debug-report.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-verbose-debug-report.sub.https.html
@@ -16,6 +16,7 @@ await registerAttributionSrc(t, { trigger: { + event_trigger_data: [{}], debug_reporting: true, debug_key: '456', },
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/top-level-filter-data-debug-report.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/top-level-filter-data-debug-report.sub.https.html index e9af7d9e..020d08d 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/top-level-filter-data-debug-report.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/top-level-filter-data-debug-report.sub.https.html
@@ -18,6 +18,7 @@ await registerAttributionSrc(t, { trigger: { + event_trigger_data: [{}], filters: {a: ['c']}, debug_reporting: true, },
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-computed.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-computed.html new file mode 100644 index 0000000..adf321610 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-computed.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>CSS Transitions: getComputedStyle().topLayer</title> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8189"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<div id="target"></div> +<script> + test_computed_value("top-layer", "none", "none"); + // 'browser' also computes to 'none' due to this UA style while the element is + // not in the top-layer: + // + // * { top-layer: none !important } + test_computed_value("top-layer", "browser", "none"); + test_computed_value("top-layer", "initial", "none"); + test_computed_value("top-layer", "revert", "none"); + test_computed_value("top-layer", "unset", "none"); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-invalid.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-invalid.html new file mode 100644 index 0000000..73bbe4b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-invalid.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>CSS Transitions: parsing top-layer with valid values</title> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8189"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<script> + // top-layer: none | browser + test_invalid_value("top-layer", "auto"); + test_invalid_value("top-layer", "normal"); + test_invalid_value("top-layer", "none browser"); + test_invalid_value("top-layer", "none, browser"); + test_invalid_value("top-layer", "\'browser\'"); + test_invalid_value("top-layer", "\'none\'"); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-valid.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-valid.html new file mode 100644 index 0000000..dc6acb4 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/parsing/top-layer-valid.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>CSS Transitions: parsing top-layer with valid values</title> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8189"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<script> + // top-layer: none | browser + test_valid_value("top-layer", "none"); + test_valid_value("top-layer", "browser"); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-transitions/top-layer-transition-property.html b/third_party/blink/web_tests/wpt_internal/css/css-transitions/top-layer-transition-property.html new file mode 100644 index 0000000..af4844f --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-transitions/top-layer-transition-property.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>CSS Transitions: 'top-layer' is a valid transition-property value</title> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8189"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<div id="target"></div> +<script> + test_valid_value("transition-property", "top-layer"); + test_valid_value("transition", "top-layer 2s", "top-layer 2s ease 0s"); + + test_computed_value("transition-property", "top-layer"); + test_computed_value("transition", "top-layer 1s", "top-layer 1s ease 0s"); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html b/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html new file mode 100644 index 0000000..8b82006 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + 'use strict'; + + promise_test(async (t) => { + await promise_rejects_dom( + t, 'SecurityError', navigator.hid.getDevices(), + 'getDevices() should throw a SecurityError DOMException when called from a context where the top-level document has an opaque origin.'); + }, 'Calls to HID APIs from an origin with opaque top origin get blocked.'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html.headers b/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html.headers new file mode 100644 index 0000000..c7e4e7c --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/getDevices/reject_opaque_origin.https.html.headers
@@ -0,0 +1 @@ +Content-Security-Policy: sandbox allow-scripts \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/getDevices/sandboxed_iframe.https.window.js b/third_party/blink/web_tests/wpt_internal/hid/getDevices/sandboxed_iframe.https.window.js new file mode 100644 index 0000000..7d5a2802 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/getDevices/sandboxed_iframe.https.window.js
@@ -0,0 +1,22 @@ +'use strict'; + +let iframe = document.createElement('iframe'); + +promise_test(async () => { + await new Promise(resolve => { + iframe.src = '../resources/open-in-iframe.html'; + iframe.sandbox.add('allow-scripts'); + iframe.allow = 'hid'; + document.body.appendChild(iframe); + iframe.addEventListener('load', resolve); + }); + + await new Promise(resolve => { + iframe.contentWindow.postMessage({type: 'GetDevices'}, '*'); + + window.addEventListener('message', (messageEvent) => { + assert_equals(messageEvent.data, 'Success'); + resolve(); + }); + }); +}, 'Calls to HID APIs from a sandboxed iframe are valid.'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html new file mode 100644 index 0000000..6c04fbe --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + 'use strict'; + + promise_test(async (t) => { + await promise_rejects_dom( + t, 'SecurityError', navigator.hid.requestDevice({filters: [{}]}), + 'requestDevice() should throw a SecurityError DOMException when called from a context where the top-level document has an opaque origin.'); + }, 'Calls to HID APIs from an origin with opaque top origin get blocked.'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html.headers b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html.headers new file mode 100644 index 0000000..c7e4e7c --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/reject_opaque_origin.https.html.headers
@@ -0,0 +1 @@ +Content-Security-Policy: sandbox allow-scripts \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js new file mode 100644 index 0000000..41b328f --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js
@@ -0,0 +1,22 @@ +'use strict'; + +let iframe = document.createElement('iframe'); + +promise_test(async () => { + await new Promise(resolve => { + iframe.src = '../resources/open-in-iframe.html'; + iframe.sandbox.add('allow-scripts'); + iframe.allow = 'hid'; + document.body.appendChild(iframe); + iframe.addEventListener('load', resolve); + }); + + await new Promise(resolve => { + iframe.contentWindow.postMessage({type: 'RequestDevice'}, '*'); + + window.addEventListener('message', (messageEvent) => { + assert_equals(messageEvent.data, 'Success'); + resolve(); + }); + }); +}, 'Calls to HID APIs from a sandboxed iframe are valid.'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js.ini b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js.ini new file mode 100644 index 0000000..aafe66b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/requestDevice/sandboxed_iframe.https.window.js.ini
@@ -0,0 +1,4 @@ +[sandboxed_iframe.https.window.html] + expected: ERROR + [Calls to HID APIs from a sandboxed iframe are valid.] + expected: TIMEOUT
diff --git a/third_party/blink/web_tests/wpt_internal/hid/resources/open-in-iframe.html b/third_party/blink/web_tests/wpt_internal/hid/resources/open-in-iframe.html new file mode 100644 index 0000000..12ce917c658 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/hid/resources/open-in-iframe.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> + +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<body> + <button> + Fake user gesture + </button> +</body> + +<script> + test_driver.set_test_context(parent); + + window.addEventListener('message', async messageEvent => { + switch (messageEvent.data.type) { + case 'GetDevices': + navigator.hid.getDevices() + .then(devices => parent.postMessage('Success', '*')) + .catch(err => parent.postMessage(`FAIL: ${err}`, '*')); + break; + case 'RequestDevice': + await test_driver.click(document.getElementsByTagName('button')[0]); + navigator.hid.requestDevice({filters: []}) + .then(device => parent.postMessage('Success', '*')) + .catch(err => parent.postMessage(`FAIL: ${err}`, '*')); + break; + default: + parent.postMessage( + `FAIL: Bad message type: ${messageEvent.data.type}`, '*'); + } + }); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/orientation-event/motion/page-visibility.https.html b/third_party/blink/web_tests/wpt_internal/orientation-event/motion/page-visibility.https.html index b334bf7..96e3d1c 100644 --- a/third_party/blink/web_tests/wpt_internal/orientation-event/motion/page-visibility.https.html +++ b/third_party/blink/web_tests/wpt_internal/orientation-event/motion/page-visibility.https.html
@@ -4,13 +4,9 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script type="module"> -import {generateMotionData, setMainWindowHidden, setMockMotionData, waitForMotion} from '../resources/device-orientation-helpers.js'; +import {generateMotionData, setMainWindowHidden, setMockMotionData, sleep, waitForMotion} from '../resources/device-orientation-helpers.js'; import {sensor_test} from '../resources/sensor-helpers.js'; -function sleep(time_ms) { - return new Promise(resolve => window.setTimeout(resolve, time_ms)); -} - sensor_test(async (t, sensorProvider) => { const motionData = generateMotionData(0, 0, 0, 0, 0, 0, @@ -36,7 +32,7 @@ // devicemotion events fire every 16ms when active, so we sleep for a while // here to make sure we're not actually getting any events. - await sleep(100); + await sleep(t, 100); hidden = false; await setMainWindowHidden(false); return Promise.all([hiddenEventPromise, waitForMotion(motionData)]);
diff --git a/third_party/blink/web_tests/wpt_internal/orientation-event/orientation/page-visibility.https.html b/third_party/blink/web_tests/wpt_internal/orientation-event/orientation/page-visibility.https.html index 50fa1ad..72f5315 100644 --- a/third_party/blink/web_tests/wpt_internal/orientation-event/orientation/page-visibility.https.html +++ b/third_party/blink/web_tests/wpt_internal/orientation-event/orientation/page-visibility.https.html
@@ -4,13 +4,9 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script type="module"> -import {generateOrientationData, setMainWindowHidden, setMockOrientationData, waitForOrientation} from '../resources/device-orientation-helpers.js'; +import {generateOrientationData, setMainWindowHidden, setMockOrientationData, sleep, waitForOrientation} from '../resources/device-orientation-helpers.js'; import {sensor_test} from '../resources/sensor-helpers.js'; -function sleep(time_ms) { - return new Promise(resolve => window.setTimeout(resolve, time_ms)); -} - sensor_test(async (t, sensorProvider) => { const orientationData = generateOrientationData(1, 2, 3, false); @@ -35,7 +31,7 @@ // Sleep for a while to make sure no deviceorientation events are fired // while the page is hidden. - await sleep(100); + await sleep(t, 100); hidden = false; await setMainWindowHidden(false); return Promise.all([hiddenEventPromise, waitForOrientation(orientationData)]);
diff --git a/third_party/blink/web_tests/wpt_internal/orientation-event/resources/device-orientation-helpers.js b/third_party/blink/web_tests/wpt_internal/orientation-event/resources/device-orientation-helpers.js index d4d49de..f8b2634 100644 --- a/third_party/blink/web_tests/wpt_internal/orientation-event/resources/device-orientation-helpers.js +++ b/third_party/blink/web_tests/wpt_internal/orientation-event/resources/device-orientation-helpers.js
@@ -30,6 +30,10 @@ // Device[Orientation|Motion]EventPump treat NaN as a missing value. let nullToNan = x => (x === null ? NaN : x); +export function sleep(t, timeMs) { + return new Promise(resolve => t.step_timeout(resolve, timeMs)); +} + export function setMockMotionData(sensorProvider, motionData) { const degToRad = Math.PI / 180; return Promise.all([
diff --git a/third_party/blink/web_tests/wpt_internal/system-wake-lock/permission-descriptor.https.window.js b/third_party/blink/web_tests/wpt_internal/system-wake-lock/permission-descriptor.https.window.js new file mode 100644 index 0000000..1c6d9bab --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/system-wake-lock/permission-descriptor.https.window.js
@@ -0,0 +1,12 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js + +promise_test(async t => { + await test_driver.set_permission({name: 'system-wake-lock'}, 'denied'); + + return navigator.permissions.query({name: 'system-wake-lock'}) + .then(status => { + assert_class_string(status, 'PermissionStatus'); + assert_equals(status.state, 'denied'); + }); +}, 'PermissionDescriptor with name=\'system-wake-lock\' works');
diff --git a/third_party/jdk/OWNERS b/third_party/jdk/OWNERS index a0e0826..b7847c2b 100644 --- a/third_party/jdk/OWNERS +++ b/third_party/jdk/OWNERS
@@ -1,2 +1,3 @@ agrieve@chromium.org +smaier@chromium.org wnwen@chromium.org
diff --git a/third_party/jdk11/BUILD.gn b/third_party/jdk11/BUILD.gn new file mode 100644 index 0000000..19c2f73 --- /dev/null +++ b/third_party/jdk11/BUILD.gn
@@ -0,0 +1,12 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +group("java_data") { + data = [ + "current/bin/java", + "current/conf/", + "current/jmods/", + "current/lib/", + ] +}
diff --git a/third_party/jdk11/OWNERS b/third_party/jdk11/OWNERS new file mode 100644 index 0000000..655c643 --- /dev/null +++ b/third_party/jdk11/OWNERS
@@ -0,0 +1 @@ +file://third_party/jdk/OWNERS
diff --git a/third_party/jdk11/README.chromium b/third_party/jdk11/README.chromium new file mode 100644 index 0000000..f736caf --- /dev/null +++ b/third_party/jdk11/README.chromium
@@ -0,0 +1,14 @@ +Name: Java Development Kit +Short Name: JDK +URL: https://openjdk.java.net/ +Version: 11.0.15+10.cr0 +License: GPL v2 +License File: NOT_SHIPPED +Security Critical: no + +Description: +This is a legacy version of the JDK. Please use //third_party/jdk. This is just +for tools which are broken on newer versions of the JDK. + +Local Modifications: +None
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index be9157d..f4228b2 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 7f34968b7850b2bd575601bcab8f745220cab8ff +Version: f4d85f9b9012fda464c06d7dc9881c02af7a6055 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/rust/cxx/chromium_integration/rust_cxx.gni b/third_party/rust/cxx/chromium_integration/rust_cxx.gni index 7e7c873..4636b2c 100644 --- a/third_party/rust/cxx/chromium_integration/rust_cxx.gni +++ b/third_party/rust/cxx/chromium_integration/rust_cxx.gni
@@ -89,8 +89,14 @@ output_h = "{{source_gen_dir}}/{{source_file_part}}.h" output_cc = "{{source_gen_dir}}/{{source_file_part}}.cc" - cxxbridge_target = - "//third_party/rust/cxxbridge_cmd/v1:cxxbridge($host_toolchain)" + # Below we use $host_toolchain_no_sanitizers rather than $host_toolchain. + # Usually this is the same thing, but in sanitizer builds, + # host_toolchain_no_sanitizers won't have the sanitizers. + # In this case, it's fine either way, so we can choose whichever + # is the quicker to build, based on sharing C++ dependencies with + # $host_toolchain, or sharing Rust dependencies with proc macros + # using $host_toolchain_no_sanitizers. + cxxbridge_target = "//third_party/rust/cxxbridge_cmd/v1:cxxbridge($host_toolchain_no_sanitizers)" cxxbridge_out_dir = get_label_info(cxxbridge_target, "root_out_dir") cxxbridge_executable = "${cxxbridge_out_dir}/cxxbridge"
diff --git a/third_party/zlib/CMakeLists.txt b/third_party/zlib/CMakeLists.txt new file mode 100644 index 0000000..7241fb3 --- /dev/null +++ b/third_party/zlib/CMakeLists.txt
@@ -0,0 +1,229 @@ +cmake_minimum_required(VERSION 3.0) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +project(zlib C) + +set(VERSION "1.2.13") + +set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF) + +# TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx) +# and architectures (e.g. Arm). +if (ENABLE_SIMD_OPTIMIZATIONS) + add_definitions(-DINFLATE_CHUNK_SIMD_SSE2) + add_definitions(-DADLER32_SIMD_SSSE3) + add_definitions(-DINFLATE_CHUNK_READ_64LE) + add_definitions(-DCRC32_SIMD_SSE42_PCLMUL) + add_definitions(-DDEFLATE_SLIDE_HASH_SSE2) + add_compile_options(-msse4.2 -mpclmul) + # Required by CPU features detection code. + add_definitions(-DX86_NOT_WINDOWS) +endif() + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + + +#============================================================================ +# Update list of source files if optimizations were enabled +#============================================================================ +if (ENABLE_SIMD_OPTIMIZATIONS) + list(REMOVE_ITEM ZLIB_SRCS inflate.c) + + list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.h) + list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/chunkcopy.h) + list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h) + list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.h) + list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.h) + + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.c) + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c) + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inflate.c) + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.c) + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.c) + list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc_folding.c) +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) +set_target_properties(zlib PROPERTIES SOVERSION 1) + +if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version + # encoded into their final filename. We disable this on Cygwin because + # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll + # seems to be the default. + # + # This has no effect with MSVC, on that platform the version info for + # the DLL comes from the resource file win32/zlib1.rc + set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) +endif() + +if(UNIX) + # On unix-like platforms the library is almost always called libz + set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +elseif(BUILD_SHARED_LIBS AND WIN32) + # Creates zlib1.dll when building shared library version + set_target_properties(zlib PROPERTIES SUFFIX "1.dll") +endif() + +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) + install(TARGETS zlib zlibstatic + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) +endif() +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") +endif() + +#============================================================================ +# Benchmarker +#============================================================================ +enable_language(CXX) +set(CMAKE_CXX_STANDARD 14) # workaround for older compilers (e.g. g++ 5.4). +add_executable(zlib_bench contrib/bench/zlib_bench.cc) +target_link_libraries(zlib_bench zlib)
diff --git a/third_party/zlib/patches/0010-cmake-enable-simd.patch b/third_party/zlib/patches/0010-cmake-enable-simd.patch new file mode 100644 index 0000000..77f7f88 --- /dev/null +++ b/third_party/zlib/patches/0010-cmake-enable-simd.patch
@@ -0,0 +1,91 @@ +diff --git a/third_party/zlib/CMakeLists.txt b/third_party/zlib/CMakeLists.txt +index b412dc7feb732..7241fb3e301ac 100644 +--- a/third_party/zlib/CMakeLists.txt ++++ b/third_party/zlib/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 2.4.4) ++cmake_minimum_required(VERSION 3.0) + set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + + project(zlib C) +@@ -21,6 +21,21 @@ check_include_file(sys/types.h HAVE_SYS_TYPES_H) + check_include_file(stdint.h HAVE_STDINT_H) + check_include_file(stddef.h HAVE_STDDEF_H) + ++option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF) ++ ++# TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx) ++# and architectures (e.g. Arm). ++if (ENABLE_SIMD_OPTIMIZATIONS) ++ add_definitions(-DINFLATE_CHUNK_SIMD_SSE2) ++ add_definitions(-DADLER32_SIMD_SSSE3) ++ add_definitions(-DINFLATE_CHUNK_READ_64LE) ++ add_definitions(-DCRC32_SIMD_SSE42_PCLMUL) ++ add_definitions(-DDEFLATE_SLIDE_HASH_SSE2) ++ add_compile_options(-msse4.2 -mpclmul) ++ # Required by CPU features detection code. ++ add_definitions(-DX86_NOT_WINDOWS) ++endif() ++ + # + # Check to see if we have large file support + # +@@ -120,10 +135,25 @@ set(ZLIB_SRCS + zutil.c + ) + +-if(NOT MINGW) +- set(ZLIB_DLL_SRCS +- win32/zlib1.rc # If present will override custom build rule below. +- ) ++ ++#============================================================================ ++# Update list of source files if optimizations were enabled ++#============================================================================ ++if (ENABLE_SIMD_OPTIMIZATIONS) ++ list(REMOVE_ITEM ZLIB_SRCS inflate.c) ++ ++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.h) ++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/chunkcopy.h) ++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.h) ++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.h) ++ list(APPEND ZLIB_PRIVATE_HDRS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.h) ++ ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/adler32_simd.c) ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inffast_chunk.c) ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/contrib/optimizations/inflate.c) ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/cpu_features.c) ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc32_simd.c) ++ list(APPEND ZLIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/crc_folding.c) + endif() + + # parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +@@ -191,23 +221,9 @@ if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + endif() + + #============================================================================ +-# Example binaries ++# Benchmarker + #============================================================================ +- +-add_executable(example test/example.c) +-target_link_libraries(example zlib) +-add_test(example example) +- +-add_executable(minigzip test/minigzip.c) +-target_link_libraries(minigzip zlib) +- +-if(HAVE_OFF64_T) +- add_executable(example64 test/example.c) +- target_link_libraries(example64 zlib) +- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +- add_test(example64 example64) +- +- add_executable(minigzip64 test/minigzip.c) +- target_link_libraries(minigzip64 zlib) +- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +-endif() ++enable_language(CXX) ++set(CMAKE_CXX_STANDARD 14) # workaround for older compilers (e.g. g++ 5.4). ++add_executable(zlib_bench contrib/bench/zlib_bench.cc) ++target_link_libraries(zlib_bench zlib)
diff --git a/third_party/zlib/zconf.h.cmakein b/third_party/zlib/zconf.h.cmakein new file mode 100644 index 0000000..247ba24 --- /dev/null +++ b/third_party/zlib/zconf.h.cmakein
@@ -0,0 +1,549 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +#cmakedefine Z_PREFIX +#cmakedefine Z_HAVE_UNISTD_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_combine_gen z_crc32_combine_gen +# define crc32_combine_gen64 z_crc32_combine_gen64 +# define crc32_combine_op z_crc32_combine_op +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include <stddef.h> + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include <limits.h> +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include <sys/types.h> /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include <stdarg.h> /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include <stddef.h> /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#ifndef Z_HAVE_UNISTD_H +# ifdef __WATCOMC__ +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_HAVE_UNISTD_H +# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) +# define Z_HAVE_UNISTD_H +# endif +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) +# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */
diff --git a/third_party/zlib/zlib.3 b/third_party/zlib/zlib.3 new file mode 100644 index 0000000..6f6e914 --- /dev/null +++ b/third_party/zlib/zlib.3
@@ -0,0 +1,149 @@ +.TH ZLIB 3 "13 Oct 2022" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I test/example.c +and +.IR test/minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is built in to many languages and operating systems, including but not limited to +Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. +.LP +An experimental package to read and write files in the .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the +.I zlib +library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) +.br +http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) +.br +http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS AND LICENSE +Version 1.2.13 +.LP +Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler +.LP +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. +.LP +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +.LP +.nr step 1 1 +.IP \n[step]. 3 +The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +.IP \n+[step]. +Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +.IP \n+[step]. +This notice may not be removed or altered from any source distribution. +.LP +Jean-loup Gailly Mark Adler +.br +jloup@gzip.org madler@alumni.caltech.edu +.LP +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page
diff --git a/third_party/zlib/zlib.map b/third_party/zlib/zlib.map new file mode 100644 index 0000000..b330b60 --- /dev/null +++ b/third_party/zlib/zlib.map
@@ -0,0 +1,100 @@ +ZLIB_1.2.0 { + global: + compressBound; + deflateBound; + inflateBack; + inflateBackEnd; + inflateBackInit_; + inflateCopy; + local: + deflate_copyright; + inflate_copyright; + inflate_fast; + inflate_table; + zcalloc; + zcfree; + z_errmsg; + gz_error; + gz_intmax; + _*; +}; + +ZLIB_1.2.0.2 { + gzclearerr; + gzungetc; + zlibCompileFlags; +} ZLIB_1.2.0; + +ZLIB_1.2.0.8 { + deflatePrime; +} ZLIB_1.2.0.2; + +ZLIB_1.2.2 { + adler32_combine; + crc32_combine; + deflateSetHeader; + inflateGetHeader; +} ZLIB_1.2.0.8; + +ZLIB_1.2.2.3 { + deflateTune; + gzdirect; +} ZLIB_1.2.2; + +ZLIB_1.2.2.4 { + inflatePrime; +} ZLIB_1.2.2.3; + +ZLIB_1.2.3.3 { + adler32_combine64; + crc32_combine64; + gzopen64; + gzseek64; + gztell64; + inflateUndermine; +} ZLIB_1.2.2.4; + +ZLIB_1.2.3.4 { + inflateReset2; + inflateMark; +} ZLIB_1.2.3.3; + +ZLIB_1.2.3.5 { + gzbuffer; + gzoffset; + gzoffset64; + gzclose_r; + gzclose_w; +} ZLIB_1.2.3.4; + +ZLIB_1.2.5.1 { + deflatePending; +} ZLIB_1.2.3.5; + +ZLIB_1.2.5.2 { + deflateResetKeep; + gzgetc_; + inflateResetKeep; +} ZLIB_1.2.5.1; + +ZLIB_1.2.7.1 { + inflateGetDictionary; + gzvprintf; +} ZLIB_1.2.5.2; + +ZLIB_1.2.9 { + inflateCodesUsed; + inflateValidate; + uncompress2; + gzfread; + gzfwrite; + deflateGetDictionary; + adler32_z; + crc32_z; +} ZLIB_1.2.7.1; + +ZLIB_1.2.12 { + crc32_combine_gen; + crc32_combine_gen64; + crc32_combine_op; +} ZLIB_1.2.9;
diff --git a/third_party/zlib/zlib.pc.cmakein b/third_party/zlib/zlib.pc.cmakein new file mode 100644 index 0000000..a5e6429 --- /dev/null +++ b/third_party/zlib/zlib.pc.cmakein
@@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@INSTALL_LIB_DIR@ +sharedlibdir=@INSTALL_LIB_DIR@ +includedir=@INSTALL_INC_DIR@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir}
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml index 36fd95b..712c731 100644 --- a/tools/android/checkstyle/chromium-style-5.0.xml +++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -187,5 +187,13 @@ <property name="ignoreComments" value="true"/> <property name="message" value="Use java.util.Optional instead of com.google.common.base.Optional unless required to interact with external libraries."/> </module> + <module name="RegexpSinglelineJava"> + <property name="id" value="CollectionSubclass"/> + <property name="severity" value="warning"/> + <!-- E.g., matches "new HashSet<>() {" --> + <property name="format" value="new \w+(?:List|Set|Map)\b.*\{"/> + <property name="ignoreComments" value="true"/> + <property name="message" value="Subclassing collections is uncommon. If you are not doing so, please ignore. If you are subclassing in order to call add()/put(), use List.of() / Set.of() / Map.of() instead, or use multiple statements."/> + </module> </module> </module>
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 3d6e186..fc5a6bb 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -1097,8 +1097,7 @@ # Sorting must happen after normalization. logging.info('Sorting symbols') for raw_symbols in raw_symbols_list: - if file_format.LogUnsortedSymbols(raw_symbols) > 0: - file_format.SortSymbols(raw_symbols) + file_format.SortSymbols(raw_symbols) logging.debug('Accumulating symbols') # Containers should always have at least one symbol.
diff --git a/tools/binary_size/libsupersize/file_format.py b/tools/binary_size/libsupersize/file_format.py index 406eb67..e4f28819 100644 --- a/tools/binary_size/libsupersize/file_format.py +++ b/tools/binary_size/libsupersize/file_format.py
@@ -111,38 +111,6 @@ return ''.join('%r: %r\n' % (_SortKey(s), s) for s in syms) -def LogUnsortedSymbols(raw_symbols): - """Logs the number of symbols that are not sorted. - - Also logs the first few such symbols and their sort keys. - - Returns: - The number of unsorted symbols. - """ - logging.debug('Looking for out-of-order symbols (num_symbols=%d)', - len(raw_symbols)) - sort_keys = [_SortKey(s) for s in raw_symbols] - count = sum( - int(sort_keys[i] > sort_keys[i + 1]) for i in range(len(raw_symbols) - 1)) - logging.info('Out of %d symbols, %d were out-of-order.', len(raw_symbols), - count) - - # Log them if > 1% are out-of-order and it's not a tiny sample. - if len(raw_symbols) > 1000 and count / len(raw_symbols) > .01: - NUM_TO_LOG = 10 - logging.warning('Showing the first %d out-of-order symbols.', NUM_TO_LOG) - num_reported = 0 - for i in range(len(raw_symbols) - 1): - if sort_keys[i] > sort_keys[i + 1]: - num_reported += 1 - logging.warning('\n%d) %s\n%d) %s\n', i, - _DescribeSymbolSortOrder(raw_symbols[i:i + 1]), i + 1, - _DescribeSymbolSortOrder(raw_symbols[i + 1:i + 2])) - if num_reported == NUM_TO_LOG: - break - return count - - def SortSymbols(raw_symbols): """Sorts the given symbols in the order that they should be archived in.
diff --git a/tools/binary_size/libsupersize/viewer/imports/externals.d.ts b/tools/binary_size/libsupersize/viewer/imports/externals.d.ts index 6cd5fb77..6f493cf 100644 --- a/tools/binary_size/libsupersize/viewer/imports/externals.d.ts +++ b/tools/binary_size/libsupersize/viewer/imports/externals.d.ts
@@ -8,17 +8,18 @@ */ // Google APIs definitions. -declare namespace gapi { - function load(string, Func): any; - function client(): any; - - declare namespace auth2 { - function getAuthInstance(): any; +declare namespace google { + declare namespace accounts { + declare namespace oauth2 { + function revoke(string, Func): void; + function initTokenClient({}): TokenClient; + } } +} - declare namespace client { - function init(Object): any; - } +interface TokenClient { + requestAccessToken: Func; + callback: Func; } // Emscripten definitions.
diff --git a/tools/binary_size/libsupersize/viewer/imports/window.d.ts b/tools/binary_size/libsupersize/viewer/imports/window.d.ts index 43d1d7ae..c91553a 100644 --- a/tools/binary_size/libsupersize/viewer/imports/window.d.ts +++ b/tools/binary_size/libsupersize/viewer/imports/window.d.ts
@@ -11,7 +11,7 @@ // Global `window` context. declare global { interface Window { - onAuthScriptLoaded: any; + initClient: Func; supersize: any; } }
diff --git a/tools/binary_size/libsupersize/viewer/static/auth.js b/tools/binary_size/libsupersize/viewer/static/auth.js index 18811b0d..cafed8b 100644 --- a/tools/binary_size/libsupersize/viewer/static/auth.js +++ b/tools/binary_size/libsupersize/viewer/static/auth.js
@@ -4,66 +4,71 @@ 'use strict'; -/** @type {Promise} Resolves when gapi.js is loaded. */ + +/** @type {(a: TokenClient) => void} Resolve function of g_authScriptPromise. */ +let g_onAuthScriptLoaded = null; +/** @type {Promise<TokenClient>} Resolves when GIS is loaded. */ const g_authScriptPromise = new Promise((resolve, reject) => { - window.onAuthScriptLoaded = resolve; + g_onAuthScriptLoaded = resolve; }); -/** @type {?Promise} Resolves when auth has completed. */ -let g_doAuthPromise = null; +/** @type {(a: string) => void} Resolve function of g_authTokenPromise. */ +let g_onTokenReceived = null; +/** @type {Promise<string>} Resolves when access token is received. */ +const g_authTokenPromise = new Promise((resolve, reject) => { + g_onTokenReceived = resolve; +}); + +/** @type {boolean} Used to ensure the auth pipeline is only setup once. */ +let g_authFetchCalled = false; /** @return {Promise<*>} */ -async function initAuthApi() { - await g_authScriptPromise; - await new Promise((resolve, reject) => { - gapi.load('client:auth2', resolve); +async function initClient() { + let tokenClient = google.accounts.oauth2.initTokenClient({ + client_id: AUTH_CLIENT_ID, + scope: AUTH_SCOPE, + callback: '', // defined at request time in await/promise scope. }); - await gapi.client.init({ - 'clientId': AUTH_CLIENT_ID, - 'discoveryDocs': [AUTH_DISCOVERY_URL], - 'scope': AUTH_SCOPE, - }) - return gapi.auth2.getAuthInstance(); + g_onAuthScriptLoaded(tokenClient); } -/** @return {Promise<*>} */ -async function doAuthFetch() { - let googleAuth = await initAuthApi(); - - // See if already signed in. - if (googleAuth.isSignedIn.get()) { - return googleAuth.currentUser.get(); +/** @return {Promise<void>} */ +async function getToken() { + let tokenClient = await g_authScriptPromise; + try { + tokenClient.callback = (resp) => { + if (resp.error === undefined) { + g_onTokenReceived(resp.access_token); + } + }; + tokenClient.requestAccessToken(); + } catch (err) { + console.error(err) } +} + +/** @return {Promise<void>} */ +async function doAuthFetch() { + // TODO(mheikal): cache access token in localstorage and check if expired here + // and return cached token. // Show a "Please sign in" dialog. toggleSigninModal(true /*show*/); + let signinButton = document.querySelector('#signin-modal button.signin'); + signinButton.addEventListener('click', getToken); - // Loop in case the pop-up dialog is closed without signing in. - while (true) { - await new Promise((resolve, reject) => { - let signinButton = document.querySelector('#signin-modal button.signin'); - signinButton.addEventListener('click', resolve, {once: true}); - }); - - try { - await googleAuth.signIn(); - break; - } catch { - // Allow them to click dialog button again. - } - } + // Only hide the dialog once we have the token. + await g_authTokenPromise; toggleSigninModal(false /*show*/); - - return googleAuth.currentUser.get(); } /** @return {Promise<?string>} */ async function fetchAccessToken() { - if (!g_doAuthPromise) { - g_doAuthPromise = doAuthFetch(); + if (!g_authFetchCalled) { + doAuthFetch(); + g_authFetchCalled = true; } - let user = await g_doAuthPromise; - return user.getAuthResponse().access_token; + return await g_authTokenPromise; } /** @param {boolean} show */
diff --git a/tools/binary_size/libsupersize/viewer/static/viewer.html b/tools/binary_size/libsupersize/viewer/static/viewer.html index e537551..6e078aa 100644 --- a/tools/binary_size/libsupersize/viewer/static/viewer.html +++ b/tools/binary_size/libsupersize/viewer/static/viewer.html
@@ -24,10 +24,7 @@ <script defer src="state.js"></script> <script defer src="infocard-ui.js"></script> <script defer src="tree-ui.js"></script> - <script defer src="https://apis.google.com/js/api.js" - onload="this.onload=function(){};onAuthScriptLoaded()" - onreadystatechange="if (this.readyState === 'complete') this.onload()"> - </script> + <script async defer src="https://accounts.google.com/gsi/client" onload="initClient()"></script> <script async> if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js')
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py index d36da39e..aef9ce8 100755 --- a/tools/clang/scripts/build.py +++ b/tools/clang/scripts/build.py
@@ -49,9 +49,9 @@ 'sdk') PINNED_CLANG_DIR = os.path.join(LLVM_BUILD_TOOLS_DIR, 'pinned-clang') -BUG_REPORT_URL = ('https://crbug.com and run' - ' tools/clang/scripts/process_crashreports.py' - ' (only works inside Google) which will upload a report') +BUG_REPORT_URL = ('https://crbug.com in the Tools>LLVM component,' + ' run tools/clang/scripts/process_crashreports.py' + ' (only if inside Google) to upload crash related files,') LIBXML2_VERSION = 'libxml2-v2.9.12'
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index 418be8e..919e045 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -582,7 +582,7 @@ FuzzParam(&low, fuzzer); FuzzParam(&high, fuzzer); } - *p = base::UnguessableToken::Deserialize2(high, low).value(); + *p = base::UnguessableToken::Deserialize(high, low).value(); return true; } }; @@ -1560,7 +1560,7 @@ high = RandU64(); low = RandU64(); } - token = base::UnguessableToken::Deserialize2(high, low).value(); + token = base::UnguessableToken::Deserialize(high, low).value(); } if (!FuzzParam(&(*token), fuzzer)) return false;
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 80794f4..295eb3b5 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -902,13 +902,13 @@ # cause them to produce different baselines than the release # waterfall bots, and run_web_tests.py can't handle that (by design). 'linux-blink-rel': 'release_bot_blink_minimal_symbols_reclient', - 'mac10.13-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl', - 'mac10.14-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl', + 'mac10.13-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl_reclient', + 'mac10.14-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl_reclient', 'mac10.15-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl_reclient', - 'mac11.0-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl', + 'mac11.0-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl_reclient', 'mac11.0.arm64-blink-rel': 'release_bot_blink_arm64_minimal_symbols_reclient', 'mac12.0-blink-rel': 'release_bot_blink_minimal_symbols_no_nacl_reclient', - 'mac12.0.arm64-blink-rel': 'release_bot_blink_arm64_minimal_symbols', + 'mac12.0.arm64-blink-rel': 'release_bot_blink_arm64_minimal_symbols_reclient', 'win10.20h2-blink-rel': 'release_bot_blink_x86_minimal_symbols_reclient', 'win11-blink-rel': 'release_bot_blink_x64_minimal_symbols_reclient', }, @@ -978,7 +978,7 @@ 'android-official': 'android_official_optimize_reclient_trybot', 'fuchsia-official': 'fuchsia_official_optimize_reclient_trybot', 'linux-official': 'official_optimize_reclient_trybot', - 'mac-official': 'official_optimize_goma_trybot', + 'mac-official': 'official_optimize_reclient_trybot', 'win-official': 'official_optimize_reclient_trybot', 'win32-official': 'x86_official_optimize_reclient_trybot', }, @@ -1268,7 +1268,7 @@ 'ios-simulator-code-coverage': 'clang_code_coverage_ios_xctest', 'ios-simulator-cr-recipe': 'ios_simulator_debug_static_bot_xctest', 'ios-simulator-cronet': 'ios_cronet_xctest_reclient', - 'ios-simulator-full-configs': 'ios_simulator_code_coverage_partial_instrumentation_xctest_reclient', + 'ios-simulator-full-configs': 'ios_simulator_code_coverage_partial_instrumentation_xctest', 'ios-simulator-inverse-fieldtrials-fyi': 'ios_simulator_debug_static_bot_invert_fieldtrials_xctest', 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_xctest', 'ios-simulator-noncq': 'ios_simulator_debug_static_bot_xctest_reclient', @@ -1277,29 +1277,31 @@ 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_reclient', 'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest_reclient', 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_reclient', - 'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot', - 'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl', + 'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot_reclient', + 'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', 'mac-code-coverage': 'clang_code_coverage', 'mac-fieldtrial-tester': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl', 'mac-inverse-fieldtrials-fyi-rel': 'gpu_tests_release_trybot_invert_fieldtrials', - 'mac-osxbeta-rel': 'gpu_tests_debug_trybot', + 'mac-osxbeta-rel': 'gpu_tests_debug_trybot_reclient', 'mac-perfetto-rel': 'perfetto_release_trybot', - 'mac-rel': 'gpu_tests_release_trybot_no_symbols_mac_code_coverage_reclient', + 'mac-rel': 'gpu_tests_release_trybot_no_symbols_mac_code_coverage', 'mac-rel-inverse-fyi': 'gpu_tests_release_trybot_no_symbols_mac_code_coverage_reclient', 'mac10.15-wpt-content-shell-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'mac11-arm64-rel': 'mac_arm64_gpu_tests_release_trybot_no_symbols_reclient', + 'mac11-wpt-content-shell-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'mac12-arm64-rel': 'mac_arm64_gpu_tests_release_trybot_no_symbols', + 'mac12-arm64-wpt-content-shell-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'mac12-tests': 'release_trybot', 'mac12-wpt-content-shell-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'mac_chromium_10.13_rel_ng': 'release_trybot', - 'mac_chromium_10.14_rel_ng': 'release_trybot', - 'mac_chromium_10.15_rel_ng': 'release_trybot_no_nacl', + 'mac_chromium_10.14_rel_ng': 'release_trybot_reclient', + 'mac_chromium_10.15_rel_ng': 'release_trybot_no_nacl_reclient', 'mac_chromium_11.0_rel_ng': 'release_trybot_reclient', - 'mac_chromium_archive_rel_ng': 'release_bot_mac_strip_minimal_symbols', + 'mac_chromium_archive_rel_ng': 'release_bot_mac_strip_minimal_symbols_reclient', 'mac_chromium_asan_rel_ng': 'asan_dcheck_disable_nacl_release_bot_reclient', - 'mac_chromium_compile_dbg_ng': 'gpu_tests_debug_bot_reclient', - 'mac_chromium_compile_rel_ng': 'gpu_tests_release_trybot', - 'mac_chromium_dbg_ng': 'gpu_tests_debug_bot', + 'mac_chromium_compile_dbg_ng': 'gpu_tests_debug_bot', + 'mac_chromium_compile_rel_ng': 'gpu_tests_release_trybot_reclient', + 'mac_chromium_dbg_ng': 'gpu_tests_debug_bot_reclient', 'mac_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot_reclient', 'mac_upload_clang': 'release_bot', 'mac_upload_clang_arm': 'release_bot', @@ -1355,8 +1357,8 @@ }, 'tryserver.chromium.updater': { - 'mac-updater-try-builder-dbg': 'updater_debug_bot', - 'mac-updater-try-builder-rel': 'updater_release_trybot', + 'mac-updater-try-builder-dbg': 'updater_debug_bot_reclient', + 'mac-updater-try-builder-rel': 'updater_release_trybot_reclient', 'win-updater-try-builder-dbg': 'updater_debug_bot_reclient', 'win-updater-try-builder-rel': 'updater_release_trybot_reclient', }, @@ -2705,8 +2707,8 @@ 'gpu_tests', 'debug_bot_reclient', 'x86', 'no_symbols' ], - 'gpu_tests_debug_trybot': [ - 'gpu_tests', 'debug', 'no_symbols', 'dcheck_always_on', 'static', 'goma' + 'gpu_tests_debug_trybot_reclient': [ + 'gpu_tests', 'debug', 'no_symbols', 'dcheck_always_on', 'static', 'reclient' ], 'gpu_tests_ozone_linux_non_x11_release_trybot_reclient': [ @@ -2808,6 +2810,11 @@ 'chrome_for_testing', ], + 'gpu_tests_release_trybot_no_symbols_mac_code_coverage': [ + 'gpu_tests', 'release_trybot', 'no_symbols', + 'use_clang_coverage', 'partial_code_coverage_instrumentation' + ], + 'gpu_tests_release_trybot_no_symbols_mac_code_coverage_reclient': [ 'gpu_tests', 'release_trybot_reclient', 'no_symbols', 'use_clang_coverage', 'partial_code_coverage_instrumentation' @@ -3180,8 +3187,8 @@ 'release_bot_reclient', 'arm64', ], - 'mac_arm64_release_trybot': [ - 'release_trybot', 'arm64', + 'mac_arm64_release_trybot_reclient': [ + 'release_trybot_reclient', 'arm64', ], 'mac_clang_tot_official': [ @@ -3331,10 +3338,6 @@ 'official', 'goma', 'x86', 'no_symbols', 'pgo_phase_1', 'release' ], - 'official_optimize_goma_trybot': [ - 'official_optimize_goma_trybot', - ], - 'official_optimize_minimal_symbols_reclient': [ 'official_optimize_reclient', 'minimal_symbols', ], @@ -3466,20 +3469,10 @@ 'release_bot_blink_reclient', 'dcheck_always_on', ], - 'release_bot_blink_arm64_minimal_symbols': [ - 'release_bot_blink', 'arm64', 'minimal_symbols', - ], - 'release_bot_blink_arm64_minimal_symbols_reclient': [ 'release_bot_blink_reclient', 'arm64', 'minimal_symbols', ], - 'release_bot_blink_minimal_symbols_no_nacl': [ - 'release_bot_blink', - 'minimal_symbols', - 'disable_nacl', - ], - 'release_bot_blink_minimal_symbols_no_nacl_reclient': [ 'release_bot_blink_reclient', 'minimal_symbols', @@ -3682,8 +3675,8 @@ 'release_trybot_minimal_symbols', 'tsan' ], - 'release_trybot_no_nacl': [ - 'release_trybot', 'disable_nacl', + 'release_trybot_no_nacl_reclient': [ + 'release_trybot_reclient', 'disable_nacl', ], 'release_trybot_reclient': [ @@ -3722,10 +3715,6 @@ 'ubsan_vptr', 'ubsan_no_recover_hack', 'release_bot_reclient', ], - 'updater_debug_bot': [ - 'updater_on_win_mac', 'debug_static_bot', - ], - 'updater_debug_bot_arm64_reclient': [ 'arm64', 'updater_on_win_mac', 'debug_static_bot_reclient', ], @@ -3754,10 +3743,6 @@ 'updater_on_win_mac', 'release_bot_reclient', 'x86', ], - 'updater_release_trybot': [ - 'updater_on_win_mac', 'release_trybot', - ], - 'updater_release_trybot_reclient': [ 'updater_on_win_mac', 'release_trybot_reclient', ], @@ -4531,14 +4516,6 @@ 'gn_args': 'is_official_build=true', }, - 'official_optimize_goma': { - 'mixins': ['official_optimize', 'goma'], - }, - - 'official_optimize_goma_trybot': { - 'mixins': ['official_optimize_goma', 'minimal_symbols', 'dcheck_always_on'], - }, - 'official_optimize_reclient': { 'mixins': ['official_optimize', 'reclient'], },
diff --git a/tools/mb/mb_config_expectations/tryserver.blink.json b/tools/mb/mb_config_expectations/tryserver.blink.json index a8d17f4a..f8f1d90 100644 --- a/tools/mb/mb_config_expectations/tryserver.blink.json +++ b/tools/mb/mb_config_expectations/tryserver.blink.json
@@ -19,7 +19,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac10.14-blink-rel": { @@ -31,7 +31,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac10.15-blink-rel": { @@ -55,7 +55,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac11.0.arm64-blink-rel": { @@ -91,7 +91,7 @@ "proprietary_codecs": true, "symbol_level": 1, "target_cpu": "arm64", - "use_goma": true + "use_remoteexec": true } }, "win10.20h2-blink-rel": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.json b/tools/mb/mb_config_expectations/tryserver.chromium.json index 630f0aa..8a21610 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.json
@@ -31,7 +31,7 @@ "dcheck_always_on": true, "is_official_build": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "win-official": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json index 2bb72a6..515b86ac 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -341,7 +341,7 @@ "target_environment": "simulator", "target_os": "ios", "use_clang_coverage": true, - "use_remoteexec": true + "use_goma": true } }, "ios-simulator-inverse-fieldtrials-fyi": { @@ -450,7 +450,7 @@ "is_debug": false, "symbol_level": 0, "target_cpu": "arm64", - "use_goma": true + "use_remoteexec": true } }, "mac-builder-next-rel": { @@ -463,7 +463,7 @@ "proprietary_codecs": true, "symbol_level": 1, "target_cpu": "arm64", - "use_goma": true + "use_remoteexec": true } }, "mac-code-coverage": { @@ -512,7 +512,7 @@ "is_debug": true, "proprietary_codecs": true, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "mac-perfetto-rel": { @@ -535,7 +535,7 @@ "proprietary_codecs": true, "symbol_level": 0, "use_clang_coverage": true, - "use_remoteexec": true + "use_goma": true } }, "mac-rel-inverse-fyi": { @@ -572,6 +572,15 @@ "use_remoteexec": true } }, + "mac11-wpt-content-shell-fyi-rel": { + "gn_args": { + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 1, + "use_remoteexec": true + } + }, "mac12-arm64-rel": { "gn_args": { "dcheck_always_on": true, @@ -584,6 +593,15 @@ "use_goma": true } }, + "mac12-arm64-wpt-content-shell-fyi-rel": { + "gn_args": { + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 1, + "use_remoteexec": true + } + }, "mac12-tests": { "gn_args": { "dcheck_always_on": true, @@ -617,7 +635,7 @@ "is_component_build": false, "is_debug": false, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "mac_chromium_10.15_rel_ng": { @@ -627,7 +645,7 @@ "is_component_build": false, "is_debug": false, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "mac_chromium_11.0_rel_ng": { @@ -646,7 +664,7 @@ "is_component_build": false, "is_debug": false, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac_chromium_asan_rel_ng": { @@ -666,7 +684,7 @@ "is_debug": true, "proprietary_codecs": true, "symbol_level": 1, - "use_remoteexec": true + "use_goma": true } }, "mac_chromium_compile_rel_ng": { @@ -677,7 +695,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "mac_chromium_dbg_ng": { @@ -687,7 +705,7 @@ "is_debug": true, "proprietary_codecs": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac_optional_gpu_tests_rel": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.updater.json b/tools/mb/mb_config_expectations/tryserver.chromium.updater.json index fbeaa53..a4707498 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.updater.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.updater.json
@@ -5,7 +5,7 @@ "is_component_build": false, "is_debug": true, "symbol_level": 1, - "use_goma": true + "use_remoteexec": true } }, "mac-updater-try-builder-rel": { @@ -15,7 +15,7 @@ "is_component_build": false, "is_debug": false, "symbol_level": 0, - "use_goma": true + "use_remoteexec": true } }, "win-updater-try-builder-dbg": {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a42a04b..6d1a121e 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -9058,17 +9058,17 @@ <action name="Find"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> - <description>Please enter the description of this user action.</description> + <description>For iOS: see IOS.FindInPage.SearchStarted</description> </action> <action name="FindNext"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> - <description>Please enter the description of this user action.</description> + <description>For iOS: see IOS.FindInPage.FindNext</description> </action> <action name="FindPrevious"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> - <description>Please enter the description of this user action.</description> + <description>For iOS: see IOS.FindInPage.FindPrevious</description> </action> <action name="FindString"> @@ -11465,6 +11465,38 @@ </description> </action> +<action name="IOS.FindInPage.FindNext"> + <owner>qpubert@google.com</owner> + <owner>djean@chromium.org</owner> + <description> + The number of times the user navigated to the next match in Find in Page on + iOS. For instance, the user pressed the Next button in the system Find panel + or Chrome Find bar, or used the associated keybinding. + </description> +</action> + +<action name="IOS.FindInPage.FindPrevious"> + <owner>qpubert@google.com</owner> + <owner>djean@chromium.org</owner> + <description> + The number of times the user navigated to the previous match in Find in Page + on iOS. For instance, the user pressed the Previous button in the system + Find panel or Chrome Find bar, or used the associated keybinding. + </description> +</action> + +<action name="IOS.FindInPage.SearchStarted"> + <owner>qpubert@google.com</owner> + <owner>djean@chromium.org</owner> + <description> + The number of times the user started a new Find in Page search on iOS. This + is recorded every time the Chrome Find bar is presented and every time the + user edits the query. This is not recorded if the Find in Page variant uses + the system Find panel (bottom of the screen, right above the keyboard) as + opposed to the Chrome Find bar (top of the screen). + </description> +</action> + <action name="IOS.NTP.Doodle.Tapped"> <owner>gambard@chromium.org</owner> <owner>justincohen@chromium.org</owner> @@ -28730,6 +28762,14 @@ <description>User clicks the extensions row in safety check.</description> </action> +<action name="Settings.SafetyCheck.ReviewUnusedSitePermissions"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <description> + User clicks the button in the unused site permissions row in safety check. + </description> +</action> + <action name="Settings.SafetyCheck.Start"> <owner>rainhard@chromium.org</owner> <owner>andzaytsev@google.com</owner> @@ -33273,12 +33313,27 @@ </description> </action> -<action name="Suggestions.Tile.Tapped.StartSurface"> +<action name="Suggestions.Tile.Tapped.NewTabPage"> <owner>hanxi@chromium.org</owner> + <owner>xinyiji@chromium.org</owner> <owner>clank-start@google.com</owner> <description> - User tapped on a suggestions tile while viewing the start surface. - Android-only. + User tapped on a suggestions tile while viewing the new tab page. This is + recorded when 1) user clicks on most visited tiles; 2) long press on most + visited tiles to open in a new incognito tab. This is consistent with + Suggestions.Tile.Tapped.StartSurface on Start Surface. Android-only. + </description> +</action> + +<action name="Suggestions.Tile.Tapped.StartSurface"> + <owner>hanxi@chromium.org</owner> + <owner>xinyiji@chromium.org</owner> + <owner>clank-start@google.com</owner> + <description> + User tapped on a suggestions tile while viewing the start surface. This is + recorded when 1) user clicks on most visited tiles; 2) long press on most + visited tiles to open in a new incognito tab. This is consistent with + Suggestions.Tile.Tapped.NewTabPage on NTP. Android-only. </description> </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4ede548..1bae4037 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19377,6 +19377,7 @@ <int value="13" label="Excessive reports"/> <int value="14" label="Falsely attributed source"/> <int value="15" label="Report window has passed"/> + <int value="16" label="Not registered"/> </enum> <enum name="ConversionStorageSourceStatus"> @@ -29858,6 +29859,8 @@ <int value="3" label="COM Class not implementing the interface"/> <int value="4" label="Updater concurrency"/> <int value="5" label="User installation"/> + <int value="6" label="Missing Management service"/> + <int value="7" label="Process invalid"/> </enum> <enum name="DTKeyRotationResult"> @@ -35722,6 +35725,8 @@ label="SMARTCARDPROVIDERPRIVATE_REPORTGETSTATUSCHANGERESULT"/> <int value="1755" label="FILEMANAGERPRIVATE_RESUMEIOTASK"/> <int value="1756" label="PASSWORDSPRIVATE_GETCREDENTIALSWITHREUSEDPASSWORD"/> + <int value="1757" label="OS_TELEMETRY_GETAUDIOINFO"/> + <int value="1758" label="OS_TELEMETRY_GETMARKETINGINFO"/> </enum> <enum name="ExtensionIconState"> @@ -36934,6 +36939,12 @@ <int value="28" label="Failed to create a GATT connection in the Bluetoth platform layer. Fast Pair may retry a GATT connection following."/> + <int value="29" + label="Timed out while waiting for a response after attempt to + disconnect"/> + <int value="30" + label="Failed to connect to discovered device after pairing when the + device is known to the adapter."/> </enum> <enum name="FastPairPairingMethod"> @@ -44235,6 +44246,24 @@ <int value="2" label="Disabled"/> </enum> +<enum name="FirstRunCloudPolicyStoreState"> + <int value="0" label="Loaded before initialization"> + The cloud policy store was already loaded when the FRE intro was first + initialiazed. + </int> + <int value="1" label="Loaded successfully"> + The cloud policy store has loaded within the time delay specified in the + observer. + </int> + <int value="2" label="Not loaded in time"> + The cloud policy store did not load within the time delay specified in the + observer. + </int> + <int value="3" label="Error raised"> + The cloud policy store raised an error while loading. + </int> +</enum> + <enum name="FirstRunLaunchSource"> <summary> External applications/promotions that triggered Chrome launch and First Run. @@ -49667,6 +49696,23 @@ <int value="3" label="Training Mode"/> </enum> +<enum name="HPRTExperimentCombinedResult"> + <int value="0" label="No mechanism"/> + <int value="1" label="URL real-time only"/> + <int value="2" label="Hash database only"/> + <int value="3" label="Hash real-time only"/> + <int value="4" label="URL real-time + hash database"/> + <int value="5" label="URL real-time + hash real-time"/> + <int value="6" label="Hash database + hash real-time"/> + <int value="7" label="All mechanisms"/> +</enum> + +<enum name="HPRTExperimentUnknownNoYes"> + <int value="0" label="Unknown"/> + <int value="1" label="No"/> + <int value="2" label="Yes"/> +</enum> + <enum name="HpsTurnOnResult"> <int value="0" label="Success"/> <int value="1" label="Version Mismatch, will cause an update"/> @@ -54419,6 +54465,17 @@ <int value="2" label="keyboardUnlock()"/> </enum> +<enum name="KeyboardModifierRemappingKeys"> + <int value="0" label="Meta"/> + <int value="1" label="Control"/> + <int value="2" label="Alt"/> + <int value="3" label="Disabled"/> + <int value="4" label="CapsLock"/> + <int value="5" label="Escape"/> + <int value="6" label="Backspace"/> + <int value="7" label="Assistant"/> +</enum> + <enum name="KeychainMigrationStatus"> <int value="0" label="Migration hasn't started"/> <int value="1" label="Migration succeeded"/> @@ -58413,6 +58470,7 @@ <int value="-1575430234" label="DontPrefetchLibraries:disabled"/> <int value="-1575375861" label="enable-captive-portal-random-url"/> <int value="-1575131701" label="AppServiceAsh:disabled"/> + <int value="-1574799991" label="SkipServiceWorkerForInstallPromot:enabled"/> <int value="-1573468162" label="ClientStorageAccessContextAuditing:enabled"/> <int value="-1572010356" label="enable-privet-v3"/> <int value="-1571841513" label="enable-devtools-experiments"/> @@ -59048,6 +59106,7 @@ <int value="-1232629319" label="ResamplingScrollEvents:disabled"/> <int value="-1232521924" label="AutofillRemoveCardExpiryFromDownstreamSuggestion:disabled"/> + <int value="-1231606770" label="ChromeRefresh2023:disabled"/> <int value="-1231507397" label="NtpZeroSuggest:enabled"/> <int value="-1230678816" label="PersonalizationHub:disabled"/> <int value="-1230610048" label="SyncWifiConfigurations:disabled"/> @@ -59492,6 +59551,8 @@ <int value="-983335806" label="DelegatedCompositing:disabled"/> <int value="-983087919" label="PrioritizeCompositingAfterDelayTrials:enabled"/> + <int value="-982734304" + label="ContextMenuGoogleLensSearchOptimizations:enabled"/> <int value="-982588611" label="ShimlessRMAOsUpdate:disabled"/> <int value="-981993135" label="DesktopPWAsAdditionalWindowingControls:enabled"/> @@ -59765,6 +59826,7 @@ label="AutofillEnforceDelaysInStrikeDatabase:enabled"/> <int value="-831066457" label="IncognitoBrandConsistencyForDesktop:disabled"/> <int value="-829498062" label="HttpsFirstModeV2:disabled"/> + <int value="-826010284" label="EnterpriseReportingUI:disabled"/> <int value="-825942229" label="tab-management-experiment-type-elderberry"/> <int value="-825312041" label="CastStreamingAv1:enabled"/> <int value="-824199802" label="ContextualSearchSimplifiedServer:enabled"/> @@ -60036,6 +60098,7 @@ <int value="-678184617" label="TranslateSubFrames:disabled"/> <int value="-677978627" label="ZeroCopyTabCapture:enabled"/> <int value="-677938988" label="AssistantConsentSimplifiedText:disabled"/> + <int value="-675107321" label="ChromeVoxQ1FastTrackFeatures:enabled"/> <int value="-674804217" label="SoleIntegration:enabled"/> <int value="-674265959" label="AppPreloadService:enabled"/> <int value="-673804828" label="EnablePlayStoreAppSearch:disabled"/> @@ -60199,6 +60262,7 @@ <int value="-582570706" label="PPAPISharedImagesSwapChain:disabled"/> <int value="-581236612" label="ConnectivityDiagnosticsWebUi:disabled"/> <int value="-580897686" label="SharedHighlightingAmp:enabled"/> + <int value="-579656054" label="CCTResizableSideSheetForThirdParties:enabled"/> <int value="-579192400" label="disable-input-view"/> <int value="-577982497" label="CupsPrintersUiOverhaul:enabled"/> <int value="-577503348" label="GridTabSwitcherForTablets:disabled"/> @@ -60335,6 +60399,7 @@ <int value="-504485318" label="AutofillFixServerQueriesIfPasswordManagerIsEnabled:enabled"/> <int value="-503601144" label="UserDataSnapshot:disabled"/> + <int value="-503457958" label="SkipServiceWorkerCheckInstallOnly:enabled"/> <int value="-503430431" label="XRSandbox:enabled"/> <int value="-502004335" label="OobeHidDetectionRevamp:enabled"/> <int value="-501853726" label="MultiZoneRgbKeyboard:enabled"/> @@ -60543,6 +60608,7 @@ <int value="-371397346" label="ChromeOSSharingHub:enabled"/> <int value="-371321069" label="SyncPromoAfterSigninIntercept:enabled"/> <int value="-370876369" label="ContextualSearchLiteralTapSearch:enabled"/> + <int value="-369565225" label="SkipServiceWorkerCheckInstallOnly:disabled"/> <int value="-369150124" label="SendTabToSelfV2:enabled"/> <int value="-367474066" label="DialogTouchBar:enabled"/> <int value="-366949535" label="KeyboardShortcutViewerApp:enabled"/> @@ -61055,6 +61121,7 @@ <int value="-75418012" label="ContextualSuggestionsOptOut:disabled"/> <int value="-74964571" label="EcheCustomWidget:enabled"/> <int value="-73282711" label="EnableAppListSearchAutocomplete:enabled"/> + <int value="-72904030" label="ChromeRefresh2023:enabled"/> <int value="-72455054" label="WebVrAutopresent:disabled"/> <int value="-70595606" label="ash-enable-unified-desktop"/> <int value="-70434056" label="UseGles2ForOopR:enabled"/> @@ -61132,6 +61199,7 @@ <int value="-28079219" label="UseFakeAudioCaptureTimestamps:enabled"/> <int value="-27287076" label="DesktopPWAsTabStripSettings:disabled"/> <int value="-27213807" label="GlobalMediaControls:enabled"/> + <int value="-25303818" label="CCTResizableSideSheetForThirdParties:disabled"/> <int value="-25025176" label="PerformantSplitViewResizing:enabled"/> <int value="-24570936" label="DestroyProfileOnBrowserClose:disabled"/> <int value="-24217468" label="QuickAnswersTextAnnotator:enabled"/> @@ -61360,6 +61428,7 @@ <int value="94576028" label="LensEnableRegionSearchOnPdfViewer:disabled"/> <int value="96148142" label="SyncAndroidPromosWithAlternativeTitle:enabled"/> <int value="97091906" label="AutofillSaveCardShowNoThanks:enabled"/> + <int value="97691440" label="SkipServiceWorkerForInstallPromot:disabled"/> <int value="97764742" label="QuickAnswersForMoreLocales:disabled"/> <int value="97976428" label="CastUseBlocklistForRemotingQuery:enabled"/> <int value="98029688" label="MediaAppDisplayExif:disabled"/> @@ -61372,6 +61441,7 @@ <int value="103560544" label="ViewportHeightClientHintHeader:disabled"/> <int value="103932290" label="show-autofill-type-predictions"/> <int value="105046382" label="ParallelDownloading:disabled"/> + <int value="105164136" label="EnterpriseReportingUI:enabled"/> <int value="105284154" label="PromiseIcons:enabled"/> <int value="106235373" label="LauncherSystemInfoAnswerCards:enabled"/> <int value="106744400" label="OmniboxModernizeVisualUpdate:enabled"/> @@ -62535,6 +62605,7 @@ <int value="775148009" label="OsSettingsDeepLinking:disabled"/> <int value="777569794" label="FeedWebUi:enabled"/> <int value="777667507" label="DesktopPWAsLinkCapturing:enabled"/> + <int value="777872867" label="ChromeVoxQ1FastTrackFeatures:disabled"/> <int value="778000757" label="EnableInputEventLogging:disabled"/> <int value="779086132" label="enable-data-reduction-proxy-alt"/> <int value="779703052" label="ChromeOSAmbientMode:enabled"/> @@ -63825,6 +63896,8 @@ <int value="1532006216" label="CommerceHintAndroid:disabled"/> <int value="1532505461" label="HelpAppLauncherSearch:disabled"/> <int value="1533004890" label="CrostiniEnableDlc:enabled"/> + <int value="1533392685" + label="ContextMenuGoogleLensSearchOptimizations:disabled"/> <int value="1534222388" label="EnableEphemeralFlashPermission:enabled"/> <int value="1534386287" label="SendTabToSelfWhenSignedIn:enabled"/> <int value="1534561775" label="HeavyAdPrivacyMitigations:disabled"/> @@ -66552,6 +66625,7 @@ <int value="741" label="animation-range-start"/> <int value="742" label="animation-range-end"/> <int value="743" label="animation-composition"/> + <int value="744" label="top-layer"/> </enum> <enum name="MappedEditingCommands"> @@ -68883,6 +68957,14 @@ <int value="2" label="ntdll.dll"/> </enum> +<enum name="ModuleTypeOnStartAndNTP"> + <int value="0" label="Most visited tiles"/> + <int value="1" label="Omnibox"/> + <int value="2" label="Single tab card"/> + <int value="3" label="Feed"/> + <int value="4" label="Tab switcher button"/> +</enum> + <enum name="MojoInterfaceName"> <int value="-1403116593" label="content.mojom.FrameHost"/> <int value="-1370606112" label="blink.mojom.LocalFrameHost"/> @@ -73804,11 +73886,13 @@ <int value="0" label="Test Catalog Name"/> <int value="1" label="Dictation"/> - <int value="2" label="Multipaste"/> + <int value="2" label="Multipaste (deprecated 01/2023)"/> <int value="3" label="Dark Light Mode"/> <int value="4" label="Autozoom"/> <int value="5" label="Adaptive Charging"/> <int value="6" label="Phone Hub"/> + <int value="7" label="Clipboard History Zero State"/> + <int value="8" label="Clipboard History Onboarding"/> </enum> <enum name="NukeProfileResult"> @@ -77190,6 +77274,7 @@ <int value="21" label="Virtual Card Enroll"/> <int value="22" label="Virtual Card Manual Fallback"/> <int value="23" label="Zoom"/> + <int value="24" label="Save IBAN"/> </enum> <enum name="PageActionPageEvent"> @@ -77294,6 +77379,19 @@ <int value="1" label="Prerender Activation Navigation"/> </enum> +<enum name="PageLoadPrerenderObserverEvent"> + <int value="0" label="OnPrerenderStart"/> + <int value="1" label="DidActivatePrerenderedPage"/> + <int value="2" label="OnFirstPaintInPage"/> + <int value="3" label="OnFirstContentfulPaintInPage"/> + <int value="4" label="OnFirstInputInPage"/> + <int value="5" label="OnComplete"/> + <int value="6" label="FlushMetricsOnAppEnterBackground"/> + <int value="7" label="RecordSessionEndHistograms"/> + <int value="8" label="RecordLayoutShiftScoreMetrics"/> + <int value="9" label="RecordNormalizedResponsivenessMetrics"/> +</enum> + <enum name="PageLoadTimingStatus"> <summary>Status of PageLoadTimings received from the render process</summary> <int value="0" label="Valid"/> @@ -84219,6 +84317,15 @@ <int value="5" label="PRINT_WITH_SETTINGS_COLLAPSED"/> </enum> +<enum name="PrintPreviewStateError"> + <int value="0" label="None"/> + <int value="1" label="Invalid Ticket"/> + <int value="2" label="Invalid Printer"/> + <int value="3" label="No Destinations"/> + <int value="4" label="Preview Failed"/> + <int value="5" label="Print Failed"/> +</enum> + <enum name="PrintPreviewUserActionType"> <int value="0" label="PRINT_TO_PRINTER"/> <int value="1" label="PRINT_TO_PDF"/> @@ -84325,6 +84432,7 @@ <int value="2" label="Incognito profile"/> <int value="3" label="Apis disabled"/> <int value="4" label="Site data access blocked"/> + <int value="5" label="Mismatched Consent"/> </enum> <enum name="PrivacySandboxPrivateAggregationBudgeterBudgetValidityStatus"> @@ -89588,6 +89696,7 @@ <int value="5" label="Undo block"/> <int value="6" label="Undo ignore"/> <int value="7" label="Undo reset"/> + <int value="8" label="Open review UI"/> </enum> <enum name="SafetyCheckPasswordsStatus"> @@ -89614,6 +89723,15 @@ <int value="7" label="ENABLED_STANDARD_AVAILABLE_ENHANCED"/> </enum> +<enum name="SafetyCheckUnusedSitePermissionsModuleInteractions"> + <int value="0" label="Open review UI"/> + <int value="1" label="Allow again"/> + <int value="2" label="Acknowledge all"/> + <int value="3" label="Undo allow again"/> + <int value="4" label="Undo acknowledge all"/> + <int value="5" label="Minimize review UI"/> +</enum> + <enum name="SafetyCheckUpdateStatus"> <int value="0" label="CHECKING"/> <int value="1" label="UPDATED"/> @@ -96939,6 +97057,7 @@ <int value="2" label="Frequent"/> <int value="3" label="Rare"/> <int value="4" label="Restricted"/> + <int value="5" label="Exempted"/> </enum> <enum name="StarEntryPointAction"> @@ -99666,6 +99785,11 @@ <int value="2" label="BOTTOM"/> </enum> +<enum name="ToolbarInMotionStage"> + <int value="0" label="SUPPRESSION_ENABLED"/> + <int value="1" label="READINESS_CHECKED"/> +</enum> + <enum name="ToolbarSnapshotDifference"> <int value="0" label="NONE"> This value will not be reported, only other actaul differences will be
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index b66a657..444f605 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -3111,9 +3111,7 @@ <histogram name="Android.PrepareMenu.OpenWebApkVisibilityCheck" units="ms" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Measures the amount of time spent querying for whether a WebAPK is already installed. @@ -3762,6 +3760,21 @@ </summary> </histogram> +<histogram name="Android.TopToolbar.InMotionStage" enum="ToolbarInMotionStage" + expires_after="2023-12-31"> + <owner>skym@chromium.org</owner> + <owner>seacow@google.com</owner> + <summary> + Captures the stages reached in the Toolbar's in motion handling. Recorded + every time the in motion state of the compositor changes, before the event + is routed to the renderer process. Motion states include: flinging, swiping, + and any gesture that the CompositorViewHolder is processing. This metric + shows how often the in motion handling had to request the toolbar's capture + readiness state, which is a computationally expensive operation, and could + slow down input handling. + </summary> +</histogram> + <histogram name="Android.TopToolbar.SnapshotDifference" enum="ToolbarSnapshotDifference" expires_after="2023-05-16"> <owner>skym@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 0c753af..ca14f56 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -960,6 +960,30 @@ </summary> </histogram> +<histogram name="Ash.Calendar.UpNextView.EventDisplayedCount" units="int" + expires_after="2024-01-24"> + <owner>newcomer@google.com</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Records the number of currently visible upcoming events shown to the user + when the Calendar "Up next" view displays. i.e. the user opens the + sys tray calendar, "Up next" displays 2 upcoming events, this + metric will track a count of 2. + </summary> +</histogram> + +<histogram name="Ash.Calendar.UpNextView.EventListItem.Pressed" + enum="CalendarEventSource" expires_after="2024-01-24"> + <owner>newcomer@google.com</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Recorded when an upcoming event is pressed from the Calendar "Up + next" view and launched in Google Calendar. i.e. the user opens the sys + tray calendar, "Up next" displays an event in the next 10 mins and + the user taps the event. + </summary> +</histogram> + <histogram name="Ash.Calendar.UserJourneyTime.{EventLaunchState}" units="ms" expires_after="2023-09-18"> <owner>newcomer@google.com</owner> @@ -3508,9 +3532,7 @@ Tracks the time from when a specific educational nudge is shown to when it's interacted with. Starts measuring time when the nudge is shown and records the Nudge catalog name in one of the time buckets available if the user - performs the expected action that the nudge is informing about. This metric - can be compared with `Ash.NotifierFramework.Nudge.ShownCount` to infer the - nudge action wasn't taken within that session. + performs the nudge's suggested action. </summary> <token key="TimeRange"> <variant name="Within1h"/>
diff --git a/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml index 421d6e00..f9708bc 100644 --- a/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml +++ b/tools/metrics/histograms/metadata/ash_clipboard/histograms.xml
@@ -242,6 +242,10 @@ <histogram name="Ash.ClipboardHistory.Nudges.{NudgeType}.ToFeature{Action}Time" units="seconds" expires_after="2023-04-25"> + <obsolete> + Replaced by version 2 in January 2023. This histogram can be deleted once + the new version has enough stable channel data. + </obsolete> <owner>ckincaid@chromium.org</owner> <owner>multipaste@google.com</owner> <summary> @@ -260,6 +264,33 @@ </token> </histogram> +<histogram + name="Ash.ClipboardHistory.Nudges.{NudgeType}.ToFeature{Action}TimeV2" + units="seconds" expires_after="2023-04-25"> + <owner>ckincaid@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The delay between the user being shown the clipboard history {NudgeType} and + the user's {Action} action. Recorded at the time of the {Action}. + + Note: Version 1 of this histogram counted opening the clipboard history menu + via context menu as an "open" action. However, the nudges suggest + opening clipboard history via accelerator; they do not mention a context + menu option. This histogram only records opens that the nudge may have + actually led to. + </summary> + <token key="NudgeType"> + <variant name="OnboardingNudge" summary="onboarding nudge"/> + <variant name="ScreenshotNotificationNudge" + summary="screenshot notification nudge"/> + <variant name="ZeroStateNudge" summary="zero state nudge"/> + </token> + <token key="Action"> + <variant name="Open" summary="opening the clipboard history menu"/> + <variant name="Paste" summary="pasting from the clipboard history menu"/> + </token> +</histogram> + <histogram name="Ash.ClipboardHistory.Operation" enum="ClipboardHistoryOperation" expires_after="2023-06-25"> <owner>ckincaid@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index be732e8..a314f9b 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1654,6 +1654,26 @@ </summary> </histogram> +<histogram name="Autofill.FillingCorrectnessByMethod.{FormType}.{Method}" + enum="BooleanAutofillFillingCorrectness" expires_after="2023-06-01"> + <owner>atsvirhckova@google.com</owner> + <owner>izuzic@google.com</owner> + <owner>chrome-autofill-team@google.com</owner> + <summary> + Tracks whether or not the user has edited at least one of the autofilled + fields before submitting the form. This metric is tracked whenever the value + to autofill the {FormType} is provided by the {Method}. The metric is + recorded on form submission. + </summary> + <token key="FormType"> + <variant name="Address" summary="Address form"/> + <variant name="CreditCard" summary="Credit card form"/> + </token> + <token key="Method"> + <variant name="TouchToFill" summary="Bottom sheet"/> + </token> +</histogram> + <histogram name="Autofill.FindFormControlElementByUniqueRendererIdDuration" units="microseconds" expires_after="2022-10-30"> <obsolete> @@ -3022,6 +3042,19 @@ </summary> </histogram> +<histogram + name="Autofill.ProfileImport.NewProfileNumberOfAutocompleteUnrecognizedFields" + units="fields" expires_after="2023-04-30"> + <owner>fleimgruber@google.com</owner> + <owner>chrome-autofill-team@google.com</owner> + <summary> + Logs the number of fields with an unrecognized autocomplete attributed that + were considered for the import due to AutofillFillAndImportFromMoreFields. + Emitted at the end of an import process, once the user-provided import + decision is final. + </summary> +</histogram> + <histogram name="Autofill.ProfileImport.NewProfileNumberOfEditedFields" units="fields" expires_after="2023-06-04"> <owner>koerber@google.com</owner> @@ -3187,6 +3220,19 @@ </token> </histogram> +<histogram + name="Autofill.ProfileImport.UpdateProfileNumberOfAutocompleteUnrecognizedFields" + units="fields" expires_after="2023-04-30"> + <owner>fleimgruber@google.com</owner> + <owner>chrome-autofill-team@google.com</owner> + <summary> + Logs the number of fields with an unrecognized autocomplete attributed that + were considered for the update due to AutofillFillAndImportFromMoreFields. + Emitted at the end of an update process, once the user-provided update + decision is final. + </summary> +</histogram> + <histogram name="Autofill.ProfileImport.UpdateProfileNumberOfEditedFields" units="fields" expires_after="2023-09-11"> <owner>koerber@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index 6eb77b18..5d62cb9 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1335,13 +1335,16 @@ </token> </histogram> -<histogram name="ChromeOS.Inputs.EventRewriter.KeyRewriteLatency" units="ms" - expires_after="2024-01-05"> +<histogram name="ChromeOS.Inputs.EventRewriter.KeyRewriteLatency" + units="microseconds" expires_after="2024-01-05"> <owner>wangdanny@chromium.org</owner> <owner>dpad@chromium.org</owner> <owner>cros-peripherals@google.com</owner> <summary> Records the event rewriter latency metric every time a key is pressed. + + This metric is reported for all users and will not cause abnormal + distribution since the metric is ChromeOS specified. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml index 60c3421..8c8bf2e 100644 --- a/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos_settings/histograms.xml
@@ -132,6 +132,63 @@ </summary> </histogram> +<histogram name="ChromeOS.Settings.Keyboard.Modifiers.Hash" units="hash" + expires_after="2024-01-23"> + <owner>dpad@google.com</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Records the configured modifier remapping set for all modifiers as a hash. + See //ash/system/input_device_settings/keyboard_modifier_metrics_recorder.cc + for an explanation of the storage method and how to convert the hash to get + modifier data. + </summary> +</histogram> + +<histogram + name="ChromeOS.Settings.Keyboard.Modifiers.{Modifier}RemappedTo.Changed" + enum="KeyboardModifierRemappingKeys" expires_after="2024-01-23"> + <owner>dpad@google.com</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Records the configured modifier remapping for the {Modifier} key when a user + changes the setting in the Settings SWA. + </summary> + <token key="Modifier"> + <variant name="Alt"/> + <variant name="Assistant"/> + <variant name="Backspace"/> + <variant name="CapsLock"/> + <variant name="Control"/> + <variant name="Escape"/> + <variant name="ExternalCommand"/> + <variant name="ExternalMeta"/> + <variant name="Search"/> + </token> +</histogram> + +<histogram + name="ChromeOS.Settings.Keyboard.Modifiers.{Modifier}RemappedTo.Started" + enum="KeyboardModifierRemappingKeys" expires_after="2024-01-23"> + <owner>dpad@google.com</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Records the configured modifier remapping for the {Modifier} key when a user + session is started. Only emitted once per user per session. Default values + are not recorded. + </summary> + <token key="Modifier"> + <variant name="Alt"/> + <variant name="Assistant"/> + <variant name="Backspace"/> + <variant name="CapsLock"/> + <variant name="Control"/> + <variant name="Escape"/> + <variant name="ExternalCommand"/> + <variant name="ExternalMeta"/> + <variant name="Search"/> + </token> +</histogram> + <histogram name="ChromeOS.Settings.Languages.Interaction" enum="SettingsLanguagesPageInteraction" expires_after="2023-06-18"> <owner>myy@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml index 51bb0ab..01cc477 100644 --- a/tools/metrics/histograms/metadata/compositing/histograms.xml +++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -86,18 +86,6 @@ </summary> </histogram> -<histogram name="Compositing.BufferQueue.TimeUntilBuffersRecreatedMs" - units="ms" expires_after="2023-09-30"> - <owner>khaslett@chromium.org</owner> - <owner>petermcneeley@chromium.org</owner> - <summary> - The time since a BufferQueue's buffers were destroyed until they were - recreated. If this time is commonly very small, that is a problem. Recorded - when the buffer recreates buffers that were previously destroyed. For a - single BufferQueue this should be once per frame at worst. - </summary> -</histogram> - <histogram name="Compositing.ColorGamut" enum="ColorGamut" expires_after="2022-02-06"> <owner>cblume@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml index 1c6c0811..9936cf2 100644 --- a/tools/metrics/histograms/metadata/enterprise/histograms.xml +++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -993,21 +993,6 @@ </summary> </histogram> -<histogram name="Enterprise.DeviceTrust.ManagementService.ExitCode.{Sign}" - units="exit_code" expires_after="2023-12-26"> - <owner>hmare@google.com</owner> - <owner>rogerta@chromium.org</owner> - <owner>seblalancette@chromium.org</owner> - <summary> - Captures the management service binary processes {Sign} after it completes - the execution of a command (e.g. key rotation). - </summary> - <token key="Sign"> - <variant name="Negative" summary="Negative exit code"/> - <variant name="Positive" summary="Positive exit code"/> - </token> -</histogram> - <histogram name="Enterprise.DeviceTrust.Origin" enum="DTOrigin" expires_after="2023-12-01"> <owner>lmasopust@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/fastpair/histograms.xml b/tools/metrics/histograms/metadata/fastpair/histograms.xml index c1bf962..5d635b2 100644 --- a/tools/metrics/histograms/metadata/fastpair/histograms.xml +++ b/tools/metrics/histograms/metadata/fastpair/histograms.xml
@@ -22,6 +22,18 @@ <histograms> +<histogram name="FastPair.CreateBond.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for Fast Pair to finish creating a bond with + the peripheral. Emitted when bonding completes. No metric is emitted on + failure. + </summary> +</histogram> + <histogram name="FastPair.GattConnection" enum="FastPairGattConnectionSteps" expires_after="2023-06-01"> <owner>jackshira@chromium.org</owner> @@ -34,6 +46,17 @@ </summary> </histogram> +<histogram name="FastPair.GattServiceDiscovery.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for GATT service discovery. Emitted when + GATT discovery is completed for service. No metric is emitted on failure. + </summary> +</histogram> + <histogram name="FastPair.Handshake.AttemptCount" units="count" expires_after="2023-06-01"> <owner>akingsb@google.com</owner> @@ -72,6 +95,54 @@ </summary> </histogram> +<histogram name="FastPair.KeyBasedNotify.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for the Fast Pair key based pairing notify + session to begin. Emitted when a key based notify session has been + successfully started. No metric is emitted on failure. + </summary> +</histogram> + +<histogram name="FastPair.KeyBasedWriteRequest.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for the Fast Pair key based write request to + complete. Emitted when a key based write request has completed successfully. + No metric is emitted on failure. + </summary> +</histogram> + +<histogram name="FastPair.PasskeyNotify.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for the Fast Pair passkey notify session to + begin. Emitted when a passkey notify session has been successfully started. + No metric is emitted on failure. + </summary> +</histogram> + +<histogram name="FastPair.PasskeyWriteRequest.Latency" units="ms" + expires_after="2023-07-02"> + <owner>jackshira@google.com</owner> + <owner>akingsb@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total time it takes for the Fast Pair passkey request to + complete. Emitted when a passkey write request has completed successfully. + No metric is emitted on failure. + </summary> +</histogram> + <histogram name="FastPair.RetroactivePairing" enum="FastPairRetroactiveSuccessFunnelEvent" expires_after="2023-06-01"> <owner>jackshira@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index 09cde36..62cde95 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -762,6 +762,50 @@ </summary> </histogram> +<histogram + name="History.Clusters.Backend.ContentClustering.NumClustersAfterMerge" + units="counts" expires_after="2023-06-04"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Records the number of clusters after merging similar clusters based on + content. Logged when clusters have been calculated based on any request to + cluster visits, which could be triggered from several things, including + loading the journeys UI, putting a query in the journeys page, etc... + </summary> +</histogram> + +<histogram + name="History.Clusters.Backend.ContentClustering.NumClustersBeforeMerge" + units="counts" expires_after="2023-06-04"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Records the number of clusters before merging similar clusters based on + content. Logged when clusters have been calculated based on any request to + cluster visits, which could be triggered from several things, including + loading the journeys UI, putting a query in the journeys page, etc... + </summary> +</histogram> + +<histogram + name="History.Clusters.Backend.ContentClustering.PairwiseMergeNumIterations" + units="counts" expires_after="2023-06-04"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Records the number of iterations it took for a batch of clusters to converge + during a pairwise merge of similar clusters based on content, up to a + Finch-configured maximum. Logged when clusters have been calculated based on + any request to cluster visits, which could be triggered from several things, + including loading the journeys UI, putting a query in the journeys page, + etc... + </summary> +</histogram> + <histogram name="History.Clusters.Backend.ContextClusterer.ThreadTime" units="ms" expires_after="2023-06-04"> <owner>sophiechang@chromium.org</owner> @@ -854,7 +898,10 @@ On startup and every 1 hour afterwards, these context clusters have their triggability calculated. Context clusters older than 2 hours are not updated - are not re-updated after the initial triggability is calculated. + are not re-updated after the initial triggability is calculated. However, if + there are unclustered visits (due to visits from before the user had context + clustering enabled or synced visits without a cluster ID), they will also be + context clustered with their triggerability calculated as well. When a user visits the Journeys WebUI, persisted clusters (both those with and without triggerability calculated) are fetched. Clusters are then @@ -1177,6 +1224,40 @@ </histogram> <histogram + name="History.Clusters.Backend.UpdateClusterTriggerability.HadUnclusteredVisitsToCluster" + enum="Boolean" expires_after="2023-10-01"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + On navigation, context clusters are created, grown, and persisted. + + On startup and every 1 hour afterwards, these context clusters have their + triggability calculated. Context clusters older than 2 hours are not updated + are not re-updated after the initial triggability is calculated. However, if + there are unclustered visits (due to visits from before the user had context + clustering enabled or synced visits without a cluster ID), they will also be + context clustered with their triggerability calculated as well. + + When a user visits the Journeys WebUI, persisted clusters (both those with + and without triggerability calculated) are fetched. Clusters are then + augmented with appropriate metadata needed for displaying on the Journeys + WebUI (e.g. ranking, deduping, labeling). + + When the keyword cache used to match omnibox inputs and show journey chips + or suggestions in the omnibox needs updating, context clusters (both those + with and without triggerability calculated) are fetched. + + This histogram records whether there were unclustered visits left to cluster + in the first run of this task. When this trends to all false, this + additional step can get deleted. + + Recorded for every batch of visits clustered; can be recorded more than once + every hour. + </summary> +</histogram> + +<histogram name="History.Clusters.Backend.UpdateClusterTriggerability.{Segment}" units="ms" expires_after="2023-10-01"> <owner>manukh@chromium.org</owner> @@ -1187,7 +1268,10 @@ On startup and every 1 hour afterwards, these context clusters have their triggability calculated. Context clusters older than 2 hours are not updated - are not re-updated after the initial triggability is calculated. + are not re-updated after the initial triggability is calculated. However, if + there are unclustered visits (due to visits from before the user had context + clustering enabled or synced visits without a cluster ID), they will also be + context clustered with their triggerability calculated as well. When a user visits the Journeys WebUI, persisted clusters (both those with and without triggerability calculated) are fetched. Clusters are then @@ -1210,12 +1294,22 @@ <token key="Segment"> <variant name="ComputeClusterTriggerabilityLatency" summary="receiving cluster triggerability metadata from the model"/> + <variant name="ComputeContextClustersLatency" + summary="receiving context clusters from unclustered visits from the + model"/> + <variant name="GetAnnotatedVisitsToClusterLatency" + summary="receiving persisted unclustered visits to compute context + clusters for for"/> <variant name="GetMostRecentPersistedClustersLatency" summary="receiving persisted clusters to compute cluster triggerability metadata for"/> <variant name="PersistClusterTriggerabilityLatency" summary="receiving acknowledgement for completion of persisting the cluster triggerability metadata to the history DB"/> + <variant name="PersistContextClustersLatency" + summary="receiving acknowledgement for completion of persisting the + context clusters formed from unclustered visits to the + history DB"/> </token> </histogram> @@ -1490,6 +1584,7 @@ <token key="VisitAction"> <variant name="Clicked" summary="clicks"/> <variant name="Deleted" summary="deletes"/> + <variant name="Hidden" summary="hides"/> </token> <token key="VisitType"> <variant name="" summary="visit"/>
diff --git a/tools/metrics/histograms/metadata/interstitial/histograms.xml b/tools/metrics/histograms/metadata/interstitial/histograms.xml index b0312e41..8665a2f 100644 --- a/tools/metrics/histograms/metadata/interstitial/histograms.xml +++ b/tools/metrics/histograms/metadata/interstitial/histograms.xml
@@ -36,6 +36,72 @@ </summary> </histogram> +<histogram name="interstitial.enterprise_block.decision" + enum="SecurityInterstitialDecision" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user is blocked from visiting a site as per admin rules in an + enterprise managed browser. + </summary> +</histogram> + +<histogram name="interstitial.enterprise_block.decision.repeat_visit" + enum="SecurityInterstitialDecision" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user is blocked from visiting a site as per admin rules in an + enterprise managed browser and the user tries to access it again. + </summary> +</histogram> + +<histogram name="interstitial.enterprise_block.interaction" + enum="SecurityInterstitialInteraction" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user interacts with a blocking page shown for a url that + doesn't comply with admin rules. + </summary> +</histogram> + +<histogram name="interstitial.enterprise_warn.decision" + enum="SecurityInterstitialDecision" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user is shown a warning while visiting a site that doesn't + comply with thadmin rules in an enterprise managed browser. + </summary> +</histogram> + +<histogram name="interstitial.enterprise_warn.decision.repeat_visit" + enum="SecurityInterstitialDecision" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user revisits a page they were warned about for not complying + with the admin rules in an enterprise managed browser. + </summary> +</histogram> + +<histogram name="interstitial.enterprise_warn.interaction" + enum="SecurityInterstitialInteraction" expires_after="M120"> + <owner>domfc@chromium.org</owner> + <owner>snehanagpaul@google.com</owner> + <owner>dpr-eng@google.com</owner> + <summary> + Records when a user interacts with a warning page shown for a url that + doesn't comply with admin rules. + </summary> +</histogram> + <histogram name="interstitial.ssl.cause.nonoverridable" enum="SSLErrorCauses" expires_after="never"> <!-- expires-never: Used for long term monitoring of security errors -->
diff --git a/tools/metrics/histograms/metadata/na_cl/histograms.xml b/tools/metrics/histograms/metadata/na_cl/histograms.xml index 3af3956..d570750 100644 --- a/tools/metrics/histograms/metadata/na_cl/histograms.xml +++ b/tools/metrics/histograms/metadata/na_cl/histograms.xml
@@ -426,6 +426,18 @@ </summary> </histogram> +<histogram name="NaCl.ResourceCreationImpl.CreateVideoDecoderDev_Invoked" + enum="Boolean" expires_after="2023-09-01"> + <owner>blundell@chromium.org</owner> + <owner>dschuff@chromium.org</owner> + <summary> + True is emitted when ResourceCreationImpl::CreateVideoDecoderDev() is + invoked. Targeted metric to get clarity on whether there are any attempted + creations of this API against production Chrome as we work toward + eliminating support for the API. + </summary> +</histogram> + <histogram name="NaCl.ValidationCache.Query" enum="NaClValidationCacheEnum" expires_after="2023-07-31"> <owner>dschuff@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml index 0a32e90..e1d99db 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -1076,6 +1076,23 @@ </summary> </histogram> +<histogram name="NewTabPage.Module.Click" enum="ModuleTypeOnStartAndNTP" + expires_after="2023-07-09"> + <owner>hanxi@chromium.org</owner> + <owner>xinyiji@chromium.org</owner> + <summary> + Record the total count of clicks on different modules of the New tab page. + For most visited tiles: is recorded when 1) user clicks on most visited + tiles; 2) long press on most visited tiles to open in a new tab or open in a + new tab in group or a new incognito tab or to download the link. This is + consistent with MobileNTPMostVisited. For feeds: is recorded when 1) user + clicks on feeds; 2) long press on feeds to open in a new tab or open in a + new incognito tab or check about this source and topic; 3) click the learn + more button on the top of the feeds section. The histogram is logged on New + tab page and is Android-only. + </summary> +</histogram> + <histogram name="NewTabPage.Modules.DataRequest" enum="NtpModules" expires_after="2023-05-27"> <owner>danpeng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 8b1cbcc..91e59c6 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3623,7 +3623,7 @@ </summary> </histogram> -<histogram name="Conversions.CreateReportStatus6" +<histogram name="Conversions.CreateReportStatus7" enum="ConversionStorageCreateReportStatus" expires_after="M117"> <owner>apaseltiner@chromium.org</owner> <owner>johnidel@chromium.org</owner> @@ -4138,6 +4138,18 @@ </summary> </histogram> +<histogram name="Conversions.VerboseDebugReport.HttpResponseOrNetErrorCode" + enum="CombinedHttpResponseAndNetErrorCode" expires_after="M117"> + <owner>linnan@chromium.org</owner> + <owner>johnidel@chromium.org</owner> + <owner>measurement-api-dev+metrics@google.com</owner> + <summary> + Error info for sending a verbose debug report, recorded for each sent + verbose debug report. The net error code is recorded if the HTTP response + code is unavailable. + </summary> +</histogram> + <histogram name="CopylessPaste.CacheHit" enum="CopylessCacheHit" expires_after="2020-03-01"> <owner>wychen@chromium.org</owner> @@ -9099,6 +9111,32 @@ </summary> </histogram> +<histogram name="OriginTrials.PersistentOriginTrial.PartitionSetSize" + units="sites" expires_after="2023-10-01"> + <owner>pbirk@chromium.org</owner> + <owner>src/components/origin_trials/OWNERS</owner> + <summary> + Reports the number of partitions a persistent origin trial token has been + stored against. The purpose of the metric is to uncover memory footprint + issues from storing site partitions, and to help decide if an eviction + strategy needs to be put in place. This metric is recorded once for every + stored origin trial token on browser startup. + </summary> +</histogram> + +<histogram + name="OriginTrials.PersistentOriginTrial.TokenHasFirstPartyPartition" + enum="Boolean" expires_after="2023-10-01"> + <owner>pbirk@chromium.org</owner> + <owner>src/components/origin_trials/OWNERS</owner> + <summary> + Records whether a stored partition token has its own origins eTLD+1 as one + of the partitions. This is being recorded to determine if space can be saved + by making the first-party partition a special case. This metric is recorded + on browser startup when the persisted tokens are loaded from the database. + </summary> +</histogram> + <histogram name="OriginTrials.ValidationResult" enum="OriginTrialTokenStatus" expires_after="2021-10-10"> <owner>chasej@chromium.org</owner> @@ -15202,7 +15240,7 @@ </histogram> <histogram name="WebUITabStrip.TabCreation" units="ms" - expires_after="2023-03-05"> + expires_after="2023-07-09"> <owner>robliao@chromium.org</owner> <owner>johntlee@chromium.org</owner> <summary> @@ -15211,7 +15249,7 @@ </histogram> <histogram name="WebUITabStrip.TabDataReceived" units="ms" - expires_after="2023-03-05"> + expires_after="2023-07-09"> <owner>robliao@chromium.org</owner> <owner>johntlee@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index b0835cc..3e242b6 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -167,6 +167,7 @@ <variant name="ReaderMode"/> <variant name="SaveAutofillAddress"/> <variant name="SaveCard"/> + <variant name="SaveIban"/> <variant name="SendTabToSelf"/> <variant name="SharingHub"/> <variant name="SideSearch"/> @@ -2396,6 +2397,17 @@ </summary> </histogram> +<histogram name="PageLoad.Internal.Prerender2.ObserverEvent" + enum="PageLoadPrerenderObserverEvent" expires_after="2023-07-26"> + <owner>nhiroki@chromium.org</owner> + <owner>src/content/browser/preloading/prerender/OWNERS</owner> + <summary> + Counts page load observer events related to Prerender2, like + FirstContentfulPaint. Recorded when those events are observed in + PrerenderPageLoaderMetricsObserver. + </summary> +</histogram> + <histogram name="PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime" units="ms" expires_after="2023-06-04"> <owner>jonross@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/print/histograms.xml b/tools/metrics/histograms/metadata/print/histograms.xml index d9a210d..5905376 100644 --- a/tools/metrics/histograms/metadata/print/histograms.xml +++ b/tools/metrics/histograms/metadata/print/histograms.xml
@@ -193,6 +193,28 @@ <summary>Time taken to render to PDF for print preview.</summary> </histogram> +<histogram name="PrintPreview.StateError" enum="PrintPreviewStateError" + expires_after="2024-01-23"> + <owner>gavinwill@chromium.org</owner> + <owner>thestig@chromium.org</owner> + <summary> + Records the error that puts Print Preview into an error state. The NONE + error state is not recorded. In an error state, the Print button is + disabled. + </summary> +</histogram> + +<histogram name="PrintPreview.TransitionedToReadyState" enum="BooleanHit" + expires_after="2024-01-23"> + <owner>gavinwill@chromium.org</owner> + <owner>thestig@chromium.org</owner> + <summary> + Records TRUE when Print Preview transitions from NOT_READY to READY state. + Records FALSE when Print Preview transitions from NOT_READY to ERROR state. + This metric only records for non-PDF destinations. + </summary> +</histogram> + <histogram name="PrintPreview.UserAction" enum="PrintPreviewUserActionType" expires_after="2023-07-02"> <owner>thestig@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml index 20b5ccc6..78e6f9df 100644 --- a/tools/metrics/histograms/metadata/profile/histograms.xml +++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -770,6 +770,33 @@ </summary> </histogram> +<histogram name="ProfilePicker.FirstRun.OrganizationAvailableTiming" units="ms" + expires_after="2023-07-25"> + <owner>dgn@chromium.org</owner> + <owner>jyammine@google.com</owner> + <owner>chrome-signin-team@google.com</owner> + <summary> + Records the time between the first run of Chrome on Desktop is loaded and + the organization name is available to be shown in the enterprise disclaimer. + This is only logged if the device is managed and the policy store is loaded + in the specified time delay. + </summary> +</histogram> + +<histogram name="ProfilePicker.FirstRun.PolicyStoreState" + enum="FirstRunCloudPolicyStoreState" expires_after="2023-07-25"> + <owner>dgn@chromium.org</owner> + <owner>jyammine@google.com</owner> + <owner>chrome-signin-team@google.com</owner> + <summary> + Records the loading state of the clould policy store when it is loaded or + after a specified time delay. This is recorded for the first run experience + on desktop for managed devices. This is needed to track if the managed + organization name has been properly displayed in the first run experience + managed disclaimer. + </summary> +</histogram> + <histogram name="ProfilePicker.NewProfileCreateShortcut" enum="BooleanCreated" expires_after="M90"> <owner>msalama@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml index f91e8b0d..32583f0 100644 --- a/tools/metrics/histograms/metadata/renderer/histograms.xml +++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -106,7 +106,7 @@ <histogram name="Renderer.DelegatedInkTrail.LatencyImprovement.{Renderer}.{Prediction}" - units="ms" expires_after="2023-02-01"> + units="ms" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -128,7 +128,7 @@ <histogram name="Renderer.DelegatedInkTrail.LatencyImprovementWithPrediction.Experiment{Number}" - units="ms" expires_after="2023-02-01"> + units="ms" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -149,7 +149,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.WrongDirection" - enum="BooleanDirection" expires_after="2023-02-01"> + enum="BooleanDirection" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -164,7 +164,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.{Direction}Prediction" - units="pixels" expires_after="2023-02-01"> + units="pixels" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -182,7 +182,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.{Type}Jitter" - units="pixels" expires_after="2023-02-01"> + units="pixels" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -203,7 +203,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.Frame{ScoreType}" - units="pixels" expires_after="2023-02-01"> + units="pixels" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -231,7 +231,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.WrongDirection" - enum="BooleanDirection" expires_after="2023-02-01"> + enum="BooleanDirection" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -251,7 +251,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.{ScoreType}" - units="pixels" expires_after="2023-02-01"> + units="pixels" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary> @@ -276,7 +276,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.{Type}Jitter" - units="pixels" expires_after="2023-02-01"> + units="pixels" expires_after="2024-02-01"> <owner>jonross@chromium.org</owner> <owner>sahir.vellani@microsoft.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index 98f8fc4..d78e531a 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -36,6 +36,30 @@ <variant name="Upload"/> </variants> +<variants name="HPRTExperimentDelayedResponseMaybeRedirects"> + <variant name="" summary=""/> + <variant name=".Redirects" + summary="Represents combined results from multiple redirects. Whether + it delayed the response and by how much is a slight + underestimate because the time taken is calculated by summing + up individual URL check times, which does not include the + client-side processing between individual check runs. The + underestimation is expected to be minimal since it involves + only local code running."/> +</variants> + +<variants name="HPRTExperimentMaybeRedirects"> + <variant name="" summary=""/> + <variant name=".Redirects" + summary="Represents combined results from multiple redirects."/> +</variants> + +<variants name="HPRTExperimentMechanism"> + <variant name="HPD" summary="the hash-prefix database mechanism"/> + <variant name="HPRT" summary="the hash-prefix real-time mechanism"/> + <variant name="URT" summary="the URL real-time mechanism"/> +</variants> + <variants name="MetricsCollectorBypassEventType"> <variant name="CsdInterstitialBypass" summary="client-side detection interstitial bypass"/> @@ -1078,6 +1102,121 @@ </summary> </histogram> +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.DelayedResponseResult" + enum="HPRTExperimentCombinedResult" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records which mechanisms delayed the page response. Logged when the HPRT + experiment concludes, which is once all lookup mechanisms have completed or + timed out, and BrowserUrlLoaderThrottle has reached WillProcessResponse or + has destructed CheckerOnIO before that occurred. {MaybeRedirects} + </summary> + <token key="MaybeRedirects" + variants="HPRTExperimentDelayedResponseMaybeRedirects"/> +</histogram> + +<histogram name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.TimedOutResult" + enum="HPRTExperimentCombinedResult" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records which mechanisms timed out. Logged when the HPRT experiment + concludes, which is once all lookup mechanisms have completed or timed out, + and BrowserUrlLoaderThrottle has reached WillProcessResponse or has + destructed CheckerOnIO before that occurred. {MaybeRedirects} + </summary> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.WarningsResult" + enum="HPRTExperimentCombinedResult" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records which mechanisms resulted in a warning. Logged when the HPRT + experiment concludes, which is once all lookup mechanisms have completed or + timed out, and BrowserUrlLoaderThrottle has reached WillProcessResponse or + has destructed CheckerOnIO before that occurred. {MaybeRedirects} + </summary> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.{Mechanism1}FasterThan{Mechanism2}Amount" + units="ms" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records by how much {Mechanism1} was faster than {Mechanism2}. Logged when + the HPRT experiment concludes, which is once all lookup mechanisms have + completed or timed out, and BrowserUrlLoaderThrottle has reached + WillProcessResponse or has destructed CheckerOnIO before that occurred. + {MaybeRedirects} + </summary> + <token key="Mechanism1" variants="HPRTExperimentMechanism"/> + <token key="Mechanism2" variants="HPRTExperimentMechanism"/> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.{Mechanism}.DelayedResponse" + units="HPRTExperimentUnknownNoYes" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records whether {Mechanism} delayed the page response. Logged when the HPRT + experiment concludes, which is once all lookup mechanisms have completed or + timed out, and BrowserUrlLoaderThrottle has reached WillProcessResponse or + has destructed CheckerOnIO before that occurred. {MaybeRedirects} + </summary> + <token key="Mechanism" variants="HPRTExperimentMechanism"/> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.{Mechanism}.DelayedResponseAmount" + units="ms" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records by how much {Mechanism} delayed the page response. Logged when all + lookup mechanisms in the HPRT experiment have completed or timed out, and + BrowserUrlLoaderThrottle has reached WillProcessResponse. If + BrowserUrlLoaderThrottle destructs CheckerOnIO before WillProcessResponse is + called, there is no log. {MaybeRedirects} + </summary> + <token key="Mechanism" variants="HPRTExperimentMechanism"/> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.{Mechanism}.TimedOut" + units="BooleanSuccess" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records whether {Mechanism} timed out. Logged when the HPRT experiment + concludes. {MaybeRedirects} + </summary> + <token key="Mechanism" variants="HPRTExperimentMechanism"/> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + +<histogram + name="SafeBrowsing.HPRTExperiment{MaybeRedirects}.{Mechanism}.TimeTaken" + units="ms" expires_after="2023-07-19"> + <owner>thefrog@chromium.org</owner> + <owner>chrome-counter-abuse-alerts@google.com</owner> + <summary> + Records by how long {Mechanism} took. Logged when the HPRT experiment + concludes. {MaybeRedirects} + </summary> + <token key="Mechanism" variants="HPRTExperimentMechanism"/> + <token key="MaybeRedirects" variants="HPRTExperimentMaybeRedirects"/> +</histogram> + <histogram name="SafeBrowsing.LocalBinaryUploadRequest.DlpResult" enum="BooleanSuccess" expires_after="2023-10-20"> <owner>rogerta@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml index f44302e..cae7be1f 100644 --- a/tools/metrics/histograms/metadata/settings/histograms.xml +++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -376,6 +376,18 @@ </summary> </histogram> +<histogram name="Settings.PrivacySandbox.DialogWindowTooSmall" enum="Boolean" + expires_after="2023-06-18"> + <owner>olesiamarukhno@google.com</owner> + <owner>sauski@google.com</owner> + <owner>kartoffel-core-eng@google.com</owner> + <summary> + Records whether the window size was too small to fit the Privacy Sandbox + dialog. If the window is too small, the dialog isn't shown. It is recorded + after all other conditions to show the dialog were satisfied. + </summary> +</histogram> + <histogram name="Settings.PrivacySandbox.Enabled" enum="SettingsPrivacySandboxEnabled" expires_after="2023-07-09"> <owner>harrisonsean@chromium.org</owner> @@ -499,11 +511,24 @@ <owner>hkamila@chromium.org</owner> <summary> The number of suggestions of notification permissions to revoke, recorded - when the notification permission list is updated for the SafetyCheck + when the notification permission list is initialized for the SafetyCheck notifications module. </summary> </histogram> +<histogram name="Settings.SafetyCheck.NotificationsModuleEntryPointShown" + enum="BooleanVisible" expires_after="2023-12-21"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <owner>hkamila@chromium.org</owner> + <summary> + Captures whether the entry point for the notification module of Safety Check + is shown to the user, i.e. whether it is enabled and at least one + notification permission met the criteria for review. Recorded whenever the + user visits the Safety Check page in Chrome Settings. + </summary> +</histogram> + <histogram name="Settings.SafetyCheck.NotificationsModuleInteractions" enum="SafetyCheckNotificationsModuleInteractions" expires_after="2023-10-21"> @@ -531,6 +556,56 @@ <summary>Resulting state of the safety check Safe Browsing check.</summary> </histogram> +<histogram name="Settings.SafetyCheck.UnusedSitePermissionsAllowAgainDays" + units="days" expires_after="2023-12-21"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <summary> + The number of days between the revocation of the permissions for an unused + site and when the user reverts this revocation through the unused site + permissions module of safety check in Chrome settings. Emitted when the user + clicks regrants permissions through the permissions review interface in + Chrome settings. + </summary> +</histogram> + +<histogram name="Settings.SafetyCheck.UnusedSitePermissionsListCount" + units="suggestions" expires_after="2023-12-21"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <summary> + The number of suggestions of unused site permissions to revoke, recorded + when the list of sites with revoked permissions is initialized when the user + opens the SafetyCheck unused site permissions module. + </summary> +</histogram> + +<histogram + name="Settings.SafetyCheck.UnusedSitePermissionsModuleEntryPointShown" + enum="BooleanVisible" expires_after="2023-12-21"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <owner>hkamila@chromium.org</owner> + <summary> + Captures whether the entry point for the unused site permissions module of + Safety Check is shown to the user, i.e. whether it is enabled and at least + one site permission has been revoked. Recorded whenever the user visits the + Safety Check page in Chrome Settings. + </summary> +</histogram> + +<histogram name="Settings.SafetyCheck.UnusedSitePermissionsModuleInteractions" + enum="SafetyCheckUnusedSitePermissionsModuleInteractions" + expires_after="2023-12-21"> + <owner>sideyilmaz@chromium.org</owner> + <owner>msramek@chromium.org</owner> + <summary> + The user actions taken on the unused site permissions module in safety check + in Chrome settings. Recorded every time the user interacts with the + respective UI element. + </summary> +</histogram> + <histogram name="Settings.SafetyCheck.UpdatesResult" enum="SafetyCheckUpdateStatus" expires_after="2023-04-23"> <owner>andzaytsev@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/side_search/histograms.xml b/tools/metrics/histograms/metadata/side_search/histograms.xml index fb7becf4..462320f8d 100644 --- a/tools/metrics/histograms/metadata/side_search/histograms.xml +++ b/tools/metrics/histograms/metadata/side_search/histograms.xml
@@ -59,17 +59,6 @@ </summary> </histogram> -<histogram name="SideSearch.CloseAction" enum="SideSearchCloseActionType" - expires_after="2023-12-13"> - <owner>yuhengh@chromium.org</owner> - <owner>tluk@chromium.org</owner> - <owner>romanarora@chromium.org</owner> - <summary> - The type of action taken to close Side Search. Recorded when side search - panel is closed. - </summary> -</histogram> - <histogram name="SideSearch.LoadCompletedTime" units="ms" expires_after="2023-12-13"> <owner>yuhengh@chromium.org</owner> @@ -148,17 +137,6 @@ </summary> </histogram> -<histogram name="SideSearch.OpenAction" enum="SideSearchOpenActionType" - expires_after="2023-12-13"> - <owner>yuhengh@chromium.org</owner> - <owner>tluk@chromium.org</owner> - <owner>romanarora@chromium.org</owner> - <summary> - The type of action taken to open Side Search. Recorded when side search - panel is open. - </summary> -</histogram> - <histogram name="SideSearch.PageActionIcon.LabelVisibleWhenToggled" enum="SideSearchPageActionLabelVisibility" expires_after="2023-12-13"> <owner>yuhengh@chromium.org</owner> @@ -195,21 +173,6 @@ </summary> </histogram> -<histogram name="SideSearch.SidePanel.TimeShownOpenedVia{OpenAction}" - units="ms" expires_after="2023-12-13"> - <owner>tluk@chromium.org</owner> - <owner>yuhengh@chromium.org</owner> - <summary> - Tracks the duration that a given tab's side search side panel was open for - when opened via a {OpenAction} action. This metric is emitted when the tab's - side search side panel is hidden. - </summary> - <token key="OpenAction"> - <variant name="Entrypoint"/> - <variant name="TabSwitch"/> - </token> -</histogram> - <histogram name="SideSearch.TimeSinceSidePanelAvailableToFirstOpen" units="ms" expires_after="2023-12-13"> <owner>yuhengh@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/start_surface/histograms.xml b/tools/metrics/histograms/metadata/start_surface/histograms.xml index c1378b90..6f6b60c 100644 --- a/tools/metrics/histograms/metadata/start_surface/histograms.xml +++ b/tools/metrics/histograms/metadata/start_surface/histograms.xml
@@ -33,6 +33,23 @@ </summary> </histogram> +<histogram name="StartSurface.Module.Click" enum="ModuleTypeOnStartAndNTP" + expires_after="2023-07-09"> + <owner>hanxi@chromium.org</owner> + <owner>xinyiji@chromium.org</owner> + <summary> + Record the total count of clicks on different modules of the Start surface + page. For most visited tiles: is recorded when 1) user clicks on most + visited tiles; 2) long press on most visited tiles to open in a new tab or a + new incognito tab or to download the link. This is consistent with + MobileNTPMostVisited. For feeds: is recorded when 1) user clicks on feeds; + 2) long press on feeds to open in a new tab or open in a new incognito tab + or check about this source and topic; 3) click the learn more button on the + top of the feeds section. The histogram is logged on Start surface and is + Android-only. + </summary> +</histogram> + <histogram name="StartSurface.Show.State" enum="StartSurfaceState" expires_after="2023-07-12"> <owner>hanxi@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml index 085a6c5..e1e0e121 100644 --- a/tools/metrics/histograms/metadata/translate/histograms.xml +++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -586,7 +586,7 @@ </histogram> <histogram name="Translate.PageLoad.Ranker.Decision" - enum="TranslateRankerDecision" expires_after="2023-06-04"> + enum="TranslateRankerDecision" expires_after="2023-08-31"> <owner>megjablon@google.com</owner> <owner>chrome-language@google.com</owner> <summary> @@ -611,7 +611,7 @@ </histogram> <histogram name="Translate.PageLoad.Ranker.Version" units="version" - expires_after="2023-03-26"> + expires_after="2023-08-31"> <owner>megjablon@google.com</owner> <owner>chrome-language@google.com</owner> <summary> @@ -734,7 +734,7 @@ </histogram> <histogram name="Translate.Ranker.Model.Status2" enum="RankerModelStatus" - expires_after="2023-03-26"> + expires_after="2023-08-31"> <owner>megjablon@google.com</owner> <owner>chrome-language@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml index 8a66568..8f49bb3 100644 --- a/tools/metrics/histograms/metadata/web_apk/histograms.xml +++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -36,9 +36,7 @@ <histogram name="WebApk.Install.AvailableSpace.Fail" units="MB" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the available space that can be used when installing a WebAPK from Google Play fails. The space recorded is the available space beyond the @@ -51,9 +49,7 @@ <histogram name="WebApk.Install.AvailableSpaceAfterFreeUpCache.Fail" units="MB" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the available space that can be used when installing a WebAPK from Google Play fails after freeing up cache. The space recorded is the @@ -66,9 +62,7 @@ <histogram name="WebApk.Install.GooglePlayErrorCode" enum="WebApkInstallGooglePlayErrorCode" expires_after="2023-07-16"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the error code when installing a WebAPK from Google Play fails. See go/webapk-install-googleplayerrorcode. @@ -78,9 +72,7 @@ <histogram name="WebApk.Install.GooglePlayInstallResult" enum="WebApkGooglePlayInstallResult" expires_after="2023-06-04"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records whether installing a WebAPK from Google Play succeeded. If not, records the reason that the install failed. @@ -90,9 +82,7 @@ <histogram name="WebApk.Install.InstallDuration" units="ms" expires_after="2023-07-02"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> How long it takes to install a WebAPK. The time is measured from the time that the user initiates the install to the time that the Open button is @@ -103,9 +93,7 @@ <histogram name="WebApk.Install.InstallEvent" enum="WebApkInstallEvent" expires_after="2023-07-09"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> WebAPKs are PWAs wrapped in an Android apk, installed from an app banner or the add to homescreen menu item. This stat tracks WebAPK installation @@ -117,9 +105,7 @@ expires_after="2023-06-04"> <owner>eirage@chromium.org</owner> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Record whether installing a WebAPK succeeded. If not record the reason that the install failed. @@ -130,9 +116,7 @@ expires_after="2023-06-25"> <owner>finnur@chromium.org</owner> <owner>peter@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the path that the user took to reach install point for PWAs. This can be via the Install Modal or the new BottomSheet and may involve the @@ -145,9 +129,7 @@ expires_after="2023-06-18"> <owner>hartmanng@chromium.org</owner> <owner>rayankans@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the amount of time which has elapsed from the "install infobar showing" to the "install request being sent to Google Play". @@ -160,9 +142,7 @@ <histogram name="WebApk.Launch.NetworkError" enum="NetErrorCodes" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the error codes when a WebAPK is launched with network failures. </summary> @@ -171,9 +151,7 @@ <histogram name="WebApk.Navigation.InScope" enum="Boolean" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Recorded each time that a WebAPK is navigated. Records whether the navigation is within the scope of the WebAPK's Web Manifest. Not recorded @@ -187,9 +165,7 @@ Replaced by WebApk.Notification.Permission.Status2 in June 20220. </obsolete> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> When a WebAPK receives a notification, log whether it has permission to display that notification. @@ -200,9 +176,7 @@ expires_after="2023-06-18"> <owner>hartmanng@chromium.org</owner> <owner>mvanouwerkerk@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> When a WebAPK receives a notification, log whether it has permission to display that notification. @@ -213,9 +187,7 @@ enum="ContentSetting" expires_after="2023-06-11"> <owner>mvanouwerkerk@chromium.org</owner> <owner>peconn@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> The result of a WebAPK notification permission request for the purpose of notification delegation. This is logged when the @@ -227,9 +199,7 @@ <histogram name="WebApk.ShellApkVersion2{WebApkDistributorType}" units="units" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records WebAPK "Shell APK version" when the WebAPK is launched. The "Shell APK version" is documented in shell_apk_version.gni @@ -241,9 +211,7 @@ <histogram name="WebApk.Startup.Cold.NewStyle.ShellLaunchToSplashscreenVisible" units="ms" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Tracks the time to splash screen visible starting from the launch of the WebAPK shell (rather than from the launch of Chrome) for new-style WebAPKs. @@ -275,9 +243,7 @@ <histogram name="WebApk.Uninstall{WebApkDistributorType}" enum="BooleanHit" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records that a WebAPK was uninstalled. {WebApkDistributorType} </summary> @@ -287,9 +253,7 @@ <histogram name="WebApk.Update.GooglePlayUpdateResult" enum="WebApkGooglePlayInstallResult" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records whether updating a WebAPK from Google Play succeeded. If not, records the reason that the update failed. @@ -299,9 +263,7 @@ <histogram name="WebApk.Update.NumStaleUpdateRequestFiles" units="files" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the number of zombie "WebAPK update request" files that the update process failed to cleanup. Recorded for all WebAPKs whenever a @@ -312,9 +274,7 @@ <histogram name="WebApk.Update.RequestQueued" enum="WebApkUpdateRequestQueued" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the number of times that a WebAPK update request was queued (i.e. waiting for the WebAPK to be backgrounded) before being sent to the server. @@ -324,9 +284,7 @@ <histogram name="WebApk.Update.RequestSent" enum="WebApkUpdateRequestSent" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records the time point when a request to update a WebAPK is sent to the WebAPK Server. @@ -337,9 +295,7 @@ enum="Boolean" expires_after="2023-06-30"> <owner>eirage@chromium.org</owner> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> When WebApkUpdateDataFetcher found a valid manifest that contains a different id than the installed WebAPK, record whether each of the @@ -352,9 +308,7 @@ enum="Boolean" expires_after="2023-06-30"> <owner>eirage@chromium.org</owner> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> When WebAPK updates with empty or same UniqueId, record whether each of the {LegacyIdentifierType} was the same. @@ -370,9 +324,7 @@ expires_after="2023-06-30"> <owner>eirage@chromium.org</owner> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> For WebAPK unique ID migration, record whether an update is neede (with non-empty update reason). This only records for the first legacy update that @@ -383,9 +335,7 @@ <histogram name="WebApk.WebApkService.BindSuccess" enum="BooleanSuccess" expires_after="2023-06-01"> <owner>hartmanng@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records whether Chrome can bind to a WebAPK's "WebAPK service". Recorded each time that Chrome attempts to bind to a WebAPK service. @@ -395,9 +345,7 @@ <histogram name="WebApk.WebappRegistry.NumberOfOrigins" units="count" expires_after="2023-07-15"> <owner>eirage@chromium.org</owner> - <owner> - src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS - </owner> + <owner>src/chrome/android/webapk/OWNERS</owner> <summary> Records number of unique origins for WebAPKs that have been added to WebappRegistry. This is recorded each time on Chrome startup, after the
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml index 5ad607d..ce597c85 100644 --- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml +++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -1351,6 +1351,17 @@ </summary> </histogram> +<histogram name="WebRTC.PeerConnection.RtcpMuxPolicy" + enum="PeerConnectionRtcpMux" expires_after="2023-06-11"> + <owner>hta@chromium.org</owner> + <owner>webrtc-dev@chromium.org</owner> + <owner>phancke@microsoft.com</owner> + <summary> + Which RTCPMuxPolicy was requested for the PeerConnection. Recorded during + the first DTLS connection establishment. + </summary> +</histogram> + <histogram name="WebRTC.PeerConnection.SdpComplexUsage.CreateAnswer" enum="PeerConnectionSdpUsageCategory" expires_after="2022-05-07"> <obsolete>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index f1f6d2b..c65ca8b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -10471,7 +10471,9 @@ <owner>thegreenfrog@chromium.org</owner> <owner>michaeldo@chromium.org</owner> <summary> - Logged when the FindInPage returns a user search request result. + Logged when the FindInPage returns a user search request result. Starting + from M111, this is only logged at the end of the Find session i.e. when the + Find UI is dismissed. </summary> <metric name="HasMatches" enum="Boolean"> <summary> @@ -16024,6 +16026,28 @@ </metric> </event> +<event name="PageLoadInitiatorForAdTagging" singular="True"> + <owner>yaoxia@chromium.org</owner> + <owner>jkarlin@chromium.org</owner> + <summary> + Metrics about the initiator context of a page load (e.g. whether certain + condition was true and/or what triggered the page load). Recorded when a + page commits. The metrics are specific to ad related conditions or purposes. + </summary> + <metric name="FromAdClick" enum="Boolean"> + <summary> + Whether the page was opened due to a click on an ad. + </summary> + </metric> + <metric name="FromUser" enum="Boolean"> + <summary> + Whether the navigation occurred due to a user action. This includes + omnibox navigations as well as renderer initiated navigations with user + activation. + </summary> + </metric> +</event> + <event name="PageWithPassword"> <owner>battre@chromium.org</owner> <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 408ab4a1..e59c6d9 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "e51500880a1dfa116d8e0a9c9d5b7c6b26f6e282", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/facc417319406ebaa00a0b26eca03cbbb03a7e9f/trace_processor_shell.exe" + "hash": "26e5c888058f001990f1058273f6bf7824dace13", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/0e2c11756bbe9a7ce5553bec8120cacb6ee2284d/trace_processor_shell.exe" }, "linux_arm": { "hash": "6373f26144aad58f230d11d6a91efda5a09c9873", "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "55a6e7422a7010087569ee63bb9b5f909c518699", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/61eeba8d065b8fc69f9dee9b36bc94d9d6a0293c/trace_processor_shell" + "hash": "acda920b85c8ee2c08dc18180303487d03221b7b", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/641efa71d6a1134657039277b6c78ad22aa12ebf/trace_processor_shell" }, "mac_arm64": { "hash": "5f47ee79e59d00bf3889d30ca52315522c158040", "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "e4667854f5daa74d0c492536ffdbb926938d9a03", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/82a170d5b41dcb00787fafde01073ad1731ee56b/trace_processor_shell" + "hash": "310429601d1c058886755654685023acab4eb924", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7706133c5b028b83ce0cf64ce340ebbf757305e4/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py index 81c7a4c..d9d262b 100755 --- a/tools/perf/core/results_dashboard.py +++ b/tools/perf/core/results_dashboard.py
@@ -44,8 +44,6 @@ # The paths in the results dashboard URLs for sending results. SEND_RESULTS_PATH = '/add_point' SEND_HISTOGRAMS_PATH = '/add_histograms' -SEND_RESULTS_PATH_FLASK = '/add_point_flask' -SEND_HISTOGRAMS_PATH_FLASK = '/add_histograms_flask' class SendResultException(Exception): @@ -78,8 +76,7 @@ url, send_as_histograms=False, token_generator_callback=LuciAuthTokenGeneratorCallback, - num_retries=4, - force_flask=False): + num_retries=4): """Sends results to the Chrome Performance Dashboard. This function tries to send the given data to the dashboard. @@ -111,12 +108,10 @@ 'Sending %s result of %s to dashboard (attempt %i out of %i).' % (data_type, data_label, i, num_retries)) if send_as_histograms: - _SendHistogramJson(url, dashboard_data_str, token_generator_callback, - force_flask) + _SendHistogramJson(url, dashboard_data_str, token_generator_callback) else: # TODO(eakuefner): Remove this logic once all bots use histograms. - _SendResultsJson(url, dashboard_data_str, token_generator_callback, - force_flask) + _SendResultsJson(url, dashboard_data_str, token_generator_callback) all_data_uploaded = True break except SendResultsRetryException as e: @@ -425,10 +420,7 @@ return test_path -def _SendResultsJson(url, - results_json, - token_generator_callback, - force_flask=False): +def _SendResultsJson(url, results_json, token_generator_callback): """Make a HTTP POST with the given JSON to the Performance Dashboard. Args: @@ -444,10 +436,7 @@ data = six.moves.urllib.parse.urlencode({ 'data': results_json }).encode('utf-8') - if force_flask: - req = six.moves.urllib.request.Request(url + SEND_RESULTS_PATH_FLASK, data) - else: - req = six.moves.urllib.request.Request(url + SEND_RESULTS_PATH, data) + req = six.moves.urllib.request.Request(url + SEND_RESULTS_PATH, data) try: oauth_token = token_generator_callback() req.headers['Authorization'] = 'Bearer %s' % oauth_token @@ -464,10 +453,7 @@ raise SendResultsRetryException(error) -def _SendHistogramJson(url, - histogramset_json, - token_generator_callback, - force_flask=False): +def _SendHistogramJson(url, histogramset_json, token_generator_callback): """POST a HistogramSet JSON to the Performance Dashboard. Args: @@ -492,16 +478,10 @@ http = httplib2.Http() - if force_flask: - response, content = http.request(url + SEND_HISTOGRAMS_PATH_FLASK, - method='POST', - body=data, - headers=headers) - else: - response, content = http.request(url + SEND_HISTOGRAMS_PATH, - method='POST', - body=data, - headers=headers) + response, content = http.request(url + SEND_HISTOGRAMS_PATH, + method='POST', + body=data, + headers=headers) # A 500 is presented on an exception on the dashboard side, timeout, # exception, etc. The dashboard can also send back 400 and 403, we could
diff --git a/tools/perf/core/results_dashboard_unittest.py b/tools/perf/core/results_dashboard_unittest.py index c711ed2..e80f20c 100644 --- a/tools/perf/core/results_dashboard_unittest.py +++ b/tools/perf/core/results_dashboard_unittest.py
@@ -20,13 +20,9 @@ def testRetryForSendResultRetryException(self): - def raise_retry_exception(url, - histogramset_json, - token_generator_callback, - force_flask=False): + def raise_retry_exception(url, histogramset_json, token_generator_callback): del url, histogramset_json # unused del token_generator_callback # unused - del force_flask raise results_dashboard.SendResultsRetryException('Should retry') with mock.patch('core.results_dashboard.time.sleep') as sleep_mock: @@ -87,13 +83,10 @@ def testNoRetryAfterSucessfulSendResult(self): counter = [0] - def raise_retry_exception_first_two_times(url, - histogramset_json, - token_generator_callback, - force_flask=False): + def raise_retry_exception_first_two_times(url, histogramset_json, + token_generator_callback): del url, histogramset_json # unused del token_generator_callback # unused - del force_flask counter[0] += 1 if counter[0] <= 2: raise results_dashboard.SendResultsRetryException('Please retry')
diff --git a/tools/perf/core/shard_maps/timing_data/lacros-eve-perf_timing.json b/tools/perf/core/shard_maps/timing_data/lacros-eve-perf_timing.json index fe4afafa..6f88ecd 100644 --- a/tools/perf/core/shard_maps/timing_data/lacros-eve-perf_timing.json +++ b/tools/perf/core/shard_maps/timing_data/lacros-eve-perf_timing.json
@@ -560,10 +560,6 @@ "name": "blink_perf.events/EventsDispatching.html" }, { - "duration": "68.0", - "name": "blink_perf.events/EventsDispatchingDifferentEventsOnSameNode.html" - }, - { "duration": "69.0", "name": "blink_perf.events/EventsDispatchingInDeeplyNestedV1ShadowTrees.html" },
diff --git a/tools/perf/core/stacktrace_unittest.py b/tools/perf/core/stacktrace_unittest.py index ce021d7f4..0d55710 100644 --- a/tools/perf/core/stacktrace_unittest.py +++ b/tools/perf/core/stacktrace_unittest.py
@@ -12,43 +12,36 @@ class TabStackTraceTest(tab_test_case.TabTestCase): - # Stack traces do not currently work on 10.6, but they are also being - # disabled shortly so just disable it for now. - # All platforms except chromeos should at least have a valid minidump. - # Disabled on Windows: https://crbug.com/971998. - @decorators.Disabled('snowleopard', 'chromeos', 'win', - 'android-nougat') # Flaky: https://crbug.com/1342706 + # Stack traces do not currently work on Mac 10.6. + @decorators.Isolated + @decorators.Disabled('snowleopard', 'chromeos-local') def testValidDump(self): with self.assertRaises(exceptions.DevtoolsTargetCrashException) as c: self._tab.Navigate('chrome://crash', timeout=10) self.assertTrue(c.exception.is_valid_dump) - # Stack traces aren't working on Android yet. - # Disabled on Linux and Mac, flaky: https://crbug.com/820282. - @decorators.Disabled('all') + @decorators.Isolated + @decorators.Disabled('chromeos-local') def testCrashSymbols(self): with self.assertRaises(exceptions.DevtoolsTargetCrashException) as c: - self._tab.Navigate('chrome://crash', timeout=5) + self._tab.Navigate('chrome://crash', timeout=10) self.assertIn('CrashIntentionally', '\n'.join(c.exception.stack_trace)) # Some platforms do not support full stack traces, this test requires only # minimal symbols to be available. - # Disabled on win due to crbug.com/706328. - # Disabled on Linux and Mac, flaky: https://crbug.com/820282. - @decorators.Disabled('all') + @decorators.Isolated + @decorators.Disabled('chromeos-local') def testCrashMinimalSymbols(self): with self.assertRaises(exceptions.DevtoolsTargetCrashException) as c: - self._tab.Navigate('chrome://crash', timeout=5) + self._tab.Navigate('chrome://crash', timeout=10) self.assertIn('HandleRendererDebugURL', '\n'.join(c.exception.stack_trace)) # The breakpad file specific test only apply to platforms which use the # breakpad symbol format. This also must be tested in isolation because it can # potentially interfere with other tests symbol parsing. - # @decorators.Enabled('mac', 'linux') - # Disabled tests due to flakiness: http://crbug.com/820282 - @decorators.Disabled('all') @decorators.Isolated + @decorators.Enabled('linux') def testBadBreakpadFileIgnored(self): # pylint: disable=protected-access executable_path = self._browser._browser_backend._executable @@ -61,15 +54,7 @@ f.write('MODULE PLATFORM ARCH %s %s' % (garbage_hash, executable)) f.flush() with self.assertRaises(exceptions.DevtoolsTargetCrashException) as c: - self._tab.Navigate('chrome://crash', timeout=5) - # The symbol directory should now symbols for out executable. - tmp_dir = os.path.join(self._browser._browser_backend._tmp_minidump_dir) - symbol_dir = os.path.join(tmp_dir, 'symbols') - self.assertTrue(os.path.isdir(symbol_dir)) - - # Bad breakpad file should not be in the symbol directory - garbage_symbol_dir = os.path.join(symbol_dir, executable, garbage_hash) - self.assertFalse(os.path.isdir(garbage_symbol_dir)) + self._tab.Navigate('chrome://crash', timeout=10) # Stack trace should still work. self.assertIn('CrashIntentionally', '\n'.join(c.exception.stack_trace))
diff --git a/tools/perf/core/upload_results_to_perf_dashboard.py b/tools/perf/core/upload_results_to_perf_dashboard.py index 16c9549..448dc96d 100755 --- a/tools/perf/core/upload_results_to_perf_dashboard.py +++ b/tools/perf/core/upload_results_to_perf_dashboard.py
@@ -137,7 +137,6 @@ parser.add_option('--git-revision') parser.add_option('--output-json-dashboard-url') parser.add_option('--send-as-histograms', action='store_true') - parser.add_option('--force-flask', action='store_true') return parser @@ -188,8 +187,7 @@ batch, options.name, options.results_url, - send_as_histograms=options.send_as_histograms, - force_flask=options.force_flask): + send_as_histograms=options.send_as_histograms): return 1 else: # The upload didn't fail since there was no data to upload.
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 37568b22..d9ce2b5 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -718,7 +718,6 @@ crbug.com/1129497 [ win-laptop ] webrtc/multiple_peerconnections [ Skip ] crbug.com/1380407 [ chromeos ] webrtc/multiple_peerconnections [ Skip ] crbug.com/1319408 [ android ] webrtc/insertable_streams_audio_processing [ Skip ] -crbug.com/1382492 [ desktop ] webrtc/negotiate-timing [ Skip ] # Benchmark: system_health_smoke_test crbug.com/1354513 [ win ] system_health.memory_desktop/load:media:imgur:2018 [ Skip ]
diff --git a/tools/perf/page_sets/webrtc_cases/negotiate-timing.js b/tools/perf/page_sets/webrtc_cases/negotiate-timing.js index b86c9754..851b768 100644 --- a/tools/perf/page_sets/webrtc_cases/negotiate-timing.js +++ b/tools/perf/page_sets/webrtc_cases/negotiate-timing.js
@@ -184,7 +184,7 @@ const stats = await audioTransceiver.receiver.getStats(); let currentImpairment; stats.forEach(stat => { - if (stat.type == 'track') { + if (stat.type == 'inbound-rtp') { currentImpairment = stat.concealedSamples; } });
diff --git a/tools/perf/process_perf_results.py b/tools/perf/process_perf_results.py index 671e3d34..deecd19f 100755 --- a/tools/perf/process_perf_results.py +++ b/tools/perf/process_perf_results.py
@@ -133,9 +133,6 @@ except Exception as e: logging.info('Failed to upload results to staging: %s', str(e)) - # upload to flask handler for linux-perf-fyi - args.append('--force-flask') - return upload_results_to_perf_dashboard.main(args) def _is_histogram(json_file):
diff --git a/tools/traffic_annotation/scripts/auditor/auditor.py b/tools/traffic_annotation/scripts/auditor/auditor.py index 975675e3..8362510 100755 --- a/tools/traffic_annotation/scripts/auditor/auditor.py +++ b/tools/traffic_annotation/scripts/auditor/auditor.py
@@ -286,6 +286,9 @@ combination.proto.policy.chrome_policy.extend( other.proto.policy.chrome_policy) + combination.proto.policy.chrome_device_policy.extend( + other.proto.policy.chrome_device_policy) + return combination, [] def needs_two_ids(self) -> bool: @@ -424,10 +427,11 @@ and policy.cookies_allowed == CookiesAllowed.YES): unspecifieds.append("cookies_store") - # If either of 'chrome_policy' or 'policy_exception_justification' are + # If either a policy or a 'policy_exception_justification' are # available, ignore not having the other one. - if not policy.chrome_policy and not policy.policy_exception_justification: + if (not self.has_policy() and not policy.policy_exception_justification): unspecifieds.append("chrome_policy") + unspecifieds.append("chrome_device_policy") unspecifieds.append("policy_exception_justification") if unspecifieds: @@ -452,7 +456,7 @@ self.file, self.line) ] - if policy.chrome_policy and policy.policy_exception_justification: + if self.has_policy() and policy.policy_exception_justification: return [ AuditorError( ErrorType.INCONSISTENT_ANNOTATION, @@ -531,6 +535,11 @@ ] return [] + def has_policy(self) -> bool: + """Return true if any policy field is set""" + return (self.proto.policy.chrome_policy + or self.proto.policy.chrome_device_policy) + def _check_contacts(self) -> Optional[str]: """Checks presence of contacts fields in the annotation. All available contacts fields should contain email"""
diff --git a/tools/traffic_annotation/scripts/auditor/auditor_test.py b/tools/traffic_annotation/scripts/auditor/auditor_test.py index b4dccb0..9dd28a2 100755 --- a/tools/traffic_annotation/scripts/auditor/auditor_test.py +++ b/tools/traffic_annotation/scripts/auditor/auditor_test.py
@@ -422,125 +422,130 @@ test_no = 0 while True: - try: - annotation = self.create_annotation_sample() - annotation.unique_id = "foobar_policy_fetcher{}".format(test_no) - test_description = "" - expect_error = True - logger.info( - "test_check_complete_annotations test number {}".format(test_no)) - if test_no == 0: - test_description = "All fields OK." - expect_error = False - elif test_no == 1: - test_description = "Missing semantics::sender" - annotation.proto.semantics.sender = "" - elif test_no == 2: - test_description = "Missing semantics::description" - annotation.proto.semantics.description = "" - elif test_no == 3: - test_description = "Missing semantics::trigger" - annotation.proto.semantics.trigger = "" - elif test_no == 4: - test_description = "Missing semantics::data" - annotation.proto.semantics.data = "" - elif test_no == 5: - test_description = "Missing semantics::destination" - annotation.proto.semantics.destination = Destination.UNSPECIFIED - elif test_no == 6: - test_description = "Missing policy::cookies_allowed" - annotation.proto.policy.cookies_allowed = CookiesAllowed.UNSPECIFIED - elif test_no == 7: - test_description = \ - "policy::cookies_allowed = NO with existing policy::cookies_store." - annotation.proto.policy.cookies_allowed = CookiesAllowed.NO - annotation.proto.policy.cookies_store = "somewhere" - elif test_no == 8: - test_description = \ - "policy::cookies_allowed = NO and no policy::cookies_store." - annotation.proto.policy.cookies_allowed = CookiesAllowed.NO - annotation.proto.policy.cookies_store = "" - expect_error = False - elif test_no == 9: - test_description = \ - "policy::cookies_allowed = YES and policy::cookies_store exists." - annotation.proto.policy.cookies_allowed = CookiesAllowed.YES - annotation.proto.policy.cookies_store = "somewhere" - expect_error = False - elif test_no == 10: - test_description = \ - "policy::cookies_allowed = YES and no policy::cookies_store." - annotation.proto.policy.cookies_allowed = CookiesAllowed.YES - annotation.proto.policy.cookies_store = "" - elif test_no == 11: - test_description = "Missing policy::setting." - annotation.proto.policy.setting = "" - expect_error = False - elif test_no == 12: - test_description = \ - "Missing policy::chrome_policy and " \ - "policy::policy_exception_justification." - annotation.proto.policy.ClearField("chrome_policy") - annotation.proto.policy.policy_exception_justification = "" - elif test_no == 13: - test_description = \ - "Missing policy::chrome_policy and existing " \ - "policy::policy_exception_justification." - annotation.proto.policy.ClearField("chrome_policy") - annotation.proto.policy.policy_exception_justification = "Because!" - expect_error = False - elif test_no == 14: - test_description = \ - "Existing policy::chrome_policy and no " \ - "policy::policy_exception_justification." - self.assertTrue(annotation.proto.policy.chrome_policy) - annotation.proto.policy.policy_exception_justification = "" - expect_error = False - elif test_no == 15: - test_description = \ - "Existing policy::chrome_policy and existing" \ - "policy::policy_exception_justification." - self.assertTrue(annotation.proto.policy.chrome_policy) - annotation.proto.policy.policy_exception_justification = "Because!" - elif test_no == 16: - test_description = "Missing semantics::internal::contacts" - annotation.proto.semantics.internal.Clear() - elif test_no == 17: - test_description = "Missing semantics::internal::contacts::email" - annotation.proto.semantics.internal.ClearField("contacts") - elif test_no == 18: - test_description = "Missing semantics::internal::user_data::type" - annotation.proto.semantics.user_data.Clear() - elif test_no == 19: - test_description = "Empty value semantics::internal::user_data::type" - annotation.proto.semantics.user_data.ClearField("type") - elif test_no == 20: - test_description = "Invalid format semantics::last_reviewed" - annotation.proto.semantics.last_reviewed = "23-12-2023" - else: - # Done checking individual test cases. - break + annotation = self.create_annotation_sample() + annotation.unique_id = "foobar_policy_fetcher{}".format(test_no) + test_description = "" + expect_error = True + logger.info( + "test_check_complete_annotations test number {}".format(test_no)) + if test_no == 0: + test_description = "All fields OK." + expect_error = False + elif test_no == 1: + test_description = "Missing semantics::sender" + annotation.proto.semantics.sender = "" + elif test_no == 2: + test_description = "Missing semantics::description" + annotation.proto.semantics.description = "" + elif test_no == 3: + test_description = "Missing semantics::trigger" + annotation.proto.semantics.trigger = "" + elif test_no == 4: + test_description = "Missing semantics::data" + annotation.proto.semantics.data = "" + elif test_no == 5: + test_description = "Missing semantics::destination" + annotation.proto.semantics.destination = Destination.UNSPECIFIED + elif test_no == 6: + test_description = "Missing policy::cookies_allowed" + annotation.proto.policy.cookies_allowed = CookiesAllowed.UNSPECIFIED + elif test_no == 7: + test_description = \ + "policy::cookies_allowed = NO with existing policy::cookies_store." + annotation.proto.policy.cookies_allowed = CookiesAllowed.NO + annotation.proto.policy.cookies_store = "somewhere" + elif test_no == 8: + test_description = \ + "policy::cookies_allowed = NO and no policy::cookies_store." + annotation.proto.policy.cookies_allowed = CookiesAllowed.NO + annotation.proto.policy.cookies_store = "" + expect_error = False + elif test_no == 9: + test_description = \ + "policy::cookies_allowed = YES and policy::cookies_store exists." + annotation.proto.policy.cookies_allowed = CookiesAllowed.YES + annotation.proto.policy.cookies_store = "somewhere" + expect_error = False + elif test_no == 10: + test_description = \ + "policy::cookies_allowed = YES and no policy::cookies_store." + annotation.proto.policy.cookies_allowed = CookiesAllowed.YES + annotation.proto.policy.cookies_store = "" + elif test_no == 11: + test_description = "Missing policy::setting." + annotation.proto.policy.setting = "" + expect_error = False + elif test_no == 12: + test_description = \ + "Missing chrome policy and " \ + "policy::policy_exception_justification." + annotation.proto.policy.ClearField("chrome_policy") + annotation.proto.policy.ClearField("chrome_device_policy") + annotation.proto.policy.policy_exception_justification = "" + elif test_no == 13: + test_description = \ + "Missing chrome policy and existing " \ + "policy::policy_exception_justification." + annotation.proto.policy.ClearField("chrome_policy") + annotation.proto.policy.ClearField("chrome_device_policy") + annotation.proto.policy.policy_exception_justification = "Because!" + expect_error = False + elif test_no == 14: + test_description = \ + "Existing chrome policy and no " \ + "policy::policy_exception_justification." + self.assertTrue(annotation.proto.policy.chrome_policy) + annotation.proto.policy.policy_exception_justification = "" + expect_error = False + elif test_no == 15: + test_description = \ + "Existing chrome policy and existing " \ + "policy::policy_exception_justification." + self.assertTrue(annotation.proto.policy.chrome_policy) + annotation.proto.policy.policy_exception_justification = "Because!" + elif test_no == 16: + test_description = "Missing semantics::internal::contacts" + annotation.proto.semantics.internal.Clear() + elif test_no == 17: + test_description = "Missing semantics::internal::contacts::email" + annotation.proto.semantics.internal.ClearField("contacts") + elif test_no == 18: + test_description = "Missing semantics::internal::user_data::type" + annotation.proto.semantics.user_data.Clear() + elif test_no == 19: + test_description = "Empty value semantics::internal::user_data::type" + annotation.proto.semantics.user_data.ClearField("type") + elif test_no == 20: + test_description = "Invalid format semantics::last_reviewed" + annotation.proto.semantics.last_reviewed = "23-12-2023" + elif test_no == 21: + test_description = \ + "Existing chrome policy (device policy only) and " \ + "missing policy::policy_exception_justification." + self.assertTrue(annotation.proto.policy.chrome_device_policy) + annotation.proto.policy.ClearField("chrome_policy") + annotation.proto.policy.policy_exception_justification = "" + expect_error = False + else: + # Done checking individual test cases. + break - logger.debug("Testing: {}".format(test_description)) + logger.debug("Testing: {}".format(test_description)) - self.auditor.extracted_annotations = [annotation] - errors = self.auditor.check_annotation_contents() + self.auditor.extracted_annotations = [annotation] + errors = self.auditor.check_annotation_contents() - if expect_error: - self.assertEqual(1, len(errors), - "test_no={}, errors={}".format(test_no, errors)) - else: - self.assertEqual([], errors, - "test_no={}, errors={}".format(test_no, errors)) + if expect_error: + self.assertEqual(1, len(errors), + "test_no={}, errors={}".format(test_no, errors)) + else: + self.assertEqual([], errors, + "test_no={}, errors={}".format(test_no, errors)) - annotations.append(annotation) + annotations.append(annotation) - if expect_error: - expected_errors_count += 1 - - except Exception as ex: - logger.error("Exception occurred in test_check_complete_annotations", - ex) + if expect_error: + expected_errors_count += 1 test_no += 1 @@ -576,7 +581,8 @@ other = self.create_annotation_sample() instance.proto.semantics.Clear() - instance.proto.policy.Clear() + instance.proto.policy.ClearField('chrome_policy') + other.proto.policy.ClearField('chrome_device_policy') instance.type = Annotation.Type.PARTIAL other.type = Annotation.Type.COMPLETING @@ -593,9 +599,15 @@ other.type = Annotation.Type.BRANCHED_COMPLETING other.second_id = "SomeID" instance.second_id = "SomeID" + self.assertEqual(len(instance.proto.policy.chrome_policy), 0) + self.assertEqual(len(instance.proto.policy.chrome_device_policy), 1) + self.assertEqual(len(other.proto.policy.chrome_policy), 1) + self.assertEqual(len(other.proto.policy.chrome_device_policy), 0) combination, errors = instance.create_complete_annotation(other) self.assertEqual([], errors) self.assertEqual(combination.unique_id_hash_code, other.unique_id_hash_code) + self.assertEqual(len(combination.proto.policy.chrome_policy), 1) + self.assertEqual(len(combination.proto.policy.chrome_device_policy), 1) # Inconsistent field. Destination = traffic_annotation.TrafficSemantics.Destination @@ -756,7 +768,7 @@ self.assertEqual(ErrorType.INCOMPLETE_ANNOTATION, result.type) expected_missing_fields = [ - "sender", "chrome_policy", "cookies_store", + "sender", "chrome_policy", "chrome_device_policy", "cookies_store", "policy_exception_justification" ] missing_fields = str(result).split("missing fields:", @@ -880,7 +892,7 @@ expected_contents = """Unique ID\tLast Update\tSender\tDescription\tTrigger\tData\tDestination\tCookies Allowed\tCookies Store\tSetting\tChrome Policy\tComments\tSource File supervised_user_refresh_token_fetcher\t\tSupervised Users\tFetches an OAuth2 refresh token scoped down to the Supervised User Sync scope and tied to the given Supervised User ID, identifying the Supervised User Profile to be created.\tCalled when creating a new Supervised User profile in Chromium to fetch OAuth credentials for using Sync with the new profile.\t"The request is authenticated with an OAuth2 access token identifying the Google account and contains the following information: * The Supervised User ID, a randomly generated 64-bit identifier for the profile. -* The device name, to identify the refresh token in account management."\tGoogle\tNo\t\tUsers can disable this feature by toggling 'Let anyone add a person to Chrome' in Chromium settings, under People.\tSupervisedUserCreationEnabled: false\t\thttps://cs.chromium.org/chromium/src/?l=0 +* The device name, to identify the refresh token in account management."\tGoogle\tNo\t\tUsers can disable this feature by toggling 'Let anyone add a person to Chrome' in Chromium settings, under People.\tSupervisedUserCreationEnabled: false, external_policy: ""\t\thttps://cs.chromium.org/chromium/src/?l=0 """ self.assertEqual(expected_contents, tsv_contents)
diff --git a/tools/traffic_annotation/scripts/auditor/util.py b/tools/traffic_annotation/scripts/auditor/util.py index 1dc0ccc..6f16d959 100644 --- a/tools/traffic_annotation/scripts/auditor/util.py +++ b/tools/traffic_annotation/scripts/auditor/util.py
@@ -8,6 +8,7 @@ import sys from functools import reduce +from itertools import chain from google.protobuf import text_format from google.protobuf.descriptor import FieldDescriptor from google.protobuf.message import Message @@ -260,8 +261,9 @@ line += "\t{}".format(escape_for_tsv(policy.setting)) # Chrome policies. - if policy.chrome_policy: - policies_text = policy_to_text(policy.chrome_policy) + if annotation.has_policy(): + policies_text = policy_to_text( + chain(policy.chrome_policy, policy.chrome_device_policy)) else: policies_text = policy.policy_exception_justification line += "\t{}".format(escape_for_tsv(policies_text))
diff --git a/tools/traffic_annotation/scripts/test_data/extractor_outputs/good_complete_annotation.txt b/tools/traffic_annotation/scripts/test_data/extractor_outputs/good_complete_annotation.txt index b2dced8..24a0be3 100644 --- a/tools/traffic_annotation/scripts/test_data/extractor_outputs/good_complete_annotation.txt +++ b/tools/traffic_annotation/scripts/test_data/extractor_outputs/good_complete_annotation.txt
@@ -41,4 +41,9 @@ SupervisedUserCreationEnabled: false } } + chrome_device_policy { + device_printers { + external_policy: "" + } + } } \ No newline at end of file
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_device_policy_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_device_policy_pb2.py new file mode 100644 index 0000000..f3227e4 --- /dev/null +++ b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_device_policy_pb2.py
@@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: chrome_device_policy.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import policy_common_definitions_pb2 as policy__common__definitions__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x63hrome_device_policy.proto\x12\x15\x65nterprise_management\x1a\x1fpolicy_common_definitions.proto\"B\n\x1c\x44\x65vicePolicyRefreshRateProto\x12\"\n\x1a\x64\x65vice_policy_refresh_rate\x18\x01 \x01(\x03\",\n\x12UserWhitelistProto\x12\x16\n\x0euser_whitelist\x18\x01 \x03(\t\",\n\x12UserAllowlistProto\x12\x16\n\x0euser_allowlist\x18\x01 \x03(\t\"3\n\x12\x41llowNewUsersProto\x12\x1d\n\x0f\x61llow_new_users\x18\x01 \x01(\x08:\x04true\"9\n\x15GuestModeEnabledProto\x12 \n\x12guest_mode_enabled\x18\x01 \x01(\x08:\x04true\";\n\x1aShowUserNamesOnSigninProto\x12\x1d\n\x0fshow_user_names\x18\x01 \x01(\x08:\x04true\">\n\x17\x44\x61taRoamingEnabledProto\x12#\n\x14\x64\x61ta_roaming_enabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"\xb3\x01\n!OBSOLETE_DeviceProxySettingsProto\x12\x1f\n\x13OBSOLETE_proxy_mode\x18\x01 \x01(\tB\x02\x18\x01\x12!\n\x15OBSOLETE_proxy_server\x18\x02 \x01(\tB\x02\x18\x01\x12\"\n\x16OBSOLETE_proxy_pac_url\x18\x03 \x01(\tB\x02\x18\x01\x12&\n\x1aOBSOLETE_proxy_bypass_list\x18\x04 \x01(\tB\x02\x18\x01\",\n\x12\x43\x61meraEnabledProto\x12\x16\n\x0e\x63\x61mera_enabled\x18\x01 \x01(\x08\".\n\x13MetricsEnabledProto\x12\x17\n\x0fmetrics_enabled\x18\x01 \x01(\x08\"j\n\x13ReleaseChannelProto\x12\x17\n\x0frelease_channel\x18\x01 \x01(\t\x12!\n\x19release_channel_delegated\x18\x02 \x01(\x08\x12\x17\n\x0frelease_lts_tag\x18\x03 \x01(\t\"I\n#DeviceOpenNetworkConfigurationProto\x12\"\n\x1aopen_network_configuration\x18\x01 \x01(\t\"8\n\x14NetworkHostnameProto\x12 \n\x18\x64\x65vice_hostname_template\x18\x01 \x01(\t\"?\n%DeviceHindiInscriptLayoutEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"Q\n\x1dHostnameUserConfigurableProto\x12\x30\n!device_hostname_user_configurable\x18\x01 \x01(\x08:\x05\x66\x61lse\"\x92\x0c\n\x14\x44\x65viceReportingProto\x12!\n\x13report_version_info\x18\x01 \x01(\x08:\x04true\x12#\n\x15report_activity_times\x18\x02 \x01(\x08:\x04true\x12\x1e\n\x10report_boot_mode\x18\x03 \x01(\x08:\x04true\x12\x1e\n\x0freport_location\x18\x04 \x01(\x08:\x05\x66\x61lse\x12+\n\x19report_network_interfaces\x18\x05 \x01(\x08:\x04trueB\x02\x18\x01\x12\x1a\n\x0creport_users\x18\x06 \x01(\x08:\x04true\x12(\n\x16report_hardware_status\x18\x07 \x01(\x08:\x04trueB\x02\x18\x01\x12#\n\x15report_session_status\x18\x08 \x01(\x08:\x04true\x12&\n\x17report_os_update_status\x18\n \x01(\x08:\x05\x66\x61lse\x12\'\n\x18report_running_kiosk_app\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\"\n\x13report_power_status\x18\x0c \x01(\x08:\x05\x66\x61lse\x12$\n\x15report_storage_status\x18\r \x01(\x08:\x05\x66\x61lse\x12\"\n\x13report_board_status\x18\x0e \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0freport_cpu_info\x18\x0f \x01(\x08:\x05\x66\x61lse\x12%\n\x16report_graphics_status\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\'\n\x18report_crash_report_info\x18\x11 \x01(\x08:\x05\x66\x61lse\x12#\n\x14report_timezone_info\x18\x12 \x01(\x08:\x05\x66\x61lse\x12!\n\x12report_memory_info\x18\x13 \x01(\x08:\x05\x66\x61lse\x12$\n\x15report_backlight_info\x18\x14 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0freport_app_info\x18\x15 \x01(\x08:\x05\x66\x61lse\x12$\n\x15report_bluetooth_info\x18\x16 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0freport_fan_info\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0freport_vpd_info\x18\x18 \x01(\x08:\x05\x66\x61lse\x12!\n\x12report_system_info\x18\x19 \x01(\x08:\x05\x66\x61lse\x12 \n\x11report_print_jobs\x18\x1a \x01(\x08:\x05\x66\x61lse\x12\"\n\x13report_login_logout\x18\x1b \x01(\x08:\x05\x66\x61lse\x12!\n\x13report_audio_status\x18\x1c \x01(\x08:\x04true\x12*\n\x1creport_network_configuration\x18\x1d \x01(\x08:\x04true\x12#\n\x15report_network_status\x18\x1e \x01(\x08:\x04true\x12%\n\x16report_security_status\x18\x1f \x01(\x08:\x05\x66\x61lse\x12\"\n\x13report_crd_sessions\x18$ \x01(\x08:\x05\x66\x61lse\x12!\n\x12report_peripherals\x18% \x01(\x08:\x05\x66\x61lse\x12)\n\x17\x64\x65vice_status_frequency\x18\t \x01(\x03:\x08\x31\x30\x38\x30\x30\x30\x30\x30\x12+\n\x19\x65nable_granular_reporting\x18 \x01(\x08:\x04trueB\x02\x18\x01\x12<\n+report_network_telemetry_collection_rate_ms\x18! \x01(\x03:\x07\x33\x36\x30\x30\x30\x30\x30\x12?\n/report_network_telemetry_event_checking_rate_ms\x18\" \x01(\x03:\x06\x36\x30\x30\x30\x30\x30\x12;\n+report_device_audio_status_checking_rate_ms\x18# \x01(\x03:\x06\x36\x30\x30\x30\x30\x30\x12X\n-report_signal_strength_event_driven_telemetry\x18& \x01(\x0b\x32!.enterprise_management.StringList\"=\n\x1a\x45phemeralUsersEnabledProto\x12\x1f\n\x17\x65phemeral_users_enabled\x18\x01 \x01(\x08\"B\n/DeviceKeylockerForStorageEncryptionEnabledProto\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\"\x82\x01\n\x1aOBSOLETE_AppPackEntryProto\x12!\n\x15OBSOLETE_extension_id\x18\x01 \x01(\tB\x02\x18\x01\x12\x1f\n\x13OBSOLETE_update_url\x18\x02 \x01(\tB\x02\x18\x01\x12 \n\x14OBSOLETE_online_only\x18\x03 \x01(\x08\x42\x02\x18\x01\"`\n\x15OBSOLETE_AppPackProto\x12G\n\x08\x61pp_pack\x18\x01 \x03(\x0b\x32\x31.enterprise_management.OBSOLETE_AppPackEntryProtoB\x02\x18\x01\"7\n\x18OBSOLETE_PinnedAppsProto\x12\x1b\n\x0fOBSOLETE_app_id\x18\x01 \x03(\tB\x02\x18\x01\"\x81\x01\n\"OBSOLETE_ForcedLogoutTimeoutsProto\x12(\n\x1cOBSOLETE_idle_logout_timeout\x18\x01 \x01(\x03\x42\x02\x18\x01\x12\x31\n%OBSOLETE_idle_logout_warning_duration\x18\x02 \x01(\x03\x42\x02\x18\x01\"v\n\x19OBSOLETE_ScreenSaverProto\x12.\n\"OBSOLETE_screen_saver_extension_id\x18\x01 \x01(\tB\x02\x18\x01\x12)\n\x1dOBSOLETE_screen_saver_timeout\x18\x02 \x01(\x03\x42\x02\x18\x01\"\x83\n\n\x17\x41utoUpdateSettingsProto\x12\x17\n\x0fupdate_disabled\x18\x01 \x01(\x08\x12\x1d\n\x15target_version_prefix\x18\x02 \x01(\t\x12#\n\x1btarget_version_display_name\x18\x03 \x01(\t\x12!\n\x19scatter_factor_in_seconds\x18\x04 \x01(\x03\x12_\n\x18\x61llowed_connection_types\x18\x05 \x03(\x0e\x32=.enterprise_management.AutoUpdateSettingsProto.ConnectionType\x12(\n\x1cOBSOLETE_reboot_after_update\x18\x06 \x01(\x08\x42\x02\x18\x01\x12%\n\x16http_downloads_enabled\x18\x07 \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x13reboot_after_update\x18\x08 \x01(\x08\x12\x1a\n\x0bp2p_enabled\x18\t \x01(\x08:\x05\x66\x61lse\x12}\n\x1arollback_to_target_version\x18\n \x01(\x0e\x32\x46.enterprise_management.AutoUpdateSettingsProto.RollbackToTargetVersion:\x11ROLLBACK_DISABLED\x12&\n\x1brollback_allowed_milestones\x18\x0b \x01(\x05:\x01\x30\x12!\n\x19\x64isallowed_time_intervals\x18\x0c \x01(\t\x12\x18\n\x10staging_schedule\x18\x0e \x01(\t\x12$\n\x1c\x64\x65vice_quick_fix_build_token\x18\x0f \x01(\t\x12\x86\x01\n\x1a\x63hannel_downgrade_behavior\x18\x10 \x01(\x0e\x32G.enterprise_management.AutoUpdateSettingsProto.ChannelDowngradeBehavior:\x19WAIT_FOR_VERSION_CATCH_UP\x12\x1f\n\x17target_version_selector\x18\x11 \x01(\t\"\xa0\x01\n\x0e\x43onnectionType\x12\x1c\n\x18\x43ONNECTION_TYPE_ETHERNET\x10\x00\x12\x18\n\x14\x43ONNECTION_TYPE_WIFI\x10\x01\x12\x19\n\x15\x43ONNECTION_TYPE_WIMAX\x10\x02\x12\x1d\n\x19\x43ONNECTION_TYPE_BLUETOOTH\x10\x03\x12\x1c\n\x18\x43ONNECTION_TYPE_CELLULAR\x10\x04\"\x8c\x01\n\x17RollbackToTargetVersion\x12\x18\n\x14ROLLBACK_UNSPECIFIED\x10\x00\x12\x15\n\x11ROLLBACK_DISABLED\x10\x01\x12\x1a\n\x16ROLLBACK_AND_POWERWASH\x10\x02\x12$\n ROLLBACK_AND_RESTORE_IF_POSSIBLE\x10\x03\"\x90\x01\n\x18\x43hannelDowngradeBehavior\x12*\n&CHANNEL_DOWNGRADE_BEHAVIOR_UNSPECIFIED\x10\x00\x12\x1d\n\x19WAIT_FOR_VERSION_CATCH_UP\x10\x01\x12\x0c\n\x08ROLLBACK\x10\x02\x12\x1b\n\x17\x41LLOW_USER_TO_CONFIGURE\x10\x03J\x04\x08\r\x10\x0e\"?\n\x19OBSOLETE_StartUpUrlsProto\x12\"\n\x16OBSOLETE_start_up_urls\x18\x01 \x03(\tB\x02\x18\x01\"\x9c\x02\n\x13SystemTimezoneProto\x12\x10\n\x08timezone\x18\x01 \x01(\t\x12j\n\x17timezone_detection_type\x18\x02 \x01(\x0e\x32I.enterprise_management.SystemTimezoneProto.AutomaticTimezoneDetectionType\"\x86\x01\n\x1e\x41utomaticTimezoneDetectionType\x12\x10\n\x0cUSERS_DECIDE\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x0b\n\x07IP_ONLY\x10\x02\x12\x1b\n\x17SEND_WIFI_ACCESS_POINTS\x10\x03\x12\x1a\n\x16SEND_ALL_LOCATION_INFO\x10\x04\"5\n\x19SystemUse24HourClockProto\x12\x18\n\x10use_24hour_clock\x18\x01 \x01(\x08\"7\n\x11KioskAppInfoProto\x12\x0e\n\x06\x61pp_id\x18\x01 \x01(\t\x12\x12\n\nupdate_url\x18\x02 \x01(\t\"j\n\x18\x41ndroidKioskAppInfoProto\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x12\n\nclass_name\x18\x02 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x03 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x04 \x01(\t\"D\n\x14WebKioskAppInfoProto\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\r\n\x05title\x18\x02 \x01(\t\x12\x10\n\x08icon_url\x18\x03 \x01(\t\"\xa9\x04\n\x1b\x44\x65viceLocalAccountInfoProto\x12$\n\x1c\x64\x65precated_public_session_id\x18\x01 \x01(\t\x12\x12\n\naccount_id\x18\x02 \x01(\t\x12L\n\x04type\x18\x03 \x01(\x0e\x32>.enterprise_management.DeviceLocalAccountInfoProto.AccountType\x12;\n\tkiosk_app\x18\x04 \x01(\x0b\x32(.enterprise_management.KioskAppInfoProto\x12J\n\x11\x61ndroid_kiosk_app\x18\x05 \x01(\x0b\x32/.enterprise_management.AndroidKioskAppInfoProto\x12\x42\n\rweb_kiosk_app\x18\x06 \x01(\x0b\x32+.enterprise_management.WebKioskAppInfoProto\"\xb4\x01\n\x0b\x41\x63\x63ountType\x12\x1f\n\x1b\x41\x43\x43OUNT_TYPE_PUBLIC_SESSION\x10\x00\x12\x1a\n\x16\x41\x43\x43OUNT_TYPE_KIOSK_APP\x10\x01\x12\"\n\x1e\x41\x43\x43OUNT_TYPE_KIOSK_ANDROID_APP\x10\x02\x12$\n ACCOUNT_TYPE_SAML_PUBLIC_SESSION\x10\x03\x12\x1e\n\x1a\x41\x43\x43OUNT_TYPE_WEB_KIOSK_APP\x10\x04\"\xe8\x01\n\x18\x44\x65viceLocalAccountsProto\x12\x43\n\x07\x61\x63\x63ount\x18\x01 \x03(\x0b\x32\x32.enterprise_management.DeviceLocalAccountInfoProto\x12\x15\n\rauto_login_id\x18\x02 \x01(\t\x12\x18\n\x10\x61uto_login_delay\x18\x03 \x01(\x03\x12\'\n\x19\x65nable_auto_login_bailout\x18\x04 \x01(\x08:\x04true\x12-\n\x1fprompt_for_network_when_offline\x18\x05 \x01(\x08:\x04true\"@\n\'ManagedGuestSessionPrivacyWarningsProto\x12\x15\n\x07\x65nabled\x18\x01 \x01(\x08:\x04true\"O\n*AllowRedeemChromeOsRegistrationOffersProto\x12!\n\x13\x61llow_redeem_offers\x18\x01 \x01(\x08:\x04true\"@\n\x11\x46\x65\x61tureFlagsProto\x12\x14\n\x08switches\x18\x01 \x03(\tB\x02\x18\x01\x12\x15\n\rfeature_flags\x18\x02 \x03(\t\"K\n\x10UptimeLimitProto\x12!\n\x15OBSOLETE_uptime_limit\x18\x01 \x01(\x03\x42\x02\x18\x01\x12\x14\n\x0cuptime_limit\x18\x02 \x01(\x03\"-\n\x18VariationsParameterProto\x12\x11\n\tparameter\x18\x01 \x01(\t\"h\n\x18\x41ttestationSettingsProto\x12\"\n\x13\x61ttestation_enabled\x18\x01 \x01(\x08:\x05\x66\x61lse\x12(\n\x1a\x63ontent_protection_enabled\x18\x02 \x01(\x08:\x04true\"\xcc\x13\n\x1a\x41\x63\x63\x65ssibilitySettingsProto\x12\x31\n)login_screen_default_large_cursor_enabled\x18\x01 \x01(\x08\x12\x34\n,login_screen_default_spoken_feedback_enabled\x18\x02 \x01(\x08\x12\x32\n*login_screen_default_high_contrast_enabled\x18\x03 \x01(\x08\x12y\n*login_screen_default_screen_magnifier_type\x18\x04 \x01(\x0e\x32\x45.enterprise_management.AccessibilitySettingsProto.ScreenMagnifierType\x12\x35\n-login_screen_default_virtual_keyboard_enabled\x18\x05 \x01(\x08\x12)\n!login_screen_large_cursor_enabled\x18\x06 \x01(\x08\x12W\n)login_screen_large_cursor_enabled_options\x18\x07 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$login_screen_spoken_feedback_enabled\x18\x08 \x01(\x08\x12Z\n,login_screen_spoken_feedback_enabled_options\x18\t \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"login_screen_high_contrast_enabled\x18\n \x01(\x08\x12X\n*login_screen_high_contrast_enabled_options\x18\x0b \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%login_screen_virtual_keyboard_enabled\x18\x0c \x01(\x08\x12[\n-login_screen_virtual_keyboard_enabled_options\x18\r \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1elogin_screen_dictation_enabled\x18\x0e \x01(\x08\x12T\n&login_screen_dictation_enabled_options\x18\x0f \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$login_screen_select_to_speak_enabled\x18\x10 \x01(\x08\x12Z\n,login_screen_select_to_speak_enabled_options\x18\x11 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%login_screen_cursor_highlight_enabled\x18\x12 \x01(\x08\x12[\n-login_screen_cursor_highlight_enabled_options\x18\x13 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$login_screen_caret_highlight_enabled\x18\x14 \x01(\x08\x12Z\n,login_screen_caret_highlight_enabled_options\x18\x15 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1flogin_screen_mono_audio_enabled\x18\x16 \x01(\x08\x12U\n\'login_screen_mono_audio_enabled_options\x18\x17 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1elogin_screen_autoclick_enabled\x18\x18 \x01(\x08\x12T\n&login_screen_autoclick_enabled_options\x18\x19 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n login_screen_sticky_keys_enabled\x18\x1a \x01(\x08\x12V\n(login_screen_sticky_keys_enabled_options\x18\x1b \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-login_screen_keyboard_focus_highlight_enabled\x18\x1c \x01(\x08\x12\x63\n5login_screen_keyboard_focus_highlight_enabled_options\x18\x1d \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"login_screen_screen_magnifier_type\x18\x1e \x01(\x03\x12X\n*login_screen_screen_magnifier_type_options\x18\x1f \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n5login_screen_show_options_in_system_tray_menu_enabled\x18 \x01(\x08\x12k\n=login_screen_show_options_in_system_tray_menu_enabled_options\x18! \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1elogin_screen_shortcuts_enabled\x18\" \x01(\x08\x12T\n&login_screen_shortcuts_enabled_options\x18# \x01(\x0b\x32$.enterprise_management.PolicyOptions\"U\n\x13ScreenMagnifierType\x12\x1e\n\x1aSCREEN_MAGNIFIER_TYPE_NONE\x10\x00\x12\x1e\n\x1aSCREEN_MAGNIFIER_TYPE_FULL\x10\x01\"V\n%OBSOLETE_SupervisedUsersSettingsProto\x12-\n!OBSOLETE_supervised_users_enabled\x18\x01 \x01(\x08\x42\x02\x18\x01\"H\n\x1fLoginScreenPowerManagementProto\x12%\n\x1dlogin_screen_power_management\x18\x01 \x01(\t\"4\n\x17\x41utoCleanupSettigsProto\x12\x19\n\x11\x63lean_up_strategy\x18\x01 \x01(\t\",\n\x13SystemSettingsProto\x12\x15\n\rblock_devmode\x18\x01 \x01(\x08\"p\n\x11SAMLSettingsProto\x12\x1d\n\x15transfer_saml_cookies\x18\x01 \x01(\x08\x12<\n0OBSOLETE_url_parameter_to_autofill_saml_username\x18\x02 \x01(\tB\x02\x18\x01\"D\n\x11SAMLUsernameProto\x12/\n\'url_parameter_to_autofill_saml_username\x18\x01 \x01(\t\":\n\x15RebootOnShutdownProto\x12!\n\x12reboot_on_shutdown\x18\x01 \x01(\x08:\x05\x66\x61lse\"e\n\x1c\x44\x65viceHeartbeatSettingsProto\x12 \n\x11heartbeat_enabled\x18\x01 \x01(\x08:\x05\x66\x61lse\x12#\n\x13heartbeat_frequency\x18\x02 \x01(\x03:\x06\x31\x32\x30\x30\x30\x30\"7\n\x17\x45xtensionCacheSizeProto\x12\x1c\n\x14\x65xtension_cache_size\x18\x01 \x01(\x03\"O\n\"LoginScreenDomainAutoCompleteProto\x12)\n!login_screen_domain_auto_complete\x18\x01 \x01(\t\"H\n\x1c\x44\x65viceLogUploadSettingsProto\x12(\n\x19system_log_upload_enabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"\xc5\x01\n\x1b\x44isplayRotationDefaultProto\x12]\n\x18\x64isplay_rotation_default\x18\x01 \x01(\x0e\x32;.enterprise_management.DisplayRotationDefaultProto.Rotation\"G\n\x08Rotation\x12\x0c\n\x08ROTATE_0\x10\x00\x12\r\n\tROTATE_90\x10\x01\x12\x0e\n\nROTATE_180\x10\x02\x12\x0e\n\nROTATE_270\x10\x03\"D\n*DeviceLoginScreenPrivacyScreenEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"A\n\x1c\x44\x65viceDisplayResolutionProto\x12!\n\x19\x64\x65vice_display_resolution\x18\x01 \x01(\t\"_\n&AllowKioskAppControlChromeVersionProto\x12\x35\n&allow_kiosk_app_control_chrome_version\x18\x01 \x01(\x08:\x05\x66\x61lse\"\xc8\x01\n LoginAuthenticationBehaviorProto\x12r\n\x1dlogin_authentication_behavior\x18\x01 \x01(\x0e\x32\x45.enterprise_management.LoginAuthenticationBehaviorProto.LoginBehavior:\x04GAIA\"0\n\rLoginBehavior\x12\x08\n\x04GAIA\x10\x00\x12\x15\n\x11SAML_INTERSTITIAL\x10\x01\"9\n\x10UsbDeviceIdProto\x12\x11\n\tvendor_id\x18\x01 \x01(\x05\x12\x12\n\nproduct_id\x18\x02 \x01(\x05\"R\n\x1bUsbDetachableWhitelistProto\x12\x33\n\x02id\x18\x01 \x03(\x0b\x32\'.enterprise_management.UsbDeviceIdProto\"B\n\x19UsbDeviceIdInclusiveProto\x12\x11\n\tvendor_id\x18\x01 \x01(\x05\x12\x12\n\nproduct_id\x18\x02 \x01(\x05\"[\n\x1bUsbDetachableAllowlistProto\x12<\n\x02id\x18\x01 \x03(\x0b\x32\x30.enterprise_management.UsbDeviceIdInclusiveProto\"4\n\x13\x41llowBluetoothProto\x12\x1d\n\x0f\x61llow_bluetooth\x18\x01 \x01(\x08:\x04true\";\n\x16\x44\x65viceWiFiAllowedProto\x12!\n\x13\x64\x65vice_wifi_allowed\x18\x01 \x01(\x08:\x04true\"C\n DeviceQuirksDownloadEnabledProto\x12\x1f\n\x17quirks_download_enabled\x18\x01 \x01(\x08\"1\n!LoginVideoCaptureAllowedUrlsProto\x12\x0c\n\x04urls\x18\x01 \x03(\t\"S\n$DeviceWiFiFastTransitionEnabledProto\x12+\n#device_wifi_fast_transition_enabled\x18\x01 \x01(\x08\"u\n\x1dNetworkThrottlingEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\x12\x1c\n\x11upload_rate_kbits\x18\x02 \x01(\x05:\x01\x30\x12\x1e\n\x13\x64ownload_rate_kbits\x18\x03 \x01(\x05:\x01\x30\"J\n DeviceLoginScreenExtensionsProto\x12&\n\x1e\x64\x65vice_login_screen_extensions\x18\x01 \x03(\t\"\x98\x02\n/LoginScreenExtensionManifestV2AvailabilityProto\x12\x8c\x01\n/login_screen_extension_manifest_v2_availability\x18\x01 \x01(\x0e\x32S.enterprise_management.LoginScreenExtensionManifestV2AvailabilityProto.Availability\"V\n\x0c\x41vailability\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0b\n\x07\x44ISABLE\x10\x01\x12\n\n\x06\x45NABLE\x10\x02\x12 \n\x1c\x45NABLE_FOR_FORCED_EXTENSIONS\x10\x03\"7\n\x17LoginScreenLocalesProto\x12\x1c\n\x14login_screen_locales\x18\x01 \x03(\t\"B\n\x1cLoginScreenInputMethodsProto\x12\"\n\x1alogin_screen_input_methods\x18\x01 \x03(\t\";\n\x19\x44\x65viceWallpaperImageProto\x12\x1e\n\x16\x64\x65vice_wallpaper_image\x18\x01 \x01(\t\"\xd8\x01\n$DeviceEcryptfsMigrationStrategyProto\x12i\n\x12migration_strategy\x18\x01 \x01(\x0e\x32M.enterprise_management.DeviceEcryptfsMigrationStrategyProto.MigrationStrategy\"E\n\x11MigrationStrategy\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0c\x44ISALLOW_ARC\x10\x01\x12\x13\n\x0f\x41LLOW_MIGRATION\x10\x02\"\xba\x01\n%DeviceSecondFactorAuthenticationProto\x12R\n\x04mode\x18\x01 \x01(\x0e\x32\x44.enterprise_management.DeviceSecondFactorAuthenticationProto.U2fMode\"=\n\x07U2fMode\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x07\n\x03U2F\x10\x02\x12\x10\n\x0cU2F_EXTENDED\x10\x03\"%\n\x15\x43\x61stReceiverNameProto\x12\x0c\n\x04name\x18\x01 \x01(\t\"\xed\x01\n\x0fWeeklyTimeProto\x12\x45\n\x0b\x64\x61y_of_week\x18\x01 \x01(\x0e\x32\x30.enterprise_management.WeeklyTimeProto.DayOfWeek\x12\x0c\n\x04time\x18\x02 \x01(\x05\"\x84\x01\n\tDayOfWeek\x12\x1b\n\x17\x44\x41Y_OF_WEEK_UNSPECIFIED\x10\x00\x12\n\n\x06MONDAY\x10\x01\x12\x0b\n\x07TUESDAY\x10\x02\x12\r\n\tWEDNESDAY\x10\x03\x12\x0c\n\x08THURSDAY\x10\x04\x12\n\n\x06\x46RIDAY\x10\x05\x12\x0c\n\x08SATURDAY\x10\x06\x12\n\n\x06SUNDAY\x10\x07\"\x85\x01\n\x17WeeklyTimeIntervalProto\x12\x35\n\x05start\x18\x01 \x01(\x0b\x32&.enterprise_management.WeeklyTimeProto\x12\x33\n\x03\x65nd\x18\x02 \x01(\x0b\x32&.enterprise_management.WeeklyTimeProto\"\x8d\x01\n\x13\x44\x65viceOffHoursProto\x12\x41\n\tintervals\x18\x01 \x03(\x0b\x32..enterprise_management.WeeklyTimeIntervalProto\x12\x10\n\x08timezone\x18\x02 \x01(\t\x12!\n\x19ignored_policy_proto_tags\x18\x03 \x03(\x05\"4\n\x19\x44\x65viceNativePrintersProto\x12\x17\n\x0f\x65xternal_policy\x18\x01 \x01(\t\"\xda\x01\n#DeviceNativePrintersAccessModeProto\x12Z\n\x0b\x61\x63\x63\x65ss_mode\x18\x01 \x01(\x0e\x32\x45.enterprise_management.DeviceNativePrintersAccessModeProto.AccessMode\"W\n\nAccessMode\x12\x19\n\x15\x41\x43\x43\x45SS_MODE_BLACKLIST\x10\x00\x12\x19\n\x15\x41\x43\x43\x45SS_MODE_WHITELIST\x10\x01\x12\x13\n\x0f\x41\x43\x43\x45SS_MODE_ALL\x10\x02\"7\n\"DeviceNativePrintersBlacklistProto\x12\x11\n\tblacklist\x18\x01 \x03(\t\"7\n\"DeviceNativePrintersWhitelistProto\x12\x11\n\twhitelist\x18\x01 \x03(\t\".\n\x13\x44\x65vicePrintersProto\x12\x17\n\x0f\x65xternal_policy\x18\x01 \x01(\t\"\xce\x01\n\x1d\x44\x65vicePrintersAccessModeProto\x12T\n\x0b\x61\x63\x63\x65ss_mode\x18\x01 \x01(\x0e\x32?.enterprise_management.DevicePrintersAccessModeProto.AccessMode\"W\n\nAccessMode\x12\x19\n\x15\x41\x43\x43\x45SS_MODE_BLOCKLIST\x10\x00\x12\x19\n\x15\x41\x43\x43\x45SS_MODE_ALLOWLIST\x10\x01\x12\x13\n\x0f\x41\x43\x43\x45SS_MODE_ALL\x10\x02\"1\n\x1c\x44\x65vicePrintersBlocklistProto\x12\x11\n\tblocklist\x18\x01 \x03(\t\"1\n\x1c\x44\x65vicePrintersAllowlistProto\x12\x11\n\tallowlist\x18\x01 \x03(\t\":\n\x1f\x44\x65viceExternalPrintServersProto\x12\x17\n\x0f\x65xternal_policy\x18\x01 \x01(\t\"=\n(DeviceExternalPrintServersAllowlistProto\x12\x11\n\tallowlist\x18\x01 \x03(\t\"\xe8\x02\n\x1eTPMFirmwareUpdateSettingsProto\x12&\n\x1e\x61llow_user_initiated_powerwash\x18\x01 \x01(\x08\x12\x32\n*allow_user_initiated_preserve_device_state\x18\x02 \x01(\x08\x12\x65\n\x10\x61uto_update_mode\x18\x03 \x01(\x0e\x32\x44.enterprise_management.TPMFirmwareUpdateSettingsProto.AutoUpdateMode:\x05NEVER\"\x82\x01\n\x0e\x41utoUpdateMode\x12 \n\x1c\x41UTO_UPDATE_MODE_UNSPECIFIED\x10\x00\x12\t\n\x05NEVER\x10\x01\x12\x17\n\x13USER_ACKNOWLEDGMENT\x10\x02\x12\x1a\n\x16WITHOUT_ACKNOWLEDGMENT\x10\x03\x12\x0e\n\nENROLLMENT\x10\x04\"K\n$OBSOLETE_MinimumRequiredVersionProto\x12#\n\x17OBSOLETE_chrome_version\x18\x01 \x01(\tB\x02\x18\x01\"c\n-DeviceLoginScreenAutoSelectCertificateForUrls\x12\x32\n*login_screen_auto_select_certificate_rules\x18\x01 \x03(\t\"?\n\x1bUnaffiliatedArcAllowedProto\x12 \n\x18unaffiliated_arc_allowed\x18\x01 \x01(\x08\"\xce\x01\n\"DeviceKerberosEncryptionTypesProto\x12`\n\x05types\x18\x01 \x01(\x0e\x32?.enterprise_management.DeviceKerberosEncryptionTypesProto.Types:\x10\x45NC_TYPES_STRONG\"F\n\x05Types\x12\x11\n\rENC_TYPES_ALL\x10\x00\x12\x14\n\x10\x45NC_TYPES_STRONG\x10\x01\x12\x14\n\x10\x45NC_TYPES_LEGACY\x10\x02\"\xde\x02\n\x1bKeyboardBacklightColorProto\x12g\n\x05\x63olor\x18\x01 \x01(\x0e\x32\x41.enterprise_management.KeyboardBacklightColorProto.BacklightColor:\x15\x42\x41\x43KLIGHT_UNSPECIFIED\"\xd5\x01\n\x0e\x42\x61\x63klightColor\x12\x19\n\x15\x42\x41\x43KLIGHT_UNSPECIFIED\x10\x00\x12\x13\n\x0f\x42\x41\x43KLIGHT_WHITE\x10\x01\x12\x11\n\rBACKLIGHT_RED\x10\x02\x12\x14\n\x10\x42\x41\x43KLIGHT_YELLOW\x10\x03\x12\x13\n\x0f\x42\x41\x43KLIGHT_GREEN\x10\x04\x12\x12\n\x0e\x42\x41\x43KLIGHT_BLUE\x10\x05\x12\x14\n\x10\x42\x41\x43KLIGHT_INDIGO\x10\x06\x12\x14\n\x10\x42\x41\x43KLIGHT_PURPLE\x10\x07\x12\x15\n\x11\x42\x41\x43KLIGHT_RAINBOW\x10\x64\"\xfe\x01\n+DeviceUserPolicyLoopbackProcessingModeProto\x12o\n\x04mode\x18\x01 \x01(\x0e\x32G.enterprise_management.DeviceUserPolicyLoopbackProcessingModeProto.Mode:\x18USER_POLICY_MODE_DEFAULT\"^\n\x04Mode\x12\x1c\n\x18USER_POLICY_MODE_DEFAULT\x10\x00\x12\x1a\n\x16USER_POLICY_MODE_MERGE\x10\x01\x12\x1c\n\x18USER_POLICY_MODE_REPLACE\x10\x02\"U\n-OBSOLETE_DeviceLoginScreenIsolateOriginsProto\x12$\n\x18OBSOLETE_isolate_origins\x18\x01 \x01(\tB\x02\x18\x01\"V\n-OBSOLETE_DeviceLoginScreenSitePerProcessProto\x12%\n\x19OBSOLETE_site_per_process\x18\x01 \x01(\x08\x42\x02\x18\x01\"?\n\x1bVirtualMachinesAllowedProto\x12 \n\x18virtual_machines_allowed\x18\x01 \x01(\x08\"9\n$DeviceMachinePasswordChangeRateProto\x12\x11\n\trate_days\x18\x01 \x01(\x05\"5\n\x1b\x44\x65viceGpoCacheLifetimeProto\x12\x16\n\x0elifetime_hours\x18\x01 \x01(\x05\":\n DeviceAuthDataCacheLifetimeProto\x12\x16\n\x0elifetime_hours\x18\x01 \x01(\x05\"V\n&DeviceUnaffiliatedCrostiniAllowedProto\x12,\n$device_unaffiliated_crostini_allowed\x18\x01 \x01(\x08\"1\n\x14PluginVmAllowedProto\x12\x19\n\x11plugin_vm_allowed\x18\x01 \x01(\x08\"8\n\x17PluginVmLicenseKeyProto\x12\x1d\n\x15plugin_vm_license_key\x18\x01 \x01(\t\"\x99\x02\n\x1e\x44\x65viceRebootOnUserSignoutProto\x12p\n\x16reboot_on_signout_mode\x18\x01 \x01(\x0e\x32I.enterprise_management.DeviceRebootOnUserSignoutProto.RebootOnSignoutMode:\x05NEVER\"\x84\x01\n\x13RebootOnSignoutMode\x12&\n\"REBOOT_ON_SIGNOUT_MODE_UNSPECIFIED\x10\x00\x12\t\n\x05NEVER\x10\x01\x12\x0f\n\x0b\x41RC_SESSION\x10\x02\x12\n\n\x06\x41LWAYS\x10\x03\x12\x1d\n\x19VM_STARTED_OR_ARC_SESSION\x10\x04\">\n\x1a\x44\x65viceWilcoDtcAllowedProto\x12 \n\x18\x64\x65vice_wilco_dtc_allowed\x18\x01 \x01(\x08\"J\n DeviceWilcoDtcConfigurationProto\x12&\n\x1e\x64\x65vice_wilco_dtc_configuration\x18\x01 \x01(\t\"\\\n\x19\x44\x65vicePowerPeakShiftProto\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x19\n\x11\x62\x61ttery_threshold\x18\x02 \x01(\x05\x12\x13\n\x0b\x64\x61y_configs\x18\x03 \x01(\t\"&\n\x13\x44\x65viceBootOnAcProto\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\"\xe5\x01\n\x1f\x44\x65viceDockMacAddressSourceProto\x12M\n\x06source\x18\x01 \x01(\x0e\x32=.enterprise_management.DeviceDockMacAddressSourceProto.Source\"s\n\x06Source\x12\x16\n\x12SOURCE_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x44\x45VICE_DOCK_MAC_ADDRESS\x10\x01\x12\x1a\n\x16\x44\x45VICE_NIC_MAC_ADDRESS\x10\x02\x12\x18\n\x14\x44OCK_NIC_MAC_ADDRESS\x10\x03\"L\n$DeviceAdvancedBatteryChargeModeProto\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12\x13\n\x0b\x64\x61y_configs\x18\x02 \x01(\t\"\xb8\x02\n\x1c\x44\x65viceBatteryChargeModeProto\x12\x62\n\x13\x62\x61ttery_charge_mode\x18\x01 \x01(\x0e\x32\x45.enterprise_management.DeviceBatteryChargeModeProto.BatteryChargeMode\x12\x1b\n\x13\x63ustom_charge_start\x18\x02 \x01(\x05\x12\x1a\n\x12\x63ustom_charge_stop\x18\x03 \x01(\x05\"{\n\x11\x42\x61tteryChargeMode\x12\x14\n\x10MODE_UNSPECIFIED\x10\x00\x12\x0c\n\x08STANDARD\x10\x01\x12\x12\n\x0e\x45XPRESS_CHARGE\x10\x02\x12\x14\n\x10PRIMARILY_AC_USE\x10\x03\x12\x0c\n\x08\x41\x44\x41PTIVE\x10\x04\x12\n\n\x06\x43USTOM\x10\x05\"+\n\x18\x44\x65viceUsbPowerShareProto\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\"Q\n\x1f\x44\x65viceScheduledUpdateCheckProto\x12.\n&device_scheduled_update_check_settings\x18\x01 \x01(\t\"?\n\x1b\x44\x65vicePowerwashAllowedProto\x12 \n\x18\x64\x65vice_powerwash_allowed\x18\x01 \x01(\x08\"l\n/DeviceLoginScreenWebUsbAllowDevicesForUrlsProto\x12\x39\n1device_login_screen_webusb_allow_devices_for_urls\x18\x01 \x01(\t\"9\n\x18SystemProxySettingsProto\x12\x1d\n\x15system_proxy_settings\x18\x01 \x01(\t\"Y\n\'RequiredClientCertificateForDeviceProto\x12.\n&required_client_certificate_for_device\x18\x01 \x01(\t\"\xf3\x01\n+DeviceCrostiniArcAdbSideloadingAllowedProto\x12h\n\x04mode\x18\x01 \x01(\x0e\x32P.enterprise_management.DeviceCrostiniArcAdbSideloadingAllowedProto.AllowanceMode:\x08\x44ISALLOW\"Z\n\rAllowanceMode\x12\x0c\n\x08\x44ISALLOW\x10\x00\x12\x1b\n\x17\x44ISALLOW_WITH_POWERWASH\x10\x01\x12\x1e\n\x1a\x41LLOW_FOR_AFFILIATED_USERS\x10\x02\"Z\n\'DeviceShowLowDiskSpaceNotificationProto\x12/\n\'device_show_low_disk_space_notification\x18\x01 \x01(\x08\"S\n$DeviceFamilyLinkAccountsAllowedProto\x12+\n\x1c\x66\x61mily_link_accounts_allowed\x18\x01 \x01(\x08:\x05\x66\x61lse\"B\n\x1f\x44\x65viceArcDataSnapshotHoursProto\x12\x1f\n\x17\x61rc_data_snapshot_hours\x18\x01 \x01(\t\"=\n#DeviceSystemWideTracingEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"C\n)DevicePciPeripheralDataAccessEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\">\n+DevicePciPeripheralDataAccessEnabledProtoV2\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\"<\n#OBSOLETE_DeviceBorealisAllowedProto\x12\x15\n\x07\x61llowed\x18\x01 \x01(\x08:\x04true\"8\n#DeviceAllowedBluetoothServicesProto\x12\x11\n\tallowlist\x18\x01 \x03(\t\"7\n$DeviceDebugPacketCaptureAllowedProto\x12\x0f\n\x07\x61llowed\x18\x01 \x01(\x08\"F\n\x1a\x44\x65viceScheduledRebootProto\x12(\n device_scheduled_reboot_settings\x18\x01 \x01(\t\"I\n/DeviceRestrictedManagedGuestSessionEnabledProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"8\n\x1f\x44\x65viceI18nShortcutsEnabledProto\x12\x15\n\x07\x65nabled\x18\x01 \x01(\x08:\x04true\"P\n\"RevenDeviceHWDataUsageEnabledProto\x12*\n\x1bhardware_data_usage_enabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"@\n&DeviceLoginScreenWebUILazyLoadingProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"E\n,EncryptedReportingPipelineConfigurationProto\x12\x15\n\x07\x65nabled\x18\x01 \x01(\x08:\x04true\"4\n\x1a\x44\x65viceReportXDREventsProto\x12\x16\n\x07\x65nabled\x18\x01 \x01(\x08:\x05\x66\x61lse\"\xcf\x62\n\x19\x43hromeDeviceSettingsProto\x12W\n\x1a\x64\x65vice_policy_refresh_rate\x18\x01 \x01(\x0b\x32\x33.enterprise_management.DevicePolicyRefreshRateProto\x12\x41\n\x0euser_whitelist\x18\x02 \x01(\x0b\x32).enterprise_management.UserWhitelistProto\x12H\n\x12guest_mode_enabled\x18\x03 \x01(\x0b\x32,.enterprise_management.GuestModeEnabledProto\x12[\n\x15\x64\x65vice_proxy_settings\x18\x04 \x01(\x0b\x32\x38.enterprise_management.OBSOLETE_DeviceProxySettingsProtoB\x02\x18\x01\x12\x41\n\x0e\x63\x61mera_enabled\x18\x05 \x01(\x0b\x32).enterprise_management.CameraEnabledProto\x12J\n\x0fshow_user_names\x18\x06 \x01(\x0b\x32\x31.enterprise_management.ShowUserNamesOnSigninProto\x12L\n\x14\x64\x61ta_roaming_enabled\x18\x07 \x01(\x0b\x32..enterprise_management.DataRoamingEnabledProto\x12\x42\n\x0f\x61llow_new_users\x18\x08 \x01(\x0b\x32).enterprise_management.AllowNewUsersProto\x12\x43\n\x0fmetrics_enabled\x18\t \x01(\x0b\x32*.enterprise_management.MetricsEnabledProto\x12\x43\n\x0frelease_channel\x18\n \x01(\x0b\x32*.enterprise_management.ReleaseChannelProto\x12^\n\x1aopen_network_configuration\x18\x0b \x01(\x0b\x32:.enterprise_management.DeviceOpenNetworkConfigurationProto\x12\x45\n\x10\x64\x65vice_reporting\x18\x0c \x01(\x0b\x32+.enterprise_management.DeviceReportingProto\x12R\n\x17\x65phemeral_users_enabled\x18\r \x01(\x0b\x32\x31.enterprise_management.EphemeralUsersEnabledProto\x12\x42\n\x08\x61pp_pack\x18\x0e \x01(\x0b\x32,.enterprise_management.OBSOLETE_AppPackProtoB\x02\x18\x01\x12]\n\x16\x66orced_logout_timeouts\x18\x0f \x01(\x0b\x32\x39.enterprise_management.OBSOLETE_ForcedLogoutTimeoutsProtoB\x02\x18\x01\x12P\n\x12login_screen_saver\x18\x10 \x01(\x0b\x32\x30.enterprise_management.OBSOLETE_ScreenSaverProtoB\x02\x18\x01\x12L\n\x14\x61uto_update_settings\x18\x11 \x01(\x0b\x32..enterprise_management.AutoUpdateSettingsProto\x12K\n\rstart_up_urls\x18\x12 \x01(\x0b\x32\x30.enterprise_management.OBSOLETE_StartUpUrlsProtoB\x02\x18\x01\x12H\n\x0bpinned_apps\x18\x13 \x01(\x0b\x32/.enterprise_management.OBSOLETE_PinnedAppsProtoB\x02\x18\x01\x12\x43\n\x0fsystem_timezone\x18\x14 \x01(\x0b\x32*.enterprise_management.SystemTimezoneProto\x12N\n\x15\x64\x65vice_local_accounts\x18\x15 \x01(\x0b\x32/.enterprise_management.DeviceLocalAccountsProto\x12^\n\x13\x61llow_redeem_offers\x18\x16 \x01(\x0b\x32\x41.enterprise_management.AllowRedeemChromeOsRegistrationOffersProto\x12?\n\rfeature_flags\x18\x17 \x01(\x0b\x32(.enterprise_management.FeatureFlagsProto\x12=\n\x0cuptime_limit\x18\x18 \x01(\x0b\x32\'.enterprise_management.UptimeLimitProto\x12M\n\x14variations_parameter\x18\x19 \x01(\x0b\x32/.enterprise_management.VariationsParameterProto\x12M\n\x14\x61ttestation_settings\x18\x1a \x01(\x0b\x32/.enterprise_management.AttestationSettingsProto\x12Q\n\x16\x61\x63\x63\x65ssibility_settings\x18\x1b \x01(\x0b\x32\x31.enterprise_management.AccessibilitySettingsProto\x12\x63\n\x19supervised_users_settings\x18\x1c \x01(\x0b\x32<.enterprise_management.OBSOLETE_SupervisedUsersSettingsProtoB\x02\x18\x01\x12]\n\x1dlogin_screen_power_management\x18\x1d \x01(\x0b\x32\x36.enterprise_management.LoginScreenPowerManagementProto\x12J\n\x10use_24hour_clock\x18\x1e \x01(\x0b\x32\x30.enterprise_management.SystemUse24HourClockProto\x12N\n\x16\x61uto_clean_up_settings\x18\x1f \x01(\x0b\x32..enterprise_management.AutoCleanupSettigsProto\x12\x43\n\x0fsystem_settings\x18 \x01(\x0b\x32*.enterprise_management.SystemSettingsProto\x12?\n\rsaml_settings\x18! \x01(\x0b\x32(.enterprise_management.SAMLSettingsProto\x12H\n\x12reboot_on_shutdown\x18\" \x01(\x0b\x32,.enterprise_management.RebootOnShutdownProto\x12V\n\x19\x64\x65vice_heartbeat_settings\x18# \x01(\x0b\x32\x33.enterprise_management.DeviceHeartbeatSettingsProto\x12L\n\x14\x65xtension_cache_size\x18$ \x01(\x0b\x32..enterprise_management.ExtensionCacheSizeProto\x12\x64\n!login_screen_domain_auto_complete\x18% \x01(\x0b\x32\x39.enterprise_management.LoginScreenDomainAutoCompleteProto\x12W\n\x1a\x64\x65vice_log_upload_settings\x18& \x01(\x0b\x32\x33.enterprise_management.DeviceLogUploadSettingsProto\x12T\n\x18\x64isplay_rotation_default\x18\' \x01(\x0b\x32\x32.enterprise_management.DisplayRotationDefaultProto\x12m\n&allow_kiosk_app_control_chrome_version\x18( \x01(\x0b\x32=.enterprise_management.AllowKioskAppControlChromeVersionProto\x12^\n\x1dlogin_authentication_behavior\x18) \x01(\x0b\x32\x37.enterprise_management.LoginAuthenticationBehaviorProto\x12T\n\x18usb_detachable_whitelist\x18* \x01(\x0b\x32\x32.enterprise_management.UsbDetachableWhitelistProto\x12\x43\n\x0f\x61llow_bluetooth\x18+ \x01(\x0b\x32*.enterprise_management.AllowBluetoothProto\x12X\n\x17quirks_download_enabled\x18, \x01(\x0b\x32\x37.enterprise_management.DeviceQuirksDownloadEnabledProto\x12\x62\n login_video_capture_allowed_urls\x18- \x01(\x0b\x32\x38.enterprise_management.LoginVideoCaptureAllowedUrlsProto\x12_\n\x1e\x64\x65vice_login_screen_extensions\x18. \x01(\x0b\x32\x37.enterprise_management.DeviceLoginScreenExtensionsProto\x12P\n\x12network_throttling\x18/ \x01(\x0b\x32\x34.enterprise_management.NetworkThrottlingEnabledProto\x12P\n\x16\x64\x65vice_wallpaper_image\x18\x30 \x01(\x0b\x32\x30.enterprise_management.DeviceWallpaperImageProto\x12L\n\x14login_screen_locales\x18\x31 \x01(\x0b\x32..enterprise_management.LoginScreenLocalesProto\x12W\n\x1alogin_screen_input_methods\x18\x32 \x01(\x0b\x32\x33.enterprise_management.LoginScreenInputMethodsProto\x12k\n\"device_ecryptfs_migration_strategy\x18\x33 \x01(\x0b\x32;.enterprise_management.DeviceEcryptfsMigrationStrategyProtoB\x02\x18\x01\x12i\n#device_second_factor_authentication\x18\x34 \x01(\x0b\x32<.enterprise_management.DeviceSecondFactorAuthenticationProto\x12H\n\x12\x63\x61st_receiver_name\x18\x35 \x01(\x0b\x32,.enterprise_management.CastReceiverNameProto\x12\x44\n\x10\x64\x65vice_off_hours\x18\x36 \x01(\x0b\x32*.enterprise_management.DeviceOffHoursProto\x12P\n\x16native_device_printers\x18\x37 \x01(\x0b\x32\x30.enterprise_management.DeviceNativePrintersProto\x12\x66\n\"native_device_printers_access_mode\x18\x38 \x01(\x0b\x32:.enterprise_management.DeviceNativePrintersAccessModeProto\x12\x63\n native_device_printers_blacklist\x18\x39 \x01(\x0b\x32\x39.enterprise_management.DeviceNativePrintersBlacklistProto\x12\x63\n native_device_printers_whitelist\x18: \x01(\x0b\x32\x39.enterprise_management.DeviceNativePrintersWhitelistProto\x12[\n\x1ctpm_firmware_update_settings\x18; \x01(\x0b\x32\x35.enterprise_management.TPMFirmwareUpdateSettingsProto\x12\x61\n\x18minimum_required_version\x18< \x01(\x0b\x32;.enterprise_management.OBSOLETE_MinimumRequiredVersionProtoB\x02\x18\x01\x12\x82\x01\n4device_login_screen_auto_select_certificate_for_urls\x18> \x01(\x0b\x32\x44.enterprise_management.DeviceLoginScreenAutoSelectCertificateForUrls\x12T\n\x18unaffiliated_arc_allowed\x18? \x01(\x0b\x32\x32.enterprise_management.UnaffiliatedArcAllowedProto\x12\x45\n\x10network_hostname\x18@ \x01(\x0b\x32+.enterprise_management.NetworkHostnameProto\x12\x63\n device_kerberos_encryption_types\x18\x41 \x01(\x0b\x32\x39.enterprise_management.DeviceKerberosEncryptionTypesProto\x12w\n+device_user_policy_loopback_processing_mode\x18\x42 \x01(\x0b\x32\x42.enterprise_management.DeviceUserPolicyLoopbackProcessingModeProto\x12u\n#device_login_screen_isolate_origins\x18\x43 \x01(\x0b\x32\x44.enterprise_management.OBSOLETE_DeviceLoginScreenIsolateOriginsProtoB\x02\x18\x01\x12v\n$device_login_screen_site_per_process\x18\x44 \x01(\x0b\x32\x44.enterprise_management.OBSOLETE_DeviceLoginScreenSitePerProcessProtoB\x02\x18\x01\x12T\n\x18virtual_machines_allowed\x18\x45 \x01(\x0b\x32\x32.enterprise_management.VirtualMachinesAllowedProto\x12h\n#device_machine_password_change_rate\x18\x46 \x01(\x0b\x32;.enterprise_management.DeviceMachinePasswordChangeRateProto\x12k\n$device_unaffiliated_crostini_allowed\x18H \x01(\x0b\x32=.enterprise_management.DeviceUnaffiliatedCrostiniAllowedProto\x12h\n#device_wifi_fast_transition_enabled\x18I \x01(\x0b\x32;.enterprise_management.DeviceWiFiFastTransitionEnabledProto\x12V\n\x19\x64\x65vice_display_resolution\x18J \x01(\x0b\x32\x33.enterprise_management.DeviceDisplayResolutionProto\x12\x46\n\x11plugin_vm_allowed\x18K \x01(\x0b\x32+.enterprise_management.PluginVmAllowedProto\x12U\n\x19\x64\x65vice_gpo_cache_lifetime\x18L \x01(\x0b\x32\x32.enterprise_management.DeviceGpoCacheLifetimeProto\x12`\n\x1f\x64\x65vice_auth_data_cache_lifetime\x18M \x01(\x0b\x32\x37.enterprise_management.DeviceAuthDataCacheLifetimeProto\x12M\n\x15plugin_vm_license_key\x18N \x01(\x0b\x32..enterprise_management.PluginVmLicenseKeyProto\x12\\\n\x1d\x64\x65vice_reboot_on_user_signout\x18O \x01(\x0b\x32\x35.enterprise_management.DeviceRebootOnUserSignoutProto\x12S\n\x18\x64\x65vice_wilco_dtc_allowed\x18P \x01(\x0b\x32\x31.enterprise_management.DeviceWilcoDtcAllowedProto\x12_\n\x1e\x64\x65vice_wilco_dtc_configuration\x18Q \x01(\x0b\x32\x37.enterprise_management.DeviceWilcoDtcConfigurationProto\x12J\n\x13\x64\x65vice_wifi_allowed\x18R \x01(\x0b\x32-.enterprise_management.DeviceWiFiAllowedProto\x12Q\n\x17\x64\x65vice_power_peak_shift\x18S \x01(\x0b\x32\x30.enterprise_management.DevicePowerPeakShiftProto\x12\x45\n\x11\x64\x65vice_boot_on_ac\x18T \x01(\x0b\x32*.enterprise_management.DeviceBootOnAcProto\x12^\n\x1e\x64\x65vice_dock_mac_address_source\x18U \x01(\x0b\x32\x36.enterprise_management.DeviceDockMacAddressSourceProto\x12h\n#device_advanced_battery_charge_mode\x18V \x01(\x0b\x32;.enterprise_management.DeviceAdvancedBatteryChargeModeProto\x12W\n\x1a\x64\x65vice_battery_charge_mode\x18W \x01(\x0b\x32\x33.enterprise_management.DeviceBatteryChargeModeProto\x12O\n\x16\x64\x65vice_usb_power_share\x18X \x01(\x0b\x32/.enterprise_management.DeviceUsbPowerShareProto\x12]\n\x1d\x64\x65vice_scheduled_update_check\x18Y \x01(\x0b\x32\x36.enterprise_management.DeviceScheduledUpdateCheckProto\x12T\n\x18\x64\x65vice_powerwash_allowed\x18[ \x01(\x0b\x32\x32.enterprise_management.DevicePowerwashAllowedProto\x12\x81\x01\n1device_login_screen_webusb_allow_devices_for_urls\x18\\ \x01(\x0b\x32\x46.enterprise_management.DeviceLoginScreenWebUsbAllowDevicesForUrlsProto\x12[\n(device_login_screen_system_info_enforced\x18] \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12_\n)device_web_based_attestation_allowed_urls\x18^ \x01(\x0b\x32,.enterprise_management.StringListPolicyProto\x12\\\n)device_show_numeric_keyboard_for_password\x18_ \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12[\n(login_screen_primary_mouse_button_switch\x18` \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12H\n\x16\x64\x65vice_minimum_version\x18\x61 \x01(\x0b\x32(.enterprise_management.StringPolicyProto\x12N\n\x15system_proxy_settings\x18\x62 \x01(\x0b\x32/.enterprise_management.SystemProxySettingsProto\x12P\n\x1d\x64\x65vice_chrome_variations_type\x18\x63 \x01(\x0b\x32).enterprise_management.IntegerPolicyProto\x12u\n*device_login_screen_privacy_screen_enabled\x18\x64 \x01(\x0b\x32\x41.enterprise_management.DeviceLoginScreenPrivacyScreenEnabledProto\x12n\n&required_client_certificate_for_device\x18\x65 \x01(\x0b\x32>.enterprise_management.RequiredClientCertificateForDeviceProto\x12w\n+device_crostini_arc_adb_sideloading_allowed\x18\x66 \x01(\x0b\x32\x42.enterprise_management.DeviceCrostiniArcAdbSideloadingAllowedProto\x12T\n\"device_minimum_version_aue_message\x18g \x01(\x0b\x32(.enterprise_management.StringPolicyProto\x12n\n&managed_guest_session_privacy_warnings\x18h \x01(\x0b\x32>.enterprise_management.ManagedGuestSessionPrivacyWarningsProto\x12V\n\x16\x65xternal_print_servers\x18i \x01(\x0b\x32\x36.enterprise_management.DeviceExternalPrintServersProto\x12i\n external_print_servers_allowlist\x18j \x01(\x0b\x32?.enterprise_management.DeviceExternalPrintServersAllowlistProto\x12Y\n\x1b\x64\x65vice_printers_access_mode\x18k \x01(\x0b\x32\x34.enterprise_management.DevicePrintersAccessModeProto\x12V\n\x19\x64\x65vice_printers_blocklist\x18l \x01(\x0b\x32\x33.enterprise_management.DevicePrintersBlocklistProto\x12V\n\x19\x64\x65vice_printers_allowlist\x18m \x01(\x0b\x32\x33.enterprise_management.DevicePrintersAllowlistProto\x12\x43\n\x0f\x64\x65vice_printers\x18n \x01(\x0b\x32*.enterprise_management.DevicePrintersProto\x12o\n\'device_show_low_disk_space_notification\x18o \x01(\x0b\x32>.enterprise_management.DeviceShowLowDiskSpaceNotificationProto\x12\x41\n\x0euser_allowlist\x18p \x01(\x0b\x32).enterprise_management.UserAllowlistProto\x12T\n\x18usb_detachable_allowlist\x18q \x01(\x0b\x32\x32.enterprise_management.UsbDetachableAllowlistProto\x12\x61\n\x1c\x66\x61mily_link_accounts_allowed\x18r \x01(\x0b\x32;.enterprise_management.DeviceFamilyLinkAccountsAllowedProto\x12W\n\x17\x61rc_data_snapshot_hours\x18s \x01(\x0b\x32\x36.enterprise_management.DeviceArcDataSnapshotHoursProto\x12_\n,device_allow_mgs_to_store_display_properties\x18t \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12\x66\n\"device_system_wide_tracing_enabled\x18u \x01(\x0b\x32:.enterprise_management.DeviceSystemWideTracingEnabledProto\x12s\n)device_pci_peripheral_data_access_enabled\x18v \x01(\x0b\x32@.enterprise_management.DevicePciPeripheralDataAccessEnabledProto\x12_\n\x17\x64\x65vice_borealis_allowed\x18w \x01(\x0b\x32:.enterprise_management.OBSOLETE_DeviceBorealisAllowedProtoB\x02\x18\x01\x12\x65\n!device_allowed_bluetooth_services\x18x \x01(\x0b\x32:.enterprise_management.DeviceAllowedBluetoothServicesProto\x12h\n#device_debug_packet_capture_allowed\x18y \x01(\x0b\x32;.enterprise_management.DeviceDebugPacketCaptureAllowedProto\x12R\n\x17\x64\x65vice_scheduled_reboot\x18z \x01(\x0b\x32\x31.enterprise_management.DeviceScheduledRebootProto\x12x\n,device_pci_peripheral_data_access_enabled_v2\x18{ \x01(\x0b\x32\x42.enterprise_management.DevicePciPeripheralDataAccessEnabledProtoV2\x12\x7f\n/device_restricted_managed_guest_session_enabled\x18| \x01(\x0b\x32\x46.enterprise_management.DeviceRestrictedManagedGuestSessionEnabledProto\x12X\n\x1ahostname_user_configurable\x18} \x01(\x0b\x32\x34.enterprise_management.HostnameUserConfigurableProto\x12h\n5login_screen_prompt_on_multiple_matching_certificates\x18~ \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12X\n%kiosk_crx_manifest_update_url_ignored\x18\x7f \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12^\n\x1d\x64\x65vice_i18n_shortcuts_enabled\x18\x80\x01 \x01(\x0b\x32\x36.enterprise_management.DeviceI18nShortcutsEnabledProto\x12V\n\"chromad_to_cloud_migration_enabled\x18\x81\x01 \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12_\n\x1bhardware_data_usage_enabled\x18\x82\x01 \x01(\x0b\x32\x39.enterprise_management.RevenDeviceHWDataUsageEnabledProto\x12\x61\n\x19login_web_ui_lazy_loading\x18\x83\x01 \x01(\x0b\x32=.enterprise_management.DeviceLoginScreenWebUILazyLoadingProto\x12y\n(keylocker_for_storage_encryption_enabled\x18\x84\x01 \x01(\x0b\x32\x46.enterprise_management.DeviceKeylockerForStorageEncryptionEnabledProto\x12Y\n%device_run_automatic_cleanup_on_login\x18\x85\x01 \x01(\x0b\x32).enterprise_management.BooleanPolicyProto\x12y\n+device_encrypted_reporting_pipeline_enabled\x18\x86\x01 \x01(\x0b\x32\x43.enterprise_management.EncryptedReportingPipelineConfigurationProto\x12@\n\rsaml_username\x18\x87\x01 \x01(\x0b\x32(.enterprise_management.SAMLUsernameProto\x12q\n:device_login_screen_context_aware_access_signals_allowlist\x18\x88\x01 \x01(\x0b\x32,.enterprise_management.StringListPolicyProto\x12W\n$device_printing_client_name_template\x18\x89\x01 \x01(\x0b\x32(.enterprise_management.StringPolicyProto\x12T\n\x18\x64\x65vice_report_xdr_events\x18\x8a\x01 \x01(\x0b\x32\x31.enterprise_management.DeviceReportXDREventsProto\x12U\n\x18keyboard_backlight_color\x18\x8b\x01 \x01(\x0b\x32\x32.enterprise_management.KeyboardBacklightColorProto\x12k\n$device_hindi_inscript_layout_enabled\x18\x8c\x01 \x01(\x0b\x32<.enterprise_management.DeviceHindiInscriptLayoutEnabledProto\x12\x80\x01\n/login_screen_extension_manifest_v2_availability\x18\x8d\x01 \x01(\x0b\x32\x46.enterprise_management.LoginScreenExtensionManifestV2AvailabilityProtoJ\x04\x08=\x10>J\x04\x08G\x10HJ\x04\x08Z\x10[B/H\x03Z+chromium/policy/enterprise_management_proto') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chrome_device_policy_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'H\003Z+chromium/policy/enterprise_management_proto' + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_mode']._options = None + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_mode']._serialized_options = b'\030\001' + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_server']._options = None + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_server']._serialized_options = b'\030\001' + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_pac_url']._options = None + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_pac_url']._serialized_options = b'\030\001' + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_bypass_list']._options = None + _OBSOLETE_DEVICEPROXYSETTINGSPROTO.fields_by_name['OBSOLETE_proxy_bypass_list']._serialized_options = b'\030\001' + _DEVICEREPORTINGPROTO.fields_by_name['report_network_interfaces']._options = None + _DEVICEREPORTINGPROTO.fields_by_name['report_network_interfaces']._serialized_options = b'\030\001' + _DEVICEREPORTINGPROTO.fields_by_name['report_hardware_status']._options = None + _DEVICEREPORTINGPROTO.fields_by_name['report_hardware_status']._serialized_options = b'\030\001' + _DEVICEREPORTINGPROTO.fields_by_name['enable_granular_reporting']._options = None + _DEVICEREPORTINGPROTO.fields_by_name['enable_granular_reporting']._serialized_options = b'\030\001' + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_extension_id']._options = None + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_extension_id']._serialized_options = b'\030\001' + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_update_url']._options = None + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_update_url']._serialized_options = b'\030\001' + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_online_only']._options = None + _OBSOLETE_APPPACKENTRYPROTO.fields_by_name['OBSOLETE_online_only']._serialized_options = b'\030\001' + _OBSOLETE_APPPACKPROTO.fields_by_name['app_pack']._options = None + _OBSOLETE_APPPACKPROTO.fields_by_name['app_pack']._serialized_options = b'\030\001' + _OBSOLETE_PINNEDAPPSPROTO.fields_by_name['OBSOLETE_app_id']._options = None + _OBSOLETE_PINNEDAPPSPROTO.fields_by_name['OBSOLETE_app_id']._serialized_options = b'\030\001' + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO.fields_by_name['OBSOLETE_idle_logout_timeout']._options = None + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO.fields_by_name['OBSOLETE_idle_logout_timeout']._serialized_options = b'\030\001' + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO.fields_by_name['OBSOLETE_idle_logout_warning_duration']._options = None + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO.fields_by_name['OBSOLETE_idle_logout_warning_duration']._serialized_options = b'\030\001' + _OBSOLETE_SCREENSAVERPROTO.fields_by_name['OBSOLETE_screen_saver_extension_id']._options = None + _OBSOLETE_SCREENSAVERPROTO.fields_by_name['OBSOLETE_screen_saver_extension_id']._serialized_options = b'\030\001' + _OBSOLETE_SCREENSAVERPROTO.fields_by_name['OBSOLETE_screen_saver_timeout']._options = None + _OBSOLETE_SCREENSAVERPROTO.fields_by_name['OBSOLETE_screen_saver_timeout']._serialized_options = b'\030\001' + _AUTOUPDATESETTINGSPROTO.fields_by_name['OBSOLETE_reboot_after_update']._options = None + _AUTOUPDATESETTINGSPROTO.fields_by_name['OBSOLETE_reboot_after_update']._serialized_options = b'\030\001' + _OBSOLETE_STARTUPURLSPROTO.fields_by_name['OBSOLETE_start_up_urls']._options = None + _OBSOLETE_STARTUPURLSPROTO.fields_by_name['OBSOLETE_start_up_urls']._serialized_options = b'\030\001' + _FEATUREFLAGSPROTO.fields_by_name['switches']._options = None + _FEATUREFLAGSPROTO.fields_by_name['switches']._serialized_options = b'\030\001' + _UPTIMELIMITPROTO.fields_by_name['OBSOLETE_uptime_limit']._options = None + _UPTIMELIMITPROTO.fields_by_name['OBSOLETE_uptime_limit']._serialized_options = b'\030\001' + _OBSOLETE_SUPERVISEDUSERSSETTINGSPROTO.fields_by_name['OBSOLETE_supervised_users_enabled']._options = None + _OBSOLETE_SUPERVISEDUSERSSETTINGSPROTO.fields_by_name['OBSOLETE_supervised_users_enabled']._serialized_options = b'\030\001' + _SAMLSETTINGSPROTO.fields_by_name['OBSOLETE_url_parameter_to_autofill_saml_username']._options = None + _SAMLSETTINGSPROTO.fields_by_name['OBSOLETE_url_parameter_to_autofill_saml_username']._serialized_options = b'\030\001' + _OBSOLETE_MINIMUMREQUIREDVERSIONPROTO.fields_by_name['OBSOLETE_chrome_version']._options = None + _OBSOLETE_MINIMUMREQUIREDVERSIONPROTO.fields_by_name['OBSOLETE_chrome_version']._serialized_options = b'\030\001' + _OBSOLETE_DEVICELOGINSCREENISOLATEORIGINSPROTO.fields_by_name['OBSOLETE_isolate_origins']._options = None + _OBSOLETE_DEVICELOGINSCREENISOLATEORIGINSPROTO.fields_by_name['OBSOLETE_isolate_origins']._serialized_options = b'\030\001' + _OBSOLETE_DEVICELOGINSCREENSITEPERPROCESSPROTO.fields_by_name['OBSOLETE_site_per_process']._options = None + _OBSOLETE_DEVICELOGINSCREENSITEPERPROCESSPROTO.fields_by_name['OBSOLETE_site_per_process']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_proxy_settings']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_proxy_settings']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['app_pack']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['app_pack']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['forced_logout_timeouts']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['forced_logout_timeouts']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['login_screen_saver']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['login_screen_saver']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['start_up_urls']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['start_up_urls']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['pinned_apps']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['pinned_apps']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['supervised_users_settings']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['supervised_users_settings']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_ecryptfs_migration_strategy']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_ecryptfs_migration_strategy']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['minimum_required_version']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['minimum_required_version']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_login_screen_isolate_origins']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_login_screen_isolate_origins']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_login_screen_site_per_process']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_login_screen_site_per_process']._serialized_options = b'\030\001' + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_borealis_allowed']._options = None + _CHROMEDEVICESETTINGSPROTO.fields_by_name['device_borealis_allowed']._serialized_options = b'\030\001' + _DEVICEPOLICYREFRESHRATEPROTO._serialized_start=86 + _DEVICEPOLICYREFRESHRATEPROTO._serialized_end=152 + _USERWHITELISTPROTO._serialized_start=154 + _USERWHITELISTPROTO._serialized_end=198 + _USERALLOWLISTPROTO._serialized_start=200 + _USERALLOWLISTPROTO._serialized_end=244 + _ALLOWNEWUSERSPROTO._serialized_start=246 + _ALLOWNEWUSERSPROTO._serialized_end=297 + _GUESTMODEENABLEDPROTO._serialized_start=299 + _GUESTMODEENABLEDPROTO._serialized_end=356 + _SHOWUSERNAMESONSIGNINPROTO._serialized_start=358 + _SHOWUSERNAMESONSIGNINPROTO._serialized_end=417 + _DATAROAMINGENABLEDPROTO._serialized_start=419 + _DATAROAMINGENABLEDPROTO._serialized_end=481 + _OBSOLETE_DEVICEPROXYSETTINGSPROTO._serialized_start=484 + _OBSOLETE_DEVICEPROXYSETTINGSPROTO._serialized_end=663 + _CAMERAENABLEDPROTO._serialized_start=665 + _CAMERAENABLEDPROTO._serialized_end=709 + _METRICSENABLEDPROTO._serialized_start=711 + _METRICSENABLEDPROTO._serialized_end=757 + _RELEASECHANNELPROTO._serialized_start=759 + _RELEASECHANNELPROTO._serialized_end=865 + _DEVICEOPENNETWORKCONFIGURATIONPROTO._serialized_start=867 + _DEVICEOPENNETWORKCONFIGURATIONPROTO._serialized_end=940 + _NETWORKHOSTNAMEPROTO._serialized_start=942 + _NETWORKHOSTNAMEPROTO._serialized_end=998 + _DEVICEHINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_start=1000 + _DEVICEHINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_end=1063 + _HOSTNAMEUSERCONFIGURABLEPROTO._serialized_start=1065 + _HOSTNAMEUSERCONFIGURABLEPROTO._serialized_end=1146 + _DEVICEREPORTINGPROTO._serialized_start=1149 + _DEVICEREPORTINGPROTO._serialized_end=2703 + _EPHEMERALUSERSENABLEDPROTO._serialized_start=2705 + _EPHEMERALUSERSENABLEDPROTO._serialized_end=2766 + _DEVICEKEYLOCKERFORSTORAGEENCRYPTIONENABLEDPROTO._serialized_start=2768 + _DEVICEKEYLOCKERFORSTORAGEENCRYPTIONENABLEDPROTO._serialized_end=2834 + _OBSOLETE_APPPACKENTRYPROTO._serialized_start=2837 + _OBSOLETE_APPPACKENTRYPROTO._serialized_end=2967 + _OBSOLETE_APPPACKPROTO._serialized_start=2969 + _OBSOLETE_APPPACKPROTO._serialized_end=3065 + _OBSOLETE_PINNEDAPPSPROTO._serialized_start=3067 + _OBSOLETE_PINNEDAPPSPROTO._serialized_end=3122 + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO._serialized_start=3125 + _OBSOLETE_FORCEDLOGOUTTIMEOUTSPROTO._serialized_end=3254 + _OBSOLETE_SCREENSAVERPROTO._serialized_start=3256 + _OBSOLETE_SCREENSAVERPROTO._serialized_end=3374 + _AUTOUPDATESETTINGSPROTO._serialized_start=3377 + _AUTOUPDATESETTINGSPROTO._serialized_end=4660 + _AUTOUPDATESETTINGSPROTO_CONNECTIONTYPE._serialized_start=4204 + _AUTOUPDATESETTINGSPROTO_CONNECTIONTYPE._serialized_end=4364 + _AUTOUPDATESETTINGSPROTO_ROLLBACKTOTARGETVERSION._serialized_start=4367 + _AUTOUPDATESETTINGSPROTO_ROLLBACKTOTARGETVERSION._serialized_end=4507 + _AUTOUPDATESETTINGSPROTO_CHANNELDOWNGRADEBEHAVIOR._serialized_start=4510 + _AUTOUPDATESETTINGSPROTO_CHANNELDOWNGRADEBEHAVIOR._serialized_end=4654 + _OBSOLETE_STARTUPURLSPROTO._serialized_start=4662 + _OBSOLETE_STARTUPURLSPROTO._serialized_end=4725 + _SYSTEMTIMEZONEPROTO._serialized_start=4728 + _SYSTEMTIMEZONEPROTO._serialized_end=5012 + _SYSTEMTIMEZONEPROTO_AUTOMATICTIMEZONEDETECTIONTYPE._serialized_start=4878 + _SYSTEMTIMEZONEPROTO_AUTOMATICTIMEZONEDETECTIONTYPE._serialized_end=5012 + _SYSTEMUSE24HOURCLOCKPROTO._serialized_start=5014 + _SYSTEMUSE24HOURCLOCKPROTO._serialized_end=5067 + _KIOSKAPPINFOPROTO._serialized_start=5069 + _KIOSKAPPINFOPROTO._serialized_end=5124 + _ANDROIDKIOSKAPPINFOPROTO._serialized_start=5126 + _ANDROIDKIOSKAPPINFOPROTO._serialized_end=5232 + _WEBKIOSKAPPINFOPROTO._serialized_start=5234 + _WEBKIOSKAPPINFOPROTO._serialized_end=5302 + _DEVICELOCALACCOUNTINFOPROTO._serialized_start=5305 + _DEVICELOCALACCOUNTINFOPROTO._serialized_end=5858 + _DEVICELOCALACCOUNTINFOPROTO_ACCOUNTTYPE._serialized_start=5678 + _DEVICELOCALACCOUNTINFOPROTO_ACCOUNTTYPE._serialized_end=5858 + _DEVICELOCALACCOUNTSPROTO._serialized_start=5861 + _DEVICELOCALACCOUNTSPROTO._serialized_end=6093 + _MANAGEDGUESTSESSIONPRIVACYWARNINGSPROTO._serialized_start=6095 + _MANAGEDGUESTSESSIONPRIVACYWARNINGSPROTO._serialized_end=6159 + _ALLOWREDEEMCHROMEOSREGISTRATIONOFFERSPROTO._serialized_start=6161 + _ALLOWREDEEMCHROMEOSREGISTRATIONOFFERSPROTO._serialized_end=6240 + _FEATUREFLAGSPROTO._serialized_start=6242 + _FEATUREFLAGSPROTO._serialized_end=6306 + _UPTIMELIMITPROTO._serialized_start=6308 + _UPTIMELIMITPROTO._serialized_end=6383 + _VARIATIONSPARAMETERPROTO._serialized_start=6385 + _VARIATIONSPARAMETERPROTO._serialized_end=6430 + _ATTESTATIONSETTINGSPROTO._serialized_start=6432 + _ATTESTATIONSETTINGSPROTO._serialized_end=6536 + _ACCESSIBILITYSETTINGSPROTO._serialized_start=6539 + _ACCESSIBILITYSETTINGSPROTO._serialized_end=9047 + _ACCESSIBILITYSETTINGSPROTO_SCREENMAGNIFIERTYPE._serialized_start=8962 + _ACCESSIBILITYSETTINGSPROTO_SCREENMAGNIFIERTYPE._serialized_end=9047 + _OBSOLETE_SUPERVISEDUSERSSETTINGSPROTO._serialized_start=9049 + _OBSOLETE_SUPERVISEDUSERSSETTINGSPROTO._serialized_end=9135 + _LOGINSCREENPOWERMANAGEMENTPROTO._serialized_start=9137 + _LOGINSCREENPOWERMANAGEMENTPROTO._serialized_end=9209 + _AUTOCLEANUPSETTIGSPROTO._serialized_start=9211 + _AUTOCLEANUPSETTIGSPROTO._serialized_end=9263 + _SYSTEMSETTINGSPROTO._serialized_start=9265 + _SYSTEMSETTINGSPROTO._serialized_end=9309 + _SAMLSETTINGSPROTO._serialized_start=9311 + _SAMLSETTINGSPROTO._serialized_end=9423 + _SAMLUSERNAMEPROTO._serialized_start=9425 + _SAMLUSERNAMEPROTO._serialized_end=9493 + _REBOOTONSHUTDOWNPROTO._serialized_start=9495 + _REBOOTONSHUTDOWNPROTO._serialized_end=9553 + _DEVICEHEARTBEATSETTINGSPROTO._serialized_start=9555 + _DEVICEHEARTBEATSETTINGSPROTO._serialized_end=9656 + _EXTENSIONCACHESIZEPROTO._serialized_start=9658 + _EXTENSIONCACHESIZEPROTO._serialized_end=9713 + _LOGINSCREENDOMAINAUTOCOMPLETEPROTO._serialized_start=9715 + _LOGINSCREENDOMAINAUTOCOMPLETEPROTO._serialized_end=9794 + _DEVICELOGUPLOADSETTINGSPROTO._serialized_start=9796 + _DEVICELOGUPLOADSETTINGSPROTO._serialized_end=9868 + _DISPLAYROTATIONDEFAULTPROTO._serialized_start=9871 + _DISPLAYROTATIONDEFAULTPROTO._serialized_end=10068 + _DISPLAYROTATIONDEFAULTPROTO_ROTATION._serialized_start=9997 + _DISPLAYROTATIONDEFAULTPROTO_ROTATION._serialized_end=10068 + _DEVICELOGINSCREENPRIVACYSCREENENABLEDPROTO._serialized_start=10070 + _DEVICELOGINSCREENPRIVACYSCREENENABLEDPROTO._serialized_end=10138 + _DEVICEDISPLAYRESOLUTIONPROTO._serialized_start=10140 + _DEVICEDISPLAYRESOLUTIONPROTO._serialized_end=10205 + _ALLOWKIOSKAPPCONTROLCHROMEVERSIONPROTO._serialized_start=10207 + _ALLOWKIOSKAPPCONTROLCHROMEVERSIONPROTO._serialized_end=10302 + _LOGINAUTHENTICATIONBEHAVIORPROTO._serialized_start=10305 + _LOGINAUTHENTICATIONBEHAVIORPROTO._serialized_end=10505 + _LOGINAUTHENTICATIONBEHAVIORPROTO_LOGINBEHAVIOR._serialized_start=10457 + _LOGINAUTHENTICATIONBEHAVIORPROTO_LOGINBEHAVIOR._serialized_end=10505 + _USBDEVICEIDPROTO._serialized_start=10507 + _USBDEVICEIDPROTO._serialized_end=10564 + _USBDETACHABLEWHITELISTPROTO._serialized_start=10566 + _USBDETACHABLEWHITELISTPROTO._serialized_end=10648 + _USBDEVICEIDINCLUSIVEPROTO._serialized_start=10650 + _USBDEVICEIDINCLUSIVEPROTO._serialized_end=10716 + _USBDETACHABLEALLOWLISTPROTO._serialized_start=10718 + _USBDETACHABLEALLOWLISTPROTO._serialized_end=10809 + _ALLOWBLUETOOTHPROTO._serialized_start=10811 + _ALLOWBLUETOOTHPROTO._serialized_end=10863 + _DEVICEWIFIALLOWEDPROTO._serialized_start=10865 + _DEVICEWIFIALLOWEDPROTO._serialized_end=10924 + _DEVICEQUIRKSDOWNLOADENABLEDPROTO._serialized_start=10926 + _DEVICEQUIRKSDOWNLOADENABLEDPROTO._serialized_end=10993 + _LOGINVIDEOCAPTUREALLOWEDURLSPROTO._serialized_start=10995 + _LOGINVIDEOCAPTUREALLOWEDURLSPROTO._serialized_end=11044 + _DEVICEWIFIFASTTRANSITIONENABLEDPROTO._serialized_start=11046 + _DEVICEWIFIFASTTRANSITIONENABLEDPROTO._serialized_end=11129 + _NETWORKTHROTTLINGENABLEDPROTO._serialized_start=11131 + _NETWORKTHROTTLINGENABLEDPROTO._serialized_end=11248 + _DEVICELOGINSCREENEXTENSIONSPROTO._serialized_start=11250 + _DEVICELOGINSCREENEXTENSIONSPROTO._serialized_end=11324 + _LOGINSCREENEXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_start=11327 + _LOGINSCREENEXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_end=11607 + _LOGINSCREENEXTENSIONMANIFESTV2AVAILABILITYPROTO_AVAILABILITY._serialized_start=11521 + _LOGINSCREENEXTENSIONMANIFESTV2AVAILABILITYPROTO_AVAILABILITY._serialized_end=11607 + _LOGINSCREENLOCALESPROTO._serialized_start=11609 + _LOGINSCREENLOCALESPROTO._serialized_end=11664 + _LOGINSCREENINPUTMETHODSPROTO._serialized_start=11666 + _LOGINSCREENINPUTMETHODSPROTO._serialized_end=11732 + _DEVICEWALLPAPERIMAGEPROTO._serialized_start=11734 + _DEVICEWALLPAPERIMAGEPROTO._serialized_end=11793 + _DEVICEECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_start=11796 + _DEVICEECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_end=12012 + _DEVICEECRYPTFSMIGRATIONSTRATEGYPROTO_MIGRATIONSTRATEGY._serialized_start=11943 + _DEVICEECRYPTFSMIGRATIONSTRATEGYPROTO_MIGRATIONSTRATEGY._serialized_end=12012 + _DEVICESECONDFACTORAUTHENTICATIONPROTO._serialized_start=12015 + _DEVICESECONDFACTORAUTHENTICATIONPROTO._serialized_end=12201 + _DEVICESECONDFACTORAUTHENTICATIONPROTO_U2FMODE._serialized_start=12140 + _DEVICESECONDFACTORAUTHENTICATIONPROTO_U2FMODE._serialized_end=12201 + _CASTRECEIVERNAMEPROTO._serialized_start=12203 + _CASTRECEIVERNAMEPROTO._serialized_end=12240 + _WEEKLYTIMEPROTO._serialized_start=12243 + _WEEKLYTIMEPROTO._serialized_end=12480 + _WEEKLYTIMEPROTO_DAYOFWEEK._serialized_start=12348 + _WEEKLYTIMEPROTO_DAYOFWEEK._serialized_end=12480 + _WEEKLYTIMEINTERVALPROTO._serialized_start=12483 + _WEEKLYTIMEINTERVALPROTO._serialized_end=12616 + _DEVICEOFFHOURSPROTO._serialized_start=12619 + _DEVICEOFFHOURSPROTO._serialized_end=12760 + _DEVICENATIVEPRINTERSPROTO._serialized_start=12762 + _DEVICENATIVEPRINTERSPROTO._serialized_end=12814 + _DEVICENATIVEPRINTERSACCESSMODEPROTO._serialized_start=12817 + _DEVICENATIVEPRINTERSACCESSMODEPROTO._serialized_end=13035 + _DEVICENATIVEPRINTERSACCESSMODEPROTO_ACCESSMODE._serialized_start=12948 + _DEVICENATIVEPRINTERSACCESSMODEPROTO_ACCESSMODE._serialized_end=13035 + _DEVICENATIVEPRINTERSBLACKLISTPROTO._serialized_start=13037 + _DEVICENATIVEPRINTERSBLACKLISTPROTO._serialized_end=13092 + _DEVICENATIVEPRINTERSWHITELISTPROTO._serialized_start=13094 + _DEVICENATIVEPRINTERSWHITELISTPROTO._serialized_end=13149 + _DEVICEPRINTERSPROTO._serialized_start=13151 + _DEVICEPRINTERSPROTO._serialized_end=13197 + _DEVICEPRINTERSACCESSMODEPROTO._serialized_start=13200 + _DEVICEPRINTERSACCESSMODEPROTO._serialized_end=13406 + _DEVICEPRINTERSACCESSMODEPROTO_ACCESSMODE._serialized_start=13319 + _DEVICEPRINTERSACCESSMODEPROTO_ACCESSMODE._serialized_end=13406 + _DEVICEPRINTERSBLOCKLISTPROTO._serialized_start=13408 + _DEVICEPRINTERSBLOCKLISTPROTO._serialized_end=13457 + _DEVICEPRINTERSALLOWLISTPROTO._serialized_start=13459 + _DEVICEPRINTERSALLOWLISTPROTO._serialized_end=13508 + _DEVICEEXTERNALPRINTSERVERSPROTO._serialized_start=13510 + _DEVICEEXTERNALPRINTSERVERSPROTO._serialized_end=13568 + _DEVICEEXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_start=13570 + _DEVICEEXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_end=13631 + _TPMFIRMWAREUPDATESETTINGSPROTO._serialized_start=13634 + _TPMFIRMWAREUPDATESETTINGSPROTO._serialized_end=13994 + _TPMFIRMWAREUPDATESETTINGSPROTO_AUTOUPDATEMODE._serialized_start=13864 + _TPMFIRMWAREUPDATESETTINGSPROTO_AUTOUPDATEMODE._serialized_end=13994 + _OBSOLETE_MINIMUMREQUIREDVERSIONPROTO._serialized_start=13996 + _OBSOLETE_MINIMUMREQUIREDVERSIONPROTO._serialized_end=14071 + _DEVICELOGINSCREENAUTOSELECTCERTIFICATEFORURLS._serialized_start=14073 + _DEVICELOGINSCREENAUTOSELECTCERTIFICATEFORURLS._serialized_end=14172 + _UNAFFILIATEDARCALLOWEDPROTO._serialized_start=14174 + _UNAFFILIATEDARCALLOWEDPROTO._serialized_end=14237 + _DEVICEKERBEROSENCRYPTIONTYPESPROTO._serialized_start=14240 + _DEVICEKERBEROSENCRYPTIONTYPESPROTO._serialized_end=14446 + _DEVICEKERBEROSENCRYPTIONTYPESPROTO_TYPES._serialized_start=14376 + _DEVICEKERBEROSENCRYPTIONTYPESPROTO_TYPES._serialized_end=14446 + _KEYBOARDBACKLIGHTCOLORPROTO._serialized_start=14449 + _KEYBOARDBACKLIGHTCOLORPROTO._serialized_end=14799 + _KEYBOARDBACKLIGHTCOLORPROTO_BACKLIGHTCOLOR._serialized_start=14586 + _KEYBOARDBACKLIGHTCOLORPROTO_BACKLIGHTCOLOR._serialized_end=14799 + _DEVICEUSERPOLICYLOOPBACKPROCESSINGMODEPROTO._serialized_start=14802 + _DEVICEUSERPOLICYLOOPBACKPROCESSINGMODEPROTO._serialized_end=15056 + _DEVICEUSERPOLICYLOOPBACKPROCESSINGMODEPROTO_MODE._serialized_start=14962 + _DEVICEUSERPOLICYLOOPBACKPROCESSINGMODEPROTO_MODE._serialized_end=15056 + _OBSOLETE_DEVICELOGINSCREENISOLATEORIGINSPROTO._serialized_start=15058 + _OBSOLETE_DEVICELOGINSCREENISOLATEORIGINSPROTO._serialized_end=15143 + _OBSOLETE_DEVICELOGINSCREENSITEPERPROCESSPROTO._serialized_start=15145 + _OBSOLETE_DEVICELOGINSCREENSITEPERPROCESSPROTO._serialized_end=15231 + _VIRTUALMACHINESALLOWEDPROTO._serialized_start=15233 + _VIRTUALMACHINESALLOWEDPROTO._serialized_end=15296 + _DEVICEMACHINEPASSWORDCHANGERATEPROTO._serialized_start=15298 + _DEVICEMACHINEPASSWORDCHANGERATEPROTO._serialized_end=15355 + _DEVICEGPOCACHELIFETIMEPROTO._serialized_start=15357 + _DEVICEGPOCACHELIFETIMEPROTO._serialized_end=15410 + _DEVICEAUTHDATACACHELIFETIMEPROTO._serialized_start=15412 + _DEVICEAUTHDATACACHELIFETIMEPROTO._serialized_end=15470 + _DEVICEUNAFFILIATEDCROSTINIALLOWEDPROTO._serialized_start=15472 + _DEVICEUNAFFILIATEDCROSTINIALLOWEDPROTO._serialized_end=15558 + _PLUGINVMALLOWEDPROTO._serialized_start=15560 + _PLUGINVMALLOWEDPROTO._serialized_end=15609 + _PLUGINVMLICENSEKEYPROTO._serialized_start=15611 + _PLUGINVMLICENSEKEYPROTO._serialized_end=15667 + _DEVICEREBOOTONUSERSIGNOUTPROTO._serialized_start=15670 + _DEVICEREBOOTONUSERSIGNOUTPROTO._serialized_end=15951 + _DEVICEREBOOTONUSERSIGNOUTPROTO_REBOOTONSIGNOUTMODE._serialized_start=15819 + _DEVICEREBOOTONUSERSIGNOUTPROTO_REBOOTONSIGNOUTMODE._serialized_end=15951 + _DEVICEWILCODTCALLOWEDPROTO._serialized_start=15953 + _DEVICEWILCODTCALLOWEDPROTO._serialized_end=16015 + _DEVICEWILCODTCCONFIGURATIONPROTO._serialized_start=16017 + _DEVICEWILCODTCCONFIGURATIONPROTO._serialized_end=16091 + _DEVICEPOWERPEAKSHIFTPROTO._serialized_start=16093 + _DEVICEPOWERPEAKSHIFTPROTO._serialized_end=16185 + _DEVICEBOOTONACPROTO._serialized_start=16187 + _DEVICEBOOTONACPROTO._serialized_end=16225 + _DEVICEDOCKMACADDRESSSOURCEPROTO._serialized_start=16228 + _DEVICEDOCKMACADDRESSSOURCEPROTO._serialized_end=16457 + _DEVICEDOCKMACADDRESSSOURCEPROTO_SOURCE._serialized_start=16342 + _DEVICEDOCKMACADDRESSSOURCEPROTO_SOURCE._serialized_end=16457 + _DEVICEADVANCEDBATTERYCHARGEMODEPROTO._serialized_start=16459 + _DEVICEADVANCEDBATTERYCHARGEMODEPROTO._serialized_end=16535 + _DEVICEBATTERYCHARGEMODEPROTO._serialized_start=16538 + _DEVICEBATTERYCHARGEMODEPROTO._serialized_end=16850 + _DEVICEBATTERYCHARGEMODEPROTO_BATTERYCHARGEMODE._serialized_start=16727 + _DEVICEBATTERYCHARGEMODEPROTO_BATTERYCHARGEMODE._serialized_end=16850 + _DEVICEUSBPOWERSHAREPROTO._serialized_start=16852 + _DEVICEUSBPOWERSHAREPROTO._serialized_end=16895 + _DEVICESCHEDULEDUPDATECHECKPROTO._serialized_start=16897 + _DEVICESCHEDULEDUPDATECHECKPROTO._serialized_end=16978 + _DEVICEPOWERWASHALLOWEDPROTO._serialized_start=16980 + _DEVICEPOWERWASHALLOWEDPROTO._serialized_end=17043 + _DEVICELOGINSCREENWEBUSBALLOWDEVICESFORURLSPROTO._serialized_start=17045 + _DEVICELOGINSCREENWEBUSBALLOWDEVICESFORURLSPROTO._serialized_end=17153 + _SYSTEMPROXYSETTINGSPROTO._serialized_start=17155 + _SYSTEMPROXYSETTINGSPROTO._serialized_end=17212 + _REQUIREDCLIENTCERTIFICATEFORDEVICEPROTO._serialized_start=17214 + _REQUIREDCLIENTCERTIFICATEFORDEVICEPROTO._serialized_end=17303 + _DEVICECROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_start=17306 + _DEVICECROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_end=17549 + _DEVICECROSTINIARCADBSIDELOADINGALLOWEDPROTO_ALLOWANCEMODE._serialized_start=17459 + _DEVICECROSTINIARCADBSIDELOADINGALLOWEDPROTO_ALLOWANCEMODE._serialized_end=17549 + _DEVICESHOWLOWDISKSPACENOTIFICATIONPROTO._serialized_start=17551 + _DEVICESHOWLOWDISKSPACENOTIFICATIONPROTO._serialized_end=17641 + _DEVICEFAMILYLINKACCOUNTSALLOWEDPROTO._serialized_start=17643 + _DEVICEFAMILYLINKACCOUNTSALLOWEDPROTO._serialized_end=17726 + _DEVICEARCDATASNAPSHOTHOURSPROTO._serialized_start=17728 + _DEVICEARCDATASNAPSHOTHOURSPROTO._serialized_end=17794 + _DEVICESYSTEMWIDETRACINGENABLEDPROTO._serialized_start=17796 + _DEVICESYSTEMWIDETRACINGENABLEDPROTO._serialized_end=17857 + _DEVICEPCIPERIPHERALDATAACCESSENABLEDPROTO._serialized_start=17859 + _DEVICEPCIPERIPHERALDATAACCESSENABLEDPROTO._serialized_end=17926 + _DEVICEPCIPERIPHERALDATAACCESSENABLEDPROTOV2._serialized_start=17928 + _DEVICEPCIPERIPHERALDATAACCESSENABLEDPROTOV2._serialized_end=17990 + _OBSOLETE_DEVICEBOREALISALLOWEDPROTO._serialized_start=17992 + _OBSOLETE_DEVICEBOREALISALLOWEDPROTO._serialized_end=18052 + _DEVICEALLOWEDBLUETOOTHSERVICESPROTO._serialized_start=18054 + _DEVICEALLOWEDBLUETOOTHSERVICESPROTO._serialized_end=18110 + _DEVICEDEBUGPACKETCAPTUREALLOWEDPROTO._serialized_start=18112 + _DEVICEDEBUGPACKETCAPTUREALLOWEDPROTO._serialized_end=18167 + _DEVICESCHEDULEDREBOOTPROTO._serialized_start=18169 + _DEVICESCHEDULEDREBOOTPROTO._serialized_end=18239 + _DEVICERESTRICTEDMANAGEDGUESTSESSIONENABLEDPROTO._serialized_start=18241 + _DEVICERESTRICTEDMANAGEDGUESTSESSIONENABLEDPROTO._serialized_end=18314 + _DEVICEI18NSHORTCUTSENABLEDPROTO._serialized_start=18316 + _DEVICEI18NSHORTCUTSENABLEDPROTO._serialized_end=18372 + _REVENDEVICEHWDATAUSAGEENABLEDPROTO._serialized_start=18374 + _REVENDEVICEHWDATAUSAGEENABLEDPROTO._serialized_end=18454 + _DEVICELOGINSCREENWEBUILAZYLOADINGPROTO._serialized_start=18456 + _DEVICELOGINSCREENWEBUILAZYLOADINGPROTO._serialized_end=18520 + _ENCRYPTEDREPORTINGPIPELINECONFIGURATIONPROTO._serialized_start=18522 + _ENCRYPTEDREPORTINGPIPELINECONFIGURATIONPROTO._serialized_end=18591 + _DEVICEREPORTXDREVENTSPROTO._serialized_start=18593 + _DEVICEREPORTXDREVENTSPROTO._serialized_end=18645 + _CHROMEDEVICESETTINGSPROTO._serialized_start=18648 + _CHROMEDEVICESETTINGSPROTO._serialized_end=31271 +# @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_full_runtime_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_full_runtime_pb2.py deleted file mode 100644 index 3b76d465..0000000 --- a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_full_runtime_pb2.py +++ /dev/null
@@ -1,1631 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: chrome_settings_full_runtime.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -import policy_common_definitions_full_runtime_pb2 as policy__common__definitions__full__runtime__pb2 - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"chrome_settings_full_runtime.proto\x12\x15\x65nterprise_management\x1a,policy_common_definitions_full_runtime.proto\"\x83\x01\n\x1f\x43\x61lendarIntegrationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x43\x61lendarIntegrationEnabled\x18\x02 \x01(\x08\"{\n\x1b\x42rowserSwitcherEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x42rowserSwitcherEnabled\x18\x02 \x01(\x08\"\xa6\x01\n\x1f\x42rowserSwitcherUrlGreylistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x42rowserSwitcherUrlGreylist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x42rowserSwitcherParsingModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x42rowserSwitcherParsingMode\x18\x02 \x01(\x03\"w\n\x19\x42rowserSwitcherDelayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x42rowserSwitcherDelay\x18\x02 \x01(\x03\"\x87\x01\n!BrowserSwitcherUseIeSitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x42rowserSwitcherUseIeSitelist\x18\x02 \x01(\x08\"\x93\x01\n\'BrowserSwitcherExternalGreylistUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"BrowserSwitcherExternalGreylistUrl\x18\x02 \x01(\t\"\x81\x01\n\x1e\x42rowserSwitcherChromePathProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x42rowserSwitcherChromePath\x18\x02 \x01(\t\"\x8f\x01\n%BrowserSwitcherKeepLastChromeTabProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n BrowserSwitcherKeepLastChromeTab\x18\x02 \x01(\x08\"{\n\x1b\x41lternativeBrowserPathProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41lternativeBrowserPath\x18\x02 \x01(\t\"\x9e\x01\n\x1b\x42rowserSwitcherUrlListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x41\n\x16\x42rowserSwitcherUrlList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!AlternativeBrowserParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x41lternativeBrowserParameters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x93\x01\n\'BrowserSwitcherExternalSitelistUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"BrowserSwitcherExternalSitelistUrl\x18\x02 \x01(\t\"\xb0\x01\n$BrowserSwitcherChromeParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12J\n\x1f\x42rowserSwitcherChromeParameters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x46irstPartySetsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46irstPartySetsEnabled\x18\x02 \x01(\x08\"}\n\x1c\x46irstPartySetsOverridesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x46irstPartySetsOverrides\x18\x02 \x01(\t\"\x8b\x01\n#AuthNegotiateDelegateAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41uthNegotiateDelegateAllowlist\x18\x02 \x01(\t\"i\n\x12NtlmV2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rNtlmV2Enabled\x18\x02 \x01(\x08\"\xb8\x01\n(AllHttpAuthSchemesAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#AllHttpAuthSchemesAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x41llowCrossOriginAuthPromptProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41llowCrossOriginAuthPrompt\x18\x02 \x01(\x08\"\x8f\x01\n%AuthNegotiateDelegateByKdcPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n AuthNegotiateDelegateByKdcPolicy\x18\x02 \x01(\x08\"\x8d\x01\n$DisableAuthNegotiateCnameLookupProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44isableAuthNegotiateCnameLookup\x18\x02 \x01(\x08\"\x93\x01\n\'IntegratedWebAuthenticationAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"IntegratedWebAuthenticationAllowed\x18\x02 \x01(\x08\"u\n\x18\x41uthServerAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41uthServerAllowlist\x18\x02 \x01(\t\"}\n\x1c\x45nableAuthNegotiatePortProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45nableAuthNegotiatePort\x18\x02 \x01(\x08\"e\n\x10\x41uthSchemesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x41uthSchemes\x18\x02 \x01(\t\"\x8d\x01\n$AuthAndroidNegotiateAccountTypeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41uthAndroidNegotiateAccountType\x18\x02 \x01(\t\"q\n\x16GSSAPILibraryNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11GSSAPILibraryName\x18\x02 \x01(\t\"\x7f\n\x1d\x42\x61sicAuthOverHttpEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x42\x61sicAuthOverHttpEnabled\x18\x02 \x01(\x08\"e\n\x10ProxyServerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bProxyServer\x18\x02 \x01(\t\"a\n\x0eProxyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x11\n\tProxyMode\x18\x02 \x01(\t\"m\n\x14ProxyBypassListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fProxyBypassList\x18\x02 \x01(\t\"m\n\x14ProxyServerModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fProxyServerMode\x18\x02 \x01(\x03\"e\n\x10ProxyPacUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bProxyPacUrl\x18\x02 \x01(\t\"\x9f\x01\n-SamlPasswordExpirationAdvanceWarningDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(SamlPasswordExpirationAdvanceWarningDays\x18\x02 \x01(\x03\"\x83\x01\n\x1fSAMLOfflineSigninTimeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aSAMLOfflineSigninTimeLimit\x18\x02 \x01(\x03\"\x91\x01\n&LockScreenReauthenticationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!LockScreenReauthenticationEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'SamlInSessionPasswordChangeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"SamlInSessionPasswordChangeEnabled\x18\x02 \x01(\x08\"{\n\x1bReportArcStatusEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ReportArcStatusEnabled\x18\x02 \x01(\x08\"o\n\x15ProjectorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ProjectorEnabled\x18\x02 \x01(\x08\"\x97\x01\n)ProjectorDogfoodForFamilyLinkEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$ProjectorDogfoodForFamilyLinkEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#ReportExtensionsAndPluginsDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eReportExtensionsAndPluginsData\x18\x02 \x01(\x08\"o\n\x15ReportPolicyDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ReportPolicyData\x18\x02 \x01(\x08\"q\n\x16ReportVersionDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ReportVersionData\x18\x02 \x01(\x08\"{\n\x1bReportSafeBrowsingDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ReportSafeBrowsingData\x18\x02 \x01(\x08\"\x89\x01\n\"CloudReportingUploadFrequencyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43loudReportingUploadFrequency\x18\x02 \x01(\x03\"o\n\x15ReportUserIDDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ReportUserIDData\x18\x02 \x01(\x08\"y\n\x1a\x43loudReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43loudReportingEnabled\x18\x02 \x01(\x08\"\x87\x01\n!CloudExtensionRequestEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudExtensionRequestEnabled\x18\x02 \x01(\x08\"u\n\x18ReportMachineIDDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ReportMachineIDData\x18\x02 \x01(\x08\"o\n\x15\x44nsOverHttpsSaltProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44nsOverHttpsSalt\x18\x02 \x01(\t\"\x97\x01\n)DnsOverHttpsTemplatesWithIdentifiersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$DnsOverHttpsTemplatesWithIdentifiers\x18\x02 \x01(\t\"\xbb\x01\n;AccessControlAllowMethodsInCORSPreflightSpecConformantProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n6AccessControlAllowMethodsInCORSPreflightSpecConformant\x18\x02 \x01(\x08\"i\n\x12\x44riveDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDriveDisabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x44riveDisabledOverCellularProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44riveDisabledOverCellular\x18\x02 \x01(\x08\"\x83\x01\n\x1fPrintingAllowedDuplexModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPrintingAllowedDuplexModes\x18\x02 \x01(\t\"\x8d\x01\n$NativePrintersBulkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fNativePrintersBulkConfiguration\x18\x02 \x01(\t\"}\n\x1c\x43loudPrintSubmitEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43loudPrintSubmitEnabled\x18\x02 \x01(\x08\"w\n\x19PrintingColorDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrintingColorDefault\x18\x02 \x01(\t\"u\n\x18\x44isablePrintPreviewProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x44isablePrintPreview\x18\x02 \x01(\x08\"}\n\x1c\x44\x65\x66\x61ultPrinterSelectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x44\x65\x66\x61ultPrinterSelection\x18\x02 \x01(\t\"{\n\x1b\x43loudPrintProxyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43loudPrintProxyEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"ExternalPrintServersAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xternalPrintServersAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x82\x01\n\rPrintersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n\x08Printers\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18UserPrintersAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserPrintersAllowed\x18\x02 \x01(\x08\"\x7f\n\x1dPrintingPaperSizeDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrintingPaperSizeDefault\x18\x02 \x01(\t\"s\n\x17PrintingPinDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12PrintingPinDefault\x18\x02 \x01(\t\"\x87\x01\n!CloudPrintWarningsSuppressedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudPrintWarningsSuppressed\x18\x02 \x01(\x08\"\x98\x01\n\x18PrinterTypeDenyListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n\x13PrinterTypeDenyList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9b\x01\n+PrintingSendUsernameAndFilenameEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PrintingSendUsernameAndFilenameEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dPrintingMaxSheetsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrintingMaxSheetsAllowed\x18\x02 \x01(\x03\"\x91\x01\n&PrintingBackgroundGraphicsDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!PrintingBackgroundGraphicsDefault\x18\x02 \x01(\t\"{\n\x1bPrintersBulkAccessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintersBulkAccessMode\x18\x02 \x01(\x03\"w\n\x19PrintRasterizePdfDpiProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrintRasterizePdfDpi\x18\x02 \x01(\x03\"}\n\x1cPrintingAllowedPinModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17PrintingAllowedPinModes\x18\x02 \x01(\t\"\x81\x01\n\x1ePrintersBulkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PrintersBulkConfiguration\x18\x02 \x01(\t\"w\n\x19\x45xternalPrintServersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x45xternalPrintServers\x18\x02 \x01(\t\"\xae\x01\n#PrintingAPIExtensionsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1ePrintingAPIExtensionsAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1ePrintingAllowedColorModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PrintingAllowedColorModes\x18\x02 \x01(\t\"\x9c\x01\n\x1aPrintersBulkAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PrintersBulkAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18PrintPostScriptModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13PrintPostScriptMode\x18\x02 \x01(\x03\"{\n\x1bPrintPdfAsImageDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintPdfAsImageDefault\x18\x02 \x01(\x08\"q\n\x16PrintHeaderFooterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11PrintHeaderFooter\x18\x02 \x01(\x08\"y\n\x1aPrintingDuplexDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15PrintingDuplexDefault\x18\x02 \x01(\t\"\x85\x01\n PrintPdfAsImageAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPrintPdfAsImageAvailability\x18\x02 \x01(\x08\"\x87\x01\n!NativePrintersBulkAccessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNativePrintersBulkAccessMode\x18\x02 \x01(\x03\"\x8d\x01\n$PrintJobHistoryExpirationPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPrintJobHistoryExpirationPeriod\x18\x02 \x01(\x03\"\x9c\x01\n\x1aPrintersBulkBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PrintersBulkBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8e\x01\n\x13NativePrintersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0eNativePrinters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bPrintRasterizationModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintRasterizationMode\x18\x02 \x01(\x03\"m\n\x14PrintingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fPrintingEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1eUserNativePrintersAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19UserNativePrintersAllowed\x18\x02 \x01(\x08\"\x9b\x01\n+PrintingAllowedBackgroundGraphicsModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PrintingAllowedBackgroundGraphicsModes\x18\x02 \x01(\t\"\x87\x01\n!DeletePrintJobHistoryAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65letePrintJobHistoryAllowed\x18\x02 \x01(\x08\"\x95\x01\n(PrintPreviewUseSystemDefaultPrinterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#PrintPreviewUseSystemDefaultPrinter\x18\x02 \x01(\x08\"u\n\x18UserBorealisAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserBorealisAllowed\x18\x02 \x01(\x08\"\x8b\x01\n#DefaultSearchProviderSearchURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65\x66\x61ultSearchProviderSearchURL\x18\x02 \x01(\t\"\xab\x01\n3DefaultSearchProviderSearchTermsReplacementKeyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x36\n.DefaultSearchProviderSearchTermsReplacementKey\x18\x02 \x01(\t\"\x9f\x01\n-DefaultSearchProviderSearchURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(DefaultSearchProviderSearchURLPostParams\x18\x02 \x01(\t\"\x9d\x01\n,DefaultSearchProviderImageURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'DefaultSearchProviderImageURLPostParams\x18\x02 \x01(\t\"\x87\x01\n!DefaultSearchProviderIconURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderIconURL\x18\x02 \x01(\t\"\x89\x01\n\"DefaultSearchProviderImageURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultSearchProviderImageURL\x18\x02 \x01(\t\"\xa1\x01\n.DefaultSearchProviderInstantURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DefaultSearchProviderInstantURLPostParams\x18\x02 \x01(\t\"\x87\x01\n!DefaultSearchProviderKeywordProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderKeyword\x18\x02 \x01(\t\"\x81\x01\n\x1e\x44\x65\x66\x61ultSearchProviderNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultSearchProviderName\x18\x02 \x01(\t\"\x8d\x01\n$DefaultSearchProviderSuggestURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultSearchProviderSuggestURL\x18\x02 \x01(\t\"\xb6\x01\n\'DefaultSearchProviderAlternateURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12M\n\"DefaultSearchProviderAlternateURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xae\x01\n#DefaultSearchProviderEncodingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1e\x44\x65\x66\x61ultSearchProviderEncodings\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x87\x01\n!DefaultSearchProviderEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderEnabled\x18\x02 \x01(\x08\"\xa1\x01\n.DefaultSearchProviderSuggestURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DefaultSearchProviderSuggestURLPostParams\x18\x02 \x01(\t\"\x8b\x01\n#DefaultSearchProviderNewTabURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65\x66\x61ultSearchProviderNewTabURL\x18\x02 \x01(\t\"\x8d\x01\n$DefaultSearchProviderInstantURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultSearchProviderInstantURL\x18\x02 \x01(\t\"\x8b\x01\n#GaiaOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eGaiaOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"w\n\x19HomepageIsNewTabPageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14HomepageIsNewTabPage\x18\x02 \x01(\x08\"s\n\x17NewTabPageLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12NewTabPageLocation\x18\x02 \x01(\t\"\x9a\x01\n\x19RestoreOnStartupURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14RestoreOnStartupURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"o\n\x15HomepageLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10HomepageLocation\x18\x02 \x01(\t\"o\n\x15RestoreOnStartupProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10RestoreOnStartup\x18\x02 \x01(\x03\"k\n\x13ShowHomeButtonProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eShowHomeButton\x18\x02 \x01(\x08\"\x96\x01\n\x17IdleTimeoutActionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12IdleTimeoutActions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"e\n\x10IdleTimeoutProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bIdleTimeout\x18\x02 \x01(\x03\"\x89\x01\n\"NativeMessagingUserLevelHostsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dNativeMessagingUserLevelHosts\x18\x02 \x01(\x08\"\xa2\x01\n\x1dNativeMessagingBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dNativeMessagingAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$UserActivityScreenDimDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fUserActivityScreenDimDelayScale\x18\x02 \x01(\x03\"o\n\x15IdleDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10IdleDelayBattery\x18\x02 \x01(\x03\"c\n\x0fIdleActionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nIdleAction\x18\x02 \x01(\x03\"\x8f\x01\n%PowerManagementUsesVideoActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PowerManagementUsesVideoActivity\x18\x02 \x01(\x08\"o\n\x15ScreenDimDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenDimDelayAC\x18\x02 \x01(\x03\"w\n\x19\x41llowScreenWakeLocksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41llowScreenWakeLocks\x18\x02 \x01(\x08\"\x83\x01\n\x1fPresentationIdleDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPresentationIdleDelayScale\x18\x02 \x01(\x03\"k\n\x13LidCloseActionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eLidCloseAction\x18\x02 \x01(\x03\"k\n\x13\x41llowWakeLocksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0e\x41llowWakeLocks\x18\x02 \x01(\x08\"w\n\x19PowerSmartDimEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PowerSmartDimEnabled\x18\x02 \x01(\x08\"y\n\x1aScreenOffDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ScreenOffDelayBattery\x18\x02 \x01(\x03\"\x8d\x01\n$PresentationScreenDimDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPresentationScreenDimDelayScale\x18\x02 \x01(\x03\"s\n\x17IdleWarningDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12IdleWarningDelayAC\x18\x02 \x01(\x03\"y\n\x1aScreenDimDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ScreenDimDelayBattery\x18\x02 \x01(\x03\"\x8f\x01\n%PowerManagementUsesAudioActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PowerManagementUsesAudioActivity\x18\x02 \x01(\x08\"e\n\x10IdleDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bIdleDelayAC\x18\x02 \x01(\x03\"\x85\x01\n PowerManagementIdleSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPowerManagementIdleSettings\x18\x02 \x01(\t\"q\n\x16ScreenLockDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ScreenLockDelayAC\x18\x02 \x01(\x03\"q\n\x16IdleActionBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11IdleActionBattery\x18\x02 \x01(\x03\"\x93\x01\n\'DevicePowerAdaptiveChargingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DevicePowerAdaptiveChargingEnabled\x18\x02 \x01(\x08\"o\n\x15ScreenLockDelaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenLockDelays\x18\x02 \x01(\t\"o\n\x15ScreenOffDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenOffDelayAC\x18\x02 \x01(\x03\"g\n\x11IdleActionACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cIdleActionAC\x18\x02 \x01(\x03\"}\n\x1cScreenBrightnessPercentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17ScreenBrightnessPercent\x18\x02 \x01(\t\"}\n\x1cIdleWarningDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17IdleWarningDelayBattery\x18\x02 \x01(\x03\"{\n\x1bScreenLockDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ScreenLockDelayBattery\x18\x02 \x01(\x03\"\x83\x01\n\x1fWaitForInitialUserActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aWaitForInitialUserActivity\x18\x02 \x01(\x08\"\x9a\x01\n\x19KeygenAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14KeygenAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x89\x01\n\"DefaultInsecureContentSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultInsecureContentSetting\x18\x02 \x01(\x03\"\x9c\x01\n\x1aSensorsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SensorsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xb8\x01\n(PdfLocalFileAccessAllowedForDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#PdfLocalFileAccessAllowedForDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1d\x44\x65\x66\x61ultLocalFontsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultLocalFontsSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19PopupsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14PopupsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1d\x46ileSystemReadAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18\x46ileSystemReadAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19KeygenBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14KeygenBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dLocalFontsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18LocalFontsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x92\x01\n\x15WebHidAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10WebHidAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19WebUsbBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14WebUsbBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultMediaStreamSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultMediaStreamSetting\x18\x02 \x01(\x03\"\x7f\n\x1d\x44\x65\x66\x61ultJavaScriptSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultJavaScriptSetting\x18\x02 \x01(\x03\"w\n\x19\x44\x65\x66\x61ultPopupsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultPopupsSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19ImagesAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14ImagesAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x44\x65\x66\x61ultKeygenSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultKeygenSetting\x18\x02 \x01(\x03\"\x9c\x01\n\x1aPluginsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PluginsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xad\x01\n4FileSystemSyncAccessHandleAsyncInterfaceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n/FileSystemSyncAccessHandleAsyncInterfaceEnabled\x18\x02 \x01(\x08\"\xa0\x01\n\x1c\x43lipboardBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43lipboardBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x89\x01\n\"DefaultWindowPlacementSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultWindowPlacementSetting\x18\x02 \x01(\x03\"\xa4\x01\n\x1e\x43ookiesSessionOnlyForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x43ookiesSessionOnlyForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n DefaultNotificationsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x65\x66\x61ultNotificationsSetting\x18\x02 \x01(\x03\"\xaa\x01\n!WebHidAllowAllDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cWebHidAllowAllDevicesForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultWebHidGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultWebHidGuardSetting\x18\x02 \x01(\x03\"\x87\x01\n!SerialAllowUsbDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSerialAllowUsbDevicesForUrls\x18\x02 \x01(\t\"\x9a\x01\n\x19SerialBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14SerialBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19WebHidBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14WebHidBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1a\x43ookiesAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x43ookiesAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1aSensorsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SensorsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1aPluginsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PluginsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1f\x46ileHandlingBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x46ileHandlingBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fRegisteredProtocolHandlersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aRegisteredProtocolHandlers\x18\x02 \x01(\t\"\x92\x01\n\x15SerialAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10SerialAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultCookiesSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultCookiesSetting\x18\x02 \x01(\x03\"\x95\x01\n(LegacySameSiteCookieBehaviorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#LegacySameSiteCookieBehaviorEnabled\x18\x02 \x01(\x03\"\xa2\x01\n\x1dJavaScriptBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18JavaScriptBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x91\x01\n&DefaultFileSystemReadGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!DefaultFileSystemReadGuardSetting\x18\x02 \x01(\x03\"\xa8\x01\n NotificationsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNotificationsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultWebUsbGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultWebUsbGuardSetting\x18\x02 \x01(\x03\"\x81\x01\n\x1eWebUsbAllowDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WebUsbAllowDevicesForUrls\x18\x02 \x01(\t\"}\n\x1c\x44\x65\x66\x61ultClipboardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x44\x65\x66\x61ultClipboardSetting\x18\x02 \x01(\x03\"\xac\x01\n\"WindowPlacementAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowPlacementAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xd2\x01\n5LegacySameSiteCookieBehaviorEnabledForDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0LegacySameSiteCookieBehaviorEnabledForDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dLocalFontsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18LocalFontsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultGeolocationSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultGeolocationSetting\x18\x02 \x01(\x03\"\xaa\x01\n!FileSystemReadBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x46ileSystemReadBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultSerialGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultSerialGuardSetting\x18\x02 \x01(\x03\"\x81\x01\n\x1eWebHidAllowDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WebHidAllowDevicesForUrls\x18\x02 \x01(\t\"\xaa\x01\n!AutoSelectCertificateForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x41utoSelectCertificateForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultPluginsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultPluginsSetting\x18\x02 \x01(\x03\"w\n\x19\x44\x65\x66\x61ultImagesSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultImagesSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19PopupsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14PopupsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$DefaultWebBluetoothGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultWebBluetoothGuardSetting\x18\x02 \x01(\x03\"\xa0\x01\n\x1c\x43lipboardAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43lipboardAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"WindowPlacementBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowPlacementBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"InsecureContentBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dInsecureContentBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1f\x46ileHandlingAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x46ileHandlingAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x92\x01\n\x15WebUsbAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10WebUsbAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultSensorsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultSensorsSetting\x18\x02 \x01(\x03\"\x9b\x01\n+WebHidAllowDevicesWithHidUsagesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&WebHidAllowDevicesWithHidUsagesForUrls\x18\x02 \x01(\t\"\xa8\x01\n NotificationsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNotificationsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n DefaultJavaScriptJitSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x65\x66\x61ultJavaScriptJitSetting\x18\x02 \x01(\x03\"\xa4\x01\n\x1e\x46ileSystemWriteAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x46ileSystemWriteAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"InsecureContentAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dInsecureContentAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1a\x43ookiesBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x43ookiesBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1fSerialAllowAllPortsForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aSerialAllowAllPortsForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19ImagesBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14ImagesBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!JavaScriptJitAllowedForSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cJavaScriptJitAllowedForSites\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x93\x01\n\'DefaultFileSystemWriteGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DefaultFileSystemWriteGuardSetting\x18\x02 \x01(\x03\"\x8d\x01\n$DefaultFileHandlingGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultFileHandlingGuardSetting\x18\x02 \x01(\x03\"\xaa\x01\n!JavaScriptJitBlockedForSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cJavaScriptJitBlockedForSites\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dJavaScriptAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18JavaScriptAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"FileSystemWriteBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x46ileSystemWriteBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$KerberosRememberPasswordEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fKerberosRememberPasswordEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fKerberosDomainAutocompleteProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aKerberosDomainAutocomplete\x18\x02 \x01(\t\"o\n\x15KerberosAccountsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10KerberosAccounts\x18\x02 \x01(\t\"\x87\x01\n!KerberosDefaultConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cKerberosDefaultConfiguration\x18\x02 \x01(\t\"\x83\x01\n\x1fKerberosAddAccountsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aKerberosAddAccountsAllowed\x18\x02 \x01(\x08\"m\n\x14KerberosEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fKerberosEnabled\x18\x02 \x01(\x08\"\xa0\x01\n\x1c\x43hromeFrameContentTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43hromeFrameContentTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x89\x01\n\"QuickAnswersDefinitionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dQuickAnswersDefinitionEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#QuickAnswersTranslationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eQuickAnswersTranslationEnabled\x18\x02 \x01(\x08\"\x91\x01\n&QuickAnswersUnitConversionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!QuickAnswersUnitConversionEnabled\x18\x02 \x01(\x08\"u\n\x18QuickAnswersEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13QuickAnswersEnabled\x18\x02 \x01(\x08\"\x97\x01\n)SupervisedUserContentProviderEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SupervisedUserContentProviderEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"SupervisedUserCreationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dSupervisedUserCreationEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'RemoteAccessHostTokenValidationUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostTokenValidationUrl\x18\x02 \x01(\t\"\xaf\x01\n5RemoteAccessHostTokenValidationCertificateIssuerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0RemoteAccessHostTokenValidationCertificateIssuer\x18\x02 \x01(\t\"\xa9\x01\n2RemoteAccessHostAllowRemoteSupportConnectionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-RemoteAccessHostAllowRemoteSupportConnections\x18\x02 \x01(\x08\"\x8b\x01\n#RemoteAccessHostRequireCurtainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eRemoteAccessHostRequireCurtain\x18\x02 \x01(\x08\"\xa7\x01\n1RemoteAccessHostAllowRemoteAccessConnectionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,RemoteAccessHostAllowRemoteAccessConnections\x18\x02 \x01(\x08\"\x87\x01\n!RemoteAccessHostUdpPortRangeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRemoteAccessHostUdpPortRange\x18\x02 \x01(\t\"\x8d\x01\n$RemoteAccessHostAllowGnubbyAuthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fRemoteAccessHostAllowGnubbyAuth\x18\x02 \x01(\x08\"\x95\x01\n(RemoteAccessHostEnableUserInterfaceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#RemoteAccessHostEnableUserInterface\x18\x02 \x01(\x08\"\x8f\x01\n%RemoteAccessHostTalkGadgetPrefixProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RemoteAccessHostTalkGadgetPrefix\x18\x02 \x01(\t\"\xb2\x01\n%RemoteAccessHostClientDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12K\n RemoteAccessHostClientDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaf\x01\n5RemoteAccessHostAllowUiAccessForRemoteAssistanceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0RemoteAccessHostAllowUiAccessForRemoteAssistance\x18\x02 \x01(\x08\"\x89\x01\n\"RemoteAccessHostMatchUsernameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dRemoteAccessHostMatchUsername\x18\x02 \x01(\x08\"\x95\x01\n(RemoteAccessClientFirewallTraversalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#RemoteAccessClientFirewallTraversal\x18\x02 \x01(\x08\"\x9b\x01\n+RemoteAccessHostAllowRelayedConnectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&RemoteAccessHostAllowRelayedConnection\x18\x02 \x01(\x08\"\xa9\x01\n2RemoteAccessHostMaximumSessionDurationMinutesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-RemoteAccessHostMaximumSessionDurationMinutes\x18\x02 \x01(\x03\"\x87\x01\n!RemoteAccessHostClientDomainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRemoteAccessHostClientDomain\x18\x02 \x01(\t\"\x8f\x01\n%RemoteAccessHostRequireTwoFactorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RemoteAccessHostRequireTwoFactor\x18\x02 \x01(\x08\"\x99\x01\n*RemoteAccessHostDebugOverridePoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%RemoteAccessHostDebugOverridePolicies\x18\x02 \x01(\t\"\x93\x01\n\'RemoteAccessHostClipboardSizeBytesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostClipboardSizeBytes\x18\x02 \x01(\x03\"\x7f\n\x1dRemoteAccessHostTokenUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18RemoteAccessHostTokenUrl\x18\x02 \x01(\t\"\xa6\x01\n\x1fRemoteAccessHostDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aRemoteAccessHostDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x91\x01\n&RemoteAccessHostFirewallTraversalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!RemoteAccessHostFirewallTraversal\x18\x02 \x01(\x08\"{\n\x1bRemoteAccessHostDomainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RemoteAccessHostDomain\x18\x02 \x01(\t\"\x91\x01\n&RemoteAccessHostAllowFileTransferProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!RemoteAccessHostAllowFileTransfer\x18\x02 \x01(\x08\"\x93\x01\n\'RemoteAccessHostAllowClientPairingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostAllowClientPairing\x18\x02 \x01(\x08\"\x7f\n\x1dNewWindowsInKioskAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NewWindowsInKioskAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"ExtensionAllowInsecureUpdatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x45xtensionAllowInsecureUpdates\x18\x02 \x01(\x08\"\xa4\x01\n\x1e\x45xtensionInstallAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallForcelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallForcelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1a\x45xtensionAllowedTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x45xtensionAllowedTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa0\x01\n\x1c\x45xtensionInstallSourcesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x45xtensionInstallSources\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$ExtensionManifestV2AvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x45xtensionManifestV2Availability\x18\x02 \x01(\x03\"}\n\x1c\x42lockExternalExtensionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42lockExternalExtensions\x18\x02 \x01(\x08\"q\n\x16\x45xtensionSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45xtensionSettings\x18\x02 \x01(\t\"\x95\x01\n(VoiceInteractionQuickAnswersEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#VoiceInteractionQuickAnswersEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#VoiceInteractionContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eVoiceInteractionContextEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#VoiceInteractionHotwordEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eVoiceInteractionHotwordEnabled\x18\x02 \x01(\x08\"\x97\x01\n)AssistantVoiceMatchEnabledDuringOobeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$AssistantVoiceMatchEnabledDuringOobe\x18\x02 \x01(\x08\"}\n\x1c\x41ssistantOnboardingModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41ssistantOnboardingMode\x18\x02 \x01(\t\"u\n\x18\x41ssistantWebEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41ssistantWebEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"AttestationExtensionAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x41ttestationExtensionAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x41ttestationEnabledForUserProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41ttestationEnabledForUser\x18\x02 \x01(\x08\"u\n\x18\x43\x61stReceiverEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43\x61stReceiverEnabled\x18\x02 \x01(\x08\"{\n\x1bRecoveryFactorBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RecoveryFactorBehavior\x18\x02 \x01(\x08\"y\n\x1aShowCastIconInToolbarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ShowCastIconInToolbar\x18\x02 \x01(\x08\"\x99\x01\n*ShowCastSessionsStartedByOtherDevicesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%ShowCastSessionsStartedByOtherDevices\x18\x02 \x01(\x08\"\x83\x01\n\x1fMediaRouterCastAllowAllIPsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aMediaRouterCastAllowAllIPs\x18\x02 \x01(\x08\"q\n\x16\x45nableMediaRouterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45nableMediaRouter\x18\x02 \x01(\x08\"o\n\x15\x41utoclickEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x41utoclickEnabled\x18\x02 \x01(\x08\"{\n\x1bVirtualKeyboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16VirtualKeyboardEnabled\x18\x02 \x01(\x08\"q\n\x16StickyKeysEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11StickyKeysEnabled\x18\x02 \x01(\x08\"}\n\x1cVirtualKeyboardFeaturesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17VirtualKeyboardFeatures\x18\x02 \x01(\t\"u\n\x18HighContrastEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13HighContrastEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"KeyboardDefaultToFunctionKeysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dKeyboardDefaultToFunctionKeys\x18\x02 \x01(\x08\"\x89\x01\n\"AccessibilityShortcutsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x41\x63\x63\x65ssibilityShortcutsEnabled\x18\x02 \x01(\x08\"w\n\x19SelectToSpeakEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14SelectToSpeakEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%FloatingAccessibilityMenuEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n FloatingAccessibilityMenuEnabled\x18\x02 \x01(\x08\"\x9f\x01\n-ShowAccessibilityOptionsInSystemTrayMenuProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(ShowAccessibilityOptionsInSystemTrayMenu\x18\x02 \x01(\x08\"{\n\x1b\x43ursorHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43ursorHighlightEnabled\x18\x02 \x01(\x08\"y\n\x1a\x43\x61retHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43\x61retHighlightEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"KeyboardFocusHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dKeyboardFocusHighlightEnabled\x18\x02 \x01(\x08\"u\n\x18ScreenMagnifierTypeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ScreenMagnifierType\x18\x02 \x01(\x03\"o\n\x15MonoAudioEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10MonoAudioEnabled\x18\x02 \x01(\x08\"\xa5\x01\n0EnhancedNetworkVoicesInSelectToSpeakAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+EnhancedNetworkVoicesInSelectToSpeakAllowed\x18\x02 \x01(\x08\"y\n\x1aSpokenFeedbackEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SpokenFeedbackEnabled\x18\x02 \x01(\x08\"o\n\x15\x44ictationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44ictationEnabled\x18\x02 \x01(\x08\"s\n\x17LargeCursorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12LargeCursorEnabled\x18\x02 \x01(\x08\"{\n\x1bPasswordManagerEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PasswordManagerEnabled\x18\x02 \x01(\x08\"\x9b\x01\n+PasswordDismissCompromisedAlertEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PasswordDismissCompromisedAlertEnabled\x18\x02 \x01(\x08\"\x87\x01\n!PasswordLeakDetectionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cPasswordLeakDetectionEnabled\x18\x02 \x01(\x08\"\x91\x01\n&PasswordManagerAllowShowPasswordsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!PasswordManagerAllowShowPasswords\x18\x02 \x01(\x08\"\x89\x01\n\"PluginVmDataCollectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dPluginVmDataCollectionAllowed\x18\x02 \x01(\x08\"k\n\x13PluginVmUserIdProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0ePluginVmUserId\x18\x02 \x01(\t\"u\n\x18UserPluginVmAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserPluginVmAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"PluginVmRequiredFreeDiskSpaceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dPluginVmRequiredFreeDiskSpace\x18\x02 \x01(\x03\"i\n\x12PluginVmImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rPluginVmImage\x18\x02 \x01(\t\"k\n\x13UsageTimeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eUsageTimeLimit\x18\x02 \x01(\t\"\x81\x01\n\x1ePerAppTimeLimitsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PerAppTimeLimitsAllowlist\x18\x02 \x01(\t\"{\n\x1bParentAccessCodeConfigProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ParentAccessCodeConfig\x18\x02 \x01(\t\"o\n\x15PerAppTimeLimitsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10PerAppTimeLimits\x18\x02 \x01(\t\"\x7f\n\x1d\x45\x64uCoexistenceToSVersionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x45\x64uCoexistenceToSVersion\x18\x02 \x01(\t\"\x8f\x01\n%RequiredClientCertificateForUserProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RequiredClientCertificateForUser\x18\x02 \x01(\t\"\x97\x01\n)SafeBrowsingExtendedReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SafeBrowsingExtendedReportingEnabled\x18\x02 \x01(\x08\"\x85\x01\n SafeBrowsingProtectionLevelProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bSafeBrowsingProtectionLevel\x18\x02 \x01(\x03\"u\n\x18SafeBrowsingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13SafeBrowsingEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%PasswordProtectionWarningTriggerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PasswordProtectionWarningTrigger\x18\x02 \x01(\x03\"\x95\x01\n(PasswordProtectionChangePasswordURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#PasswordProtectionChangePasswordURL\x18\x02 \x01(\t\"\xaa\x01\n!SafeBrowsingAllowlistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSafeBrowsingAllowlistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa8\x01\n PasswordProtectionLoginURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bPasswordProtectionLoginURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fPinUnlockAutosubmitEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPinUnlockAutosubmitEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dPinUnlockWeakPinsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PinUnlockWeakPinsAllowed\x18\x02 \x01(\x08\"\xa2\x01\n\x1dQuickUnlockModeAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18QuickUnlockModeAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bPinUnlockMinimumLengthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PinUnlockMinimumLength\x18\x02 \x01(\x03\"{\n\x1bPinUnlockMaximumLengthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PinUnlockMaximumLength\x18\x02 \x01(\x03\"s\n\x17QuickUnlockTimeoutProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12QuickUnlockTimeout\x18\x02 \x01(\x03\"s\n\x17\x43loudAPAuthEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x43loudAPAuthEnabled\x18\x02 \x01(\x03\"\x89\x01\n\"CrostiniExportImportUIAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43rostiniExportImportUIAllowed\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x43rostiniRootAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x43rostiniRootAccessAllowed\x18\x02 \x01(\x08\"m\n\x14\x43rostiniAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x43rostiniAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"CrostiniPortForwardingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43rostiniPortForwardingAllowed\x18\x02 \x01(\x08\"\x7f\n\x1dSystemTerminalSshAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18SystemTerminalSshAllowed\x18\x02 \x01(\x08\"}\n\x1c\x43rostiniAnsiblePlaybookProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43rostiniAnsiblePlaybook\x18\x02 \x01(\t\"\x8f\x01\n%CrostiniArcAdbSideloadingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n CrostiniArcAdbSideloadingAllowed\x18\x02 \x01(\x03\"\x85\x01\n DataCompressionProxyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x61taCompressionProxyEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fHindiInscriptLayoutEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aHindiInscriptLayoutEnabled\x18\x02 \x01(\x08\"\x87\x01\n!EnableOnlineRevocationChecksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x45nableOnlineRevocationChecks\x18\x02 \x01(\x08\"\xb8\x01\n(UnsafelyTreatInsecureOriginAsSecureProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#UnsafelyTreatInsecureOriginAsSecure\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x46orceYouTubeSafetyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46orceYouTubeSafetyMode\x18\x02 \x01(\x08\"\xde\x01\n;CertificateTransparencyEnforcementDisabledForLegacyCasProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x61\n6CertificateTransparencyEnforcementDisabledForLegacyCas\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"i\n\x12HttpsOnlyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rHttpsOnlyMode\x18\x02 \x01(\t\"\x8f\x01\n%SetTimeoutWithout1MsClampEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n SetTimeoutWithout1MsClampEnabled\x18\x02 \x01(\x08\"y\n\x1a\x44nsPrefetchingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44nsPrefetchingEnabled\x18\x02 \x01(\x08\"\xa8\x01\n SpellcheckLanguageBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bSpellcheckLanguageBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x90\x01\n\x14\x44isabledPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x44isabledPlugins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bSchedulerConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SchedulerConfiguration\x18\x02 \x01(\t\"\x81\x01\n\x1ePolicyAtomicGroupsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PolicyAtomicGroupsEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#AdditionalDnsQueryTypesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41\x64\x64itionalDnsQueryTypesEnabled\x18\x02 \x01(\x08\"\x99\x01\n*AdvancedProtectionDeepScanningEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%AdvancedProtectionDeepScanningEnabled\x18\x02 \x01(\x08\"\x85\x01\n ScrollToTextFragmentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bScrollToTextFragmentEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#AuthNegotiateDelegateWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41uthNegotiateDelegateWhitelist\x18\x02 \x01(\t\"\x85\x01\n RendererAppContainerEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bRendererAppContainerEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"AttestationExtensionWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x41ttestationExtensionWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bMaxConnectionsPerProxyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16MaxConnectionsPerProxy\x18\x02 \x01(\x03\"s\n\x17\x44isableScreenshotsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x44isableScreenshots\x18\x02 \x01(\x08\"\xd4\x01\n6CertificateTransparencyEnforcementDisabledForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\\\n1CertificateTransparencyEnforcementDisabledForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bShowLogoutButtonInTrayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ShowLogoutButtonInTray\x18\x02 \x01(\x08\"o\n\x15VpnConfigAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10VpnConfigAllowed\x18\x02 \x01(\x08\"\x8e\x01\n\x13\x45nabledPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0e\x45nabledPlugins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#EnableDeprecatedPrivetPrintingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nableDeprecatedPrivetPrinting\x18\x02 \x01(\x08\"\x8b\x01\n#EnterpriseRealTimeUrlCheckModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nterpriseRealTimeUrlCheckMode\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x41\x64vancedProtectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41\x64vancedProtectionAllowed\x18\x02 \x01(\x08\"{\n\x1b\x41pplicationLocaleValueProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41pplicationLocaleValue\x18\x02 \x01(\t\"w\n\x19\x41ppCacheForceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41ppCacheForceEnabled\x18\x02 \x01(\x08\"\x99\x01\n*EnterpriseAuthenticationAppLinkPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%EnterpriseAuthenticationAppLinkPolicy\x18\x02 \x01(\t\"\x87\x01\n!TaskManagerEndProcessEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cTaskManagerEndProcessEnabled\x18\x02 \x01(\x08\"y\n\x1aSitePerProcessAndroidProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SitePerProcessAndroid\x18\x02 \x01(\x08\"\x7f\n\x1dIntranetRedirectBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18IntranetRedirectBehavior\x18\x02 \x01(\x03\"\x8f\x01\n%DefaultHandlersForFileExtensionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n DefaultHandlersForFileExtensions\x18\x02 \x01(\t\"\x7f\n\x1d\x42rowserGuestModeEnforcedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x42rowserGuestModeEnforced\x18\x02 \x01(\x08\"i\n\x12SSLVersionMaxProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSSLVersionMax\x18\x02 \x01(\t\"\x81\x01\n\x1ePerAppTimeLimitsWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PerAppTimeLimitsWhitelist\x18\x02 \x01(\t\"o\n\x15IncognitoEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10IncognitoEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x42ruschettaVMConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x42ruschettaVMConfiguration\x18\x02 \x01(\t\"\x85\x01\n PacHttpsUrlStrippingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPacHttpsUrlStrippingEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'OffsetParentNewSpecBehaviorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OffsetParentNewSpecBehaviorEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'CloudPolicyOverridesPlatformPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"CloudPolicyOverridesPlatformPolicy\x18\x02 \x01(\x08\"\x95\x01\n(SecondaryGoogleAccountSigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#SecondaryGoogleAccountSigninAllowed\x18\x02 \x01(\x08\"w\n\x19\x44ownloadRestrictionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44ownloadRestrictions\x18\x02 \x01(\x03\"\x83\x01\n\x1f\x41lternateErrorPagesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41lternateErrorPagesEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#AutoLaunchProtocolsFromOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41utoLaunchProtocolsFromOrigins\x18\x02 \x01(\t\"k\n\x13WallpaperImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eWallpaperImage\x18\x02 \x01(\t\"\x97\x01\n)AbusiveExperienceInterventionEnforceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$AbusiveExperienceInterventionEnforce\x18\x02 \x01(\x08\"\x8f\x01\n%ChromeOsMultiProfileUserBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ChromeOsMultiProfileUserBehavior\x18\x02 \x01(\t\"w\n\x19RelaunchNotificationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14RelaunchNotification\x18\x02 \x01(\x03\"k\n\x13ImportHomepageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eImportHomepage\x18\x02 \x01(\x08\"k\n\x13RelaunchWindowProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eRelaunchWindow\x18\x02 \x01(\t\"k\n\x13ShelfAlignmentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eShelfAlignment\x18\x02 \x01(\t\"s\n\x17\x42ookmarkBarEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x42ookmarkBarEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ManagedAccountsSigninRestrictionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ManagedAccountsSigninRestriction\x18\x02 \x01(\t\"\x87\x01\n!PhoneHubNotificationsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cPhoneHubNotificationsAllowed\x18\x02 \x01(\x08\"\x97\x01\n)CORSNonWildcardRequestHeadersSupportProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$CORSNonWildcardRequestHeadersSupport\x18\x02 \x01(\x08\"\x8d\x01\n$HardwareAccelerationModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fHardwareAccelerationModeEnabled\x18\x02 \x01(\x08\"}\n\x1c\x43ontextualSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43ontextualSearchEnabled\x18\x02 \x01(\x08\"q\n\x16\x45\x61syUnlockAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45\x61syUnlockAllowed\x18\x02 \x01(\x08\"}\n\x1c\x45xternalStorageReadOnlyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45xternalStorageReadOnly\x18\x02 \x01(\x08\"\x87\x01\n!SecurityTokenSessionBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSecurityTokenSessionBehavior\x18\x02 \x01(\t\"u\n\x18UserFeedbackAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserFeedbackAllowed\x18\x02 \x01(\x08\"\x85\x01\n LockIconInAddressBarEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bLockIconInAddressBarEnabled\x18\x02 \x01(\x08\"\xb2\x01\n%LookalikeWarningAllowlistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12K\n LookalikeWarningAllowlistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xe0\x01\n<RestrictedManagedGuestSessionExtensionCleanupExemptListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x62\n7RestrictedManagedGuestSessionExtensionCleanupExemptList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8f\x01\n%IsolatedAppsDeveloperModeAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n IsolatedAppsDeveloperModeAllowed\x18\x02 \x01(\x08\"w\n\x19SearchSuggestEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14SearchSuggestEnabled\x18\x02 \x01(\x08\"g\n\x11TrashEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cTrashEnabled\x18\x02 \x01(\x08\"\xa0\x01\n\x1cVideoCaptureAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17VideoCaptureAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17\x42rowserLabsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x42rowserLabsEnabled\x18\x02 \x01(\x08\"\x9f\x01\n-SamlLockScreenOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(SamlLockScreenOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"\x8b\x01\n#IsolatedWebAppInstallForceListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eIsolatedWebAppInstallForceList\x18\x02 \x01(\t\"\xd2\x01\n5GetDisplayMediaSetSelectAllScreensAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0GetDisplayMediaSetSelectAllScreensAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17SessionLengthLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12SessionLengthLimit\x18\x02 \x01(\x03\"q\n\x16\x42rowserThemeColorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x42rowserThemeColor\x18\x02 \x01(\t\"\xa9\x01\n2WebAuthenticationRemoteProxiedRequestsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-WebAuthenticationRemoteProxiedRequestsAllowed\x18\x02 \x01(\x08\"\x97\x01\n)PromptOnMultipleMatchingCertificatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$PromptOnMultipleMatchingCertificates\x18\x02 \x01(\x08\"\x87\x01\n!InsecureFormsWarningsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cInsecureFormsWarningsEnabled\x18\x02 \x01(\x08\"k\n\x13GCFUserDataDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eGCFUserDataDir\x18\x02 \x01(\t\"\x85\x01\n SecondaryGoogleAccountUsageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bSecondaryGoogleAccountUsage\x18\x02 \x01(\t\"w\n\x19PolicyScopeDetectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PolicyScopeDetection\x18\x02 \x01(\x08\"i\n\x12\x44isable3DAPIsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDisable3DAPIs\x18\x02 \x01(\x08\"\x8b\x01\n#UnifiedDesktopEnabledByDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUnifiedDesktopEnabledByDefault\x18\x02 \x01(\x08\"\x81\x01\n\x1ePaymentMethodQueryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PaymentMethodQueryEnabled\x18\x02 \x01(\x08\"u\n\x18VideoCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13VideoCaptureAllowed\x18\x02 \x01(\x08\"\x8d\x01\n$LacrosDataBackwardMigrationModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fLacrosDataBackwardMigrationMode\x18\x02 \x01(\t\"\x8f\x01\n%IntensiveWakeUpThrottlingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n IntensiveWakeUpThrottlingEnabled\x18\x02 \x01(\x08\"y\n\x1aShelfAutoHideBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ShelfAutoHideBehavior\x18\x02 \x01(\t\"g\n\x11SyncDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cSyncDisabled\x18\x02 \x01(\x08\"g\n\x11\x44iskCacheDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0c\x44iskCacheDir\x18\x02 \x01(\t\"\xa1\x01\n.DataLeakPreventionClipboardCheckSizeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DataLeakPreventionClipboardCheckSizeLimit\x18\x02 \x01(\x03\"\x87\x01\n!AccessCodeCastDeviceDurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x41\x63\x63\x65ssCodeCastDeviceDuration\x18\x02 \x01(\x03\"\x85\x01\n DataLeakPreventionRulesListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x61taLeakPreventionRulesList\x18\x02 \x01(\t\"\x8a\x01\n\x11URLWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9b\x01\n+SuppressDifferentOriginSubframeDialogsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&SuppressDifferentOriginSubframeDialogs\x18\x02 \x01(\x08\"}\n\x1c\x43omponentUpdatesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43omponentUpdatesEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$WebRtcEventLogCollectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fWebRtcEventLogCollectionAllowed\x18\x02 \x01(\x08\"\x85\x01\n EncryptedClientHelloEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x45ncryptedClientHelloEnabled\x18\x02 \x01(\x08\"\x9c\x01\n\x1aSyncTypesListDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SyncTypesListDisabled\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"}\n\x1cWebXRImmersiveArEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17WebXRImmersiveArEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%OptimizationGuideFetchingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n OptimizationGuideFetchingEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"ExplicitlyAllowedNetworkPortsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xplicitlyAllowedNetworkPorts\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x96\x01\n\x17PinnedLauncherAppsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12PinnedLauncherApps\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18\x43\x43TToSDialogEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43\x43TToSDialogEnabled\x18\x02 \x01(\x08\"\xa0\x01\n\x1c\x41udioCaptureAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x41udioCaptureAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xb4\x01\n&NoteTakingAppsLockScreenAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!NoteTakingAppsLockScreenAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x87\x01\n!RoamingProfileSupportEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRoamingProfileSupportEnabled\x18\x02 \x01(\x08\"{\n\x1b\x41lwaysAuthorizePluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41lwaysAuthorizePlugins\x18\x02 \x01(\x08\"{\n\x1bPersistentQuotaEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PersistentQuotaEnabled\x18\x02 \x01(\x08\"k\n\x13WebAppSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eWebAppSettings\x18\x02 \x01(\t\"s\n\x17\x43lickToCallEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x43lickToCallEnabled\x18\x02 \x01(\x08\"s\n\x17NearbyShareAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12NearbyShareAllowed\x18\x02 \x01(\x08\"y\n\x1a\x41\x63\x63\x65ssCodeCastEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x41\x63\x63\x65ssCodeCastEnabled\x18\x02 \x01(\x08\"w\n\x19\x45\x64itBookmarksEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x45\x64itBookmarksEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"WelcomePageOnOSUpgradeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWelcomePageOnOSUpgradeEnabled\x18\x02 \x01(\x08\"\x9f\x01\n-UnmanagedDeviceSignalsConsentFlowEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(UnmanagedDeviceSignalsConsentFlowEnabled\x18\x02 \x01(\x08\"\xb9\x01\n:ExemptDomainFileTypePairsFromFileTypeDownloadWarningsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n5ExemptDomainFileTypePairsFromFileTypeDownloadWarnings\x18\x02 \x01(\t\"\x85\x01\n UserAgentClientHintsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bUserAgentClientHintsEnabled\x18\x02 \x01(\x08\"\x87\x01\n!CloudProfileReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudProfileReportingEnabled\x18\x02 \x01(\x08\"u\n\x18\x41udioSandboxEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41udioSandboxEnabled\x18\x02 \x01(\x08\"\x96\x01\n\x17SpellcheckLanguageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12SpellcheckLanguage\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x42lockThirdPartyCookiesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x42lockThirdPartyCookies\x18\x02 \x01(\x08\"i\n\x12\x44iskCacheSizeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDiskCacheSize\x18\x02 \x01(\x03\"\x87\x01\n!NativeWindowOcclusionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNativeWindowOcclusionEnabled\x18\x02 \x01(\x08\"e\n\x10UserDataDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bUserDataDir\x18\x02 \x01(\t\"\x87\x01\n!SavingBrowserHistoryDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSavingBrowserHistoryDisabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x41llowFileSelectionDialogsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41llowFileSelectionDialogs\x18\x02 \x01(\x08\"}\n\x1c\x42\x61\x63kForwardCacheEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42\x61\x63kForwardCacheEnabled\x18\x02 \x01(\x08\"o\n\x15\x43hromeVariationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x43hromeVariations\x18\x02 \x01(\x03\"q\n\x16SideSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SideSearchEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1f\x44\x65veloperToolsAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x44\x65veloperToolsAvailability\x18\x02 \x01(\x03\"y\n\x1a\x43orsLegacyModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43orsLegacyModeEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dSpellCheckServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18SpellCheckServiceEnabled\x18\x02 \x01(\x08\"\xb6\x01\n\'ContextAwareAccessSignalsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12M\n\"ContextAwareAccessSignalsAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"}\n\x1cSSLErrorOverrideAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SSLErrorOverrideAllowed\x18\x02 \x01(\x08\"e\n\x10\x44isableSpdyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x44isableSpdy\x18\x02 \x01(\x08\"i\n\x12LacrosAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rLacrosAllowed\x18\x02 \x01(\x08\"m\n\x14NTPCardsVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fNTPCardsVisible\x18\x02 \x01(\x08\"{\n\x1bWebComponentsV0EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WebComponentsV0Enabled\x18\x02 \x01(\x08\"q\n\x16\x44ownloadDirectoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x44ownloadDirectory\x18\x02 \x01(\t\"{\n\x1b\x46orceEphemeralProfilesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46orceEphemeralProfiles\x18\x02 \x01(\x08\"}\n\x1c\x42rowserAddPersonEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42rowserAddPersonEnabled\x18\x02 \x01(\x08\"c\n\x0fRC4EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nRC4Enabled\x18\x02 \x01(\x08\"k\n\x13InstantEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eInstantEnabled\x18\x02 \x01(\x08\"e\n\x10OsColorModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bOsColorMode\x18\x02 \x01(\t\"\xb4\x01\n&NoteTakingAppsLockScreenWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!NoteTakingAppsLockScreenWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"q\n\x16\x43hromeAppsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x43hromeAppsEnabled\x18\x02 \x01(\x08\"\xa1\x01\n.EnterpriseProfileCreationKeepBrowsingDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)EnterpriseProfileCreationKeepBrowsingData\x18\x02 \x01(\x08\"\x7f\n\x1d\x44\x65sktopSharingHubEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65sktopSharingHubEnabled\x18\x02 \x01(\x08\"\xa2\x01\n\x1dQuickUnlockModeWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18QuickUnlockModeWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14TabUnderAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fTabUnderAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"ChromeCleanupReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43hromeCleanupReportingEnabled\x18\x02 \x01(\x08\"u\n\x18\x43learSiteDataOnExitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43learSiteDataOnExit\x18\x02 \x01(\x08\"\x87\x01\n!DNSInterceptionChecksEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44NSInterceptionChecksEnabled\x18\x02 \x01(\x08\"\x90\x01\n\x14\x44isabledSchemesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x44isabledSchemes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x46loatingWorkspaceV2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x46loatingWorkspaceV2Enabled\x18\x02 \x01(\x08\"\x91\x01\n&SuppressChromeFrameTurndownPromptProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!SuppressChromeFrameTurndownPrompt\x18\x02 \x01(\x08\"}\n\x1c\x45xternalStorageDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45xternalStorageDisabled\x18\x02 \x01(\x08\"\x95\x01\n(BrowserLegacyExtensionPointsBlockedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#BrowserLegacyExtensionPointsBlocked\x18\x02 \x01(\x08\"\x81\x01\n\x1eSignedHTTPExchangeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SignedHTTPExchangeEnabled\x18\x02 \x01(\x08\"\x9d\x01\n,SecurityTokenSessionNotificationSecondsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'SecurityTokenSessionNotificationSeconds\x18\x02 \x01(\x03\"}\n\x1cSuggestedContentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SuggestedContentEnabled\x18\x02 \x01(\x08\"\x9b\x01\n+WebDriverOverridesIncompatiblePoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&WebDriverOverridesIncompatiblePolicies\x18\x02 \x01(\x08\"\x7f\n\x1d\x41llowNativeNotificationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowNativeNotifications\x18\x02 \x01(\x08\"\x8f\x01\n%BrowserNetworkTimeQueriesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n BrowserNetworkTimeQueriesEnabled\x18\x02 \x01(\x08\"\x9a\x01\n\x19HSTSPolicyBypassListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14HSTSPolicyBypassList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fPrefixedStorageInfoEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPrefixedStorageInfoEnabled\x18\x02 \x01(\x08\"{\n\x1b\x41llowDinosaurEasterEggProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41llowDinosaurEasterEgg\x18\x02 \x01(\x08\"\xa4\x01\n\x1e\x45xtensionInstallBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x90\x01\n\x14WebAuthnFactorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0fWebAuthnFactors\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$AccessibilityImageLabelsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41\x63\x63\x65ssibilityImageLabelsEnabled\x18\x02 \x01(\x08\"y\n\x1a\x44ownloadBubbleEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44ownloadBubbleEnabled\x18\x02 \x01(\x08\"\xa7\x01\n1ExternalProtocolDialogShowAlwaysOpenCheckboxProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,ExternalProtocolDialogShowAlwaysOpenCheckbox\x18\x02 \x01(\x08\"\x99\x01\n*InsecurePrivateNetworkRequestsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%InsecurePrivateNetworkRequestsAllowed\x18\x02 \x01(\x08\"\x81\x01\n\x1eHighEfficiencyModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19HighEfficiencyModeEnabled\x18\x02 \x01(\x08\"\xcc\x01\n2KeepFullscreenWithoutNotificationUrlAllowListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12X\n-KeepFullscreenWithoutNotificationUrlAllowList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14\x41llowScreenLockProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41llowScreenLock\x18\x02 \x01(\x08\"s\n\x17ImportSearchEngineProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12ImportSearchEngine\x18\x02 \x01(\x08\"\x96\x01\n\x17\x43orsMitigationListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12\x43orsMitigationList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eThirdPartyBlockingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19ThirdPartyBlockingEnabled\x18\x02 \x01(\x08\"\x9b\x01\n+DisplayCapturePermissionsPolicyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&DisplayCapturePermissionsPolicyEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"WebSQLNonSecureContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWebSQLNonSecureContextEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'EnableSymantecLegacyInfrastructureProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"EnableSymantecLegacyInfrastructure\x18\x02 \x01(\x08\"\xa7\x01\n1RequireOnlineRevocationChecksForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,RequireOnlineRevocationChecksForLocalAnchors\x18\x02 \x01(\x08\"\x89\x01\n\"WebRtcAllowLegacyTLSProtocolsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWebRtcAllowLegacyTLSProtocols\x18\x02 \x01(\x08\"}\n\x1cLensRegionSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17LensRegionSearchEnabled\x18\x02 \x01(\x08\"\xa5\x01\n0ForceMajorVersionToMinorPositionInUserAgentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+ForceMajorVersionToMinorPositionInUserAgent\x18\x02 \x01(\x03\"{\n\x1bRoamingProfileLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RoamingProfileLocation\x18\x02 \x01(\t\"i\n\x12\x43\x45\x43PQ2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rCECPQ2Enabled\x18\x02 \x01(\x08\"\x8d\x01\n$LensCameraAssistedSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fLensCameraAssistedSearchEnabled\x18\x02 \x01(\x08\"\xa4\x01\n\x1e\x45xtensionInstallWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#Http09OnNonDefaultPortsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eHttp09OnNonDefaultPortsEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#SandboxExternalProtocolBlockedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eSandboxExternalProtocolBlocked\x18\x02 \x01(\x08\"{\n\x1bSharedClipboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SharedClipboardEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'CloudManagementEnrollmentMandatoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"CloudManagementEnrollmentMandatory\x18\x02 \x01(\x08\"\x9d\x01\n,EnableCommonNameFallbackForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'EnableCommonNameFallbackForLocalAnchors\x18\x02 \x01(\x08\"\x8f\x01\n%ForceLegacyDefaultReferrerPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ForceLegacyDefaultReferrerPolicy\x18\x02 \x01(\x08\"\x97\x01\n)NewBaseUrlInheritanceBehaviorAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$NewBaseUrlInheritanceBehaviorAllowed\x18\x02 \x01(\x08\"m\n\x14UserAvatarImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fUserAvatarImage\x18\x02 \x01(\t\"\x9d\x01\n,UrlKeyedAnonymizedDataCollectionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'UrlKeyedAnonymizedDataCollectionEnabled\x18\x02 \x01(\x08\"\x95\x01\n(SuggestLogoutAfterClosingLastWindowProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#SuggestLogoutAfterClosingLastWindow\x18\x02 \x01(\x08\"y\n\x1a\x41llowedDomainsForAppsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x41llowedDomainsForApps\x18\x02 \x01(\t\"\x8a\x01\n\x11URLBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x41utofillCreditCardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41utofillCreditCardEnabled\x18\x02 \x01(\x08\"i\n\x12ProxySettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rProxySettings\x18\x02 \x01(\t\"k\n\x13IsolateOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eIsolateOrigins\x18\x02 \x01(\t\"\xa3\x01\n/StrictMimetypeCheckForWorkerScriptsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*StrictMimetypeCheckForWorkerScriptsEnabled\x18\x02 \x01(\x08\"}\n\x1cRestrictSigninToPatternProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17RestrictSigninToPattern\x18\x02 \x01(\t\"\xa3\x01\n/SharedArrayBufferUnrestrictedAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*SharedArrayBufferUnrestrictedAccessAllowed\x18\x02 \x01(\x08\"s\n\x17\x46ullRestoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x46ullRestoreEnabled\x18\x02 \x01(\x08\"w\n\x19\x44\x65skTemplatesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65skTemplatesEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1ePromptForDownloadLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PromptForDownloadLocation\x18\x02 \x01(\x08\"\x83\x01\n\x1fOnPrintEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aOnPrintEnterpriseConnector\x18\x02 \x01(\t\"u\n\x18\x41udioCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41udioCaptureAllowed\x18\x02 \x01(\x08\"\x81\x01\n\x1eIncognitoModeAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19IncognitoModeAvailability\x18\x02 \x01(\x03\"\x8b\x01\n#DeskAPIThirdPartyAccessEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65skAPIThirdPartyAccessEnabled\x18\x02 \x01(\x08\"\xb4\x01\n&SSLErrorOverrideAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!SSLErrorOverrideAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"k\n\x13SitePerProcessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eSitePerProcess\x18\x02 \x01(\x08\"\x9f\x01\n-GaiaLockScreenOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(GaiaLockScreenOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"\x7f\n\x1d\x46loatingWorkspaceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x46loatingWorkspaceEnabled\x18\x02 \x01(\x08\"s\n\x17WebRtcUdpPortRangeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12WebRtcUdpPortRange\x18\x02 \x01(\t\"{\n\x1bRemoteDebuggingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RemoteDebuggingAllowed\x18\x02 \x01(\x08\"\xae\x01\n#PrintingAPIExtensionsWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1ePrintingAPIExtensionsWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14UserDisplayNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fUserDisplayName\x18\x02 \x01(\t\"\x83\x01\n\x1fReportCrostiniUsageEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aReportCrostiniUsageEnabled\x18\x02 \x01(\x08\"\x91\x01\n&OnFileAttachedEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!OnFileAttachedEnterpriseConnector\x18\x02 \x01(\t\"\x8b\x01\n#CACertificateManagementAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x43\x41\x43\x65rtificateManagementAllowed\x18\x02 \x01(\x03\"\xac\x01\n\"ExternalPrintServersWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xternalPrintServersWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa3\x01\n/AmbientAuthenticationInPrivateModesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*AmbientAuthenticationInPrivateModesEnabled\x18\x02 \x01(\x03\"w\n\x19\x46orceYouTubeRestrictProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x46orceYouTubeRestrict\x18\x02 \x01(\x03\"{\n\x1b\x43opyPreventionSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43opyPreventionSettings\x18\x02 \x01(\t\"e\n\x10QuicAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bQuicAllowed\x18\x02 \x01(\x08\"{\n\x1b\x45mojiSuggestionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x45mojiSuggestionEnabled\x18\x02 \x01(\x08\"\x9d\x01\n,DeviceLocalAccountManagedSessionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'DeviceLocalAccountManagedSessionEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%NTPMiddleSlotAnnouncementVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n NTPMiddleSlotAnnouncementVisible\x18\x02 \x01(\x08\"w\n\x19\x41llowOutdatedPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41llowOutdatedPlugins\x18\x02 \x01(\x08\"q\n\x16SpellcheckEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SpellcheckEnabled\x18\x02 \x01(\x08\"\x95\x01\n(ExtensionInstallEventLoggingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#ExtensionInstallEventLoggingEnabled\x18\x02 \x01(\x08\"w\n\x19\x42rowsingDataLifetimeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x42rowsingDataLifetime\x18\x02 \x01(\t\"\x9d\x01\n,CaptivePortalAuthenticationIgnoresProxyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'CaptivePortalAuthenticationIgnoresProxy\x18\x02 \x01(\x08\"\x83\x01\n\x1fNTPCustomBackgroundEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aNTPCustomBackgroundEnabled\x18\x02 \x01(\x08\"{\n\x1bSmartLockSigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SmartLockSigninAllowed\x18\x02 \x01(\x08\"{\n\x1b\x44\x65veloperToolsDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x44\x65veloperToolsDisabled\x18\x02 \x01(\x08\"y\n\x1aWPADQuickCheckEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15WPADQuickCheckEnabled\x18\x02 \x01(\x08\"\x87\x01\n!BatterySaverModeAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x42\x61tterySaverModeAvailability\x18\x02 \x01(\x03\"s\n\x17UserAgentReductionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12UserAgentReduction\x18\x02 \x01(\x03\"o\n\x15HideWebStoreIconProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10HideWebStoreIcon\x18\x02 \x01(\x08\"\x7f\n\x1dInsightsExtensionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18InsightsExtensionEnabled\x18\x02 \x01(\x08\"\x94\x01\n\x16\x41utoplayWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoplayWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"i\n\x12SSLVersionMinProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSSLVersionMin\x18\x02 \x01(\t\"\x8e\x01\n\x13SessionLocalesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0eSessionLocales\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1fRestrictAccountsToPatternsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aRestrictAccountsToPatterns\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eMaxInvalidationFetchDelayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19MaxInvalidationFetchDelay\x18\x02 \x01(\x03\"\xa6\x01\n\x1f\x44\x65skAPIThirdPartyAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x44\x65skAPIThirdPartyAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x99\x01\n*VirtualKeyboardResizesLayoutByDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%VirtualKeyboardResizesLayoutByDefault\x18\x02 \x01(\x08\"g\n\x11WebSQLAccessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cWebSQLAccess\x18\x02 \x01(\x08\"\xca\x01\n1OverrideSecurityRestrictionsOnInsecureOriginProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12W\n,OverrideSecurityRestrictionsOnInsecureOrigin\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#AdsSettingForIntrusiveAdsSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41\x64sSettingForIntrusiveAdsSites\x18\x02 \x01(\x03\"\x7f\n\x1dOpenNetworkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18OpenNetworkConfiguration\x18\x02 \x01(\t\"y\n\x1a\x44nsOverHttpsTemplatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44nsOverHttpsTemplates\x18\x02 \x01(\t\"\xa4\x01\n\x1e\x44isabledPluginsExceptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x44isabledPluginsExceptions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1aUseLegacyFormControlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15UseLegacyFormControls\x18\x02 \x01(\x08\"\x8f\x01\n%DisableSafeBrowsingProceedAnywayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n DisableSafeBrowsingProceedAnyway\x18\x02 \x01(\x08\"\x90\x01\n\x14\x46orcedLanguagesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x46orcedLanguages\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x87\x01\n!DefaultBrowserSettingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultBrowserSettingEnabled\x18\x02 \x01(\x08\"\x91\x01\n&LoginDisplayPasswordButtonEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!LoginDisplayPasswordButtonEnabled\x18\x02 \x01(\x08\"\x85\x01\n AllowDeletingBrowserHistoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowDeletingBrowserHistory\x18\x02 \x01(\x08\"\xa8\x01\n SpellcheckLanguageBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bSpellcheckLanguageBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n TouchVirtualKeyboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bTouchVirtualKeyboardEnabled\x18\x02 \x01(\x08\"\xca\x01\n1InsecurePrivateNetworkRequestsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12W\n,InsecurePrivateNetworkRequestsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18\x41uthServerWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41uthServerWhitelist\x18\x02 \x01(\t\"\x9e\x01\n\x1b\x41utoOpenAllowedForURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x41\n\x16\x41utoOpenAllowedForURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x94\x01\n\x16\x41utoOpenFileTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoOpenFileTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xb8\x01\n(EnableDeprecatedWebPlatformFeaturesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#EnableDeprecatedWebPlatformFeatures\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bVmManagementCliAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16VmManagementCliAllowed\x18\x02 \x01(\x08\"\x97\x01\n)StartupBrowserWindowLaunchSuppressedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$StartupBrowserWindowLaunchSuppressed\x18\x02 \x01(\x08\"\x81\x01\n\x1ePhoneHubCameraRollAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PhoneHubCameraRollAllowed\x18\x02 \x01(\x08\"\x81\x01\n\x1eSigninInterceptionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SigninInterceptionEnabled\x18\x02 \x01(\x08\"\x85\x01\n MediaRecommendationsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bMediaRecommendationsEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#LockScreenMediaPlaybackEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eLockScreenMediaPlaybackEnabled\x18\x02 \x01(\x08\"s\n\x17LacrosAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12LacrosAvailability\x18\x02 \x01(\t\"\x87\x01\n!NetworkServiceSandboxEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNetworkServiceSandboxEnabled\x18\x02 \x01(\x08\"m\n\x14PhoneHubAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fPhoneHubAllowed\x18\x02 \x01(\x08\"s\n\x17GhostWindowEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12GhostWindowEnabled\x18\x02 \x01(\x08\"\xaa\x01\n!SafeBrowsingWhitelistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSafeBrowsingWhitelistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"k\n\x13MediaCacheSizeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eMediaCacheSize\x18\x02 \x01(\x03\"m\n\x14\x41utoFillEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41utoFillEnabled\x18\x02 \x01(\x08\"\xa4\x01\n\x1eWebRtcLocalIpsAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19WebRtcLocalIpsAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"q\n\x16HideWebStorePromoProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11HideWebStorePromo\x18\x02 \x01(\x08\"\x93\x01\n\'OnSecurityEventEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OnSecurityEventEnterpriseConnector\x18\x02 \x01(\t\"}\n\x1c\x42uiltInDnsClientEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42uiltInDnsClientEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$AudioProcessHighPriorityEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41udioProcessHighPriorityEnabled\x18\x02 \x01(\x08\"u\n\x18\x44isablePluginFinderProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x44isablePluginFinder\x18\x02 \x01(\x08\"{\n\x1bHistoryClustersVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16HistoryClustersVisible\x18\x02 \x01(\x08\"s\n\x17SmsMessagesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12SmsMessagesAllowed\x18\x02 \x01(\x08\"\x8a\x01\n\x11URLBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x87\x01\n!ContextualSuggestionsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43ontextualSuggestionsEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x43hromeOsLockOnIdleSuspendProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x43hromeOsLockOnIdleSuspend\x18\x02 \x01(\x08\"\x81\x01\n\x1eSystemFeaturesDisableModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SystemFeaturesDisableMode\x18\x02 \x01(\t\"q\n\x16TermsOfServiceURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11TermsOfServiceURL\x18\x02 \x01(\t\"o\n\x15\x44nsOverHttpsModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44nsOverHttpsMode\x18\x02 \x01(\t\"s\n\x17\x46orceBrowserSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x46orceBrowserSignin\x18\x02 \x01(\x08\"i\n\x12\x42rowserSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rBrowserSignin\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x45nableSha1ForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x45nableSha1ForLocalAnchors\x18\x02 \x01(\x08\"s\n\x17TotalMemoryLimitMbProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12TotalMemoryLimitMb\x18\x02 \x01(\x03\"{\n\x1bImportAutofillFormDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ImportAutofillFormData\x18\x02 \x01(\x08\"{\n\x1b\x41utofillAddressEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41utofillAddressEnabled\x18\x02 \x01(\x08\"\xb4\x01\n&PolicyListMultipleSourceMergeListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!PolicyListMultipleSourceMergeList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa9\x01\n2DefaultSearchProviderContextMenuAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-DefaultSearchProviderContextMenuAccessAllowed\x18\x02 \x01(\x08\"y\n\x1a\x45nterpriseWebStoreURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x45nterpriseWebStoreURL\x18\x02 \x01(\t\"\x8a\x01\n\x11URLAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa8\x01\n NativePrintersBulkBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNativePrintersBulkBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"q\n\x16ScreenTimeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ScreenTimeEnabled\x18\x02 \x01(\x08\"\x87\x01\n!RendererCodeIntegrityEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRendererCodeIntegrityEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1eWarnBeforeQuittingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WarnBeforeQuittingEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fTargetBlankImpliesNoOpenerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aTargetBlankImpliesNoOpener\x18\x02 \x01(\x08\"m\n\x14\x41utoplayAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41utoplayAllowed\x18\x02 \x01(\x08\"\x9b\x01\n+CommandLineFlagSecurityWarningsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&CommandLineFlagSecurityWarningsEnabled\x18\x02 \x01(\x08\"{\n\x1b\x43hromeRootStoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43hromeRootStoreEnabled\x18\x02 \x01(\x08\"q\n\x16PolicyRefreshRateProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11PolicyRefreshRate\x18\x02 \x01(\x03\"\x8f\x01\n%WebSQLInThirdPartyContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n WebSQLInThirdPartyContextEnabled\x18\x02 \x01(\x08\"\xd2\x01\n5CertificateTransparencyEnforcementDisabledForCasProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0CertificateTransparencyEnforcementDisabledForCas\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dNativeMessagingBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x46ullscreenAlertEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46ullscreenAlertEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#LacrosSecondaryProfilesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eLacrosSecondaryProfilesAllowed\x18\x02 \x01(\x08\"w\n\x19\x43loudUserPolicyMergeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x43loudUserPolicyMerge\x18\x02 \x01(\x08\"q\n\x16JavascriptEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11JavascriptEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x41llowSystemNotificationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowSystemNotifications\x18\x02 \x01(\x08\"\xc0\x01\n,PolicyDictionaryMultipleSourceMergeListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12R\n\'PolicyDictionaryMultipleSourceMergeList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$AllowWebAuthnWithBrokenTlsCertsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41llowWebAuthnWithBrokenTlsCerts\x18\x02 \x01(\x08\"m\n\x14\x46orceSafeSearchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x46orceSafeSearch\x18\x02 \x01(\x08\"\x97\x01\n)EnterpriseHardwarePlatformAPIEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$EnterpriseHardwarePlatformAPIEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"ShowAppsShortcutInBookmarkBarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dShowAppsShortcutInBookmarkBar\x18\x02 \x01(\x08\"\x89\x01\n\"ManagedConfigurationPerOriginProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dManagedConfigurationPerOrigin\x18\x02 \x01(\t\"i\n\x12SigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSigninAllowed\x18\x02 \x01(\x08\"q\n\x16TosDialogBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11TosDialogBehavior\x18\x02 \x01(\x03\"\x97\x01\n)StricterMixedContentTreatmentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$StricterMixedContentTreatmentEnabled\x18\x02 \x01(\x08\"\xb4\x01\n&DeviceAttributesAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!DeviceAttributesAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x46orceNetworkInProcessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46orceNetworkInProcess\x18\x02 \x01(\x08\"\x97\x01\n)TLS13HardeningForLocalAnchorsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$TLS13HardeningForLocalAnchorsEnabled\x18\x02 \x01(\x08\"\x97\x01\n)SafeBrowsingForTrustedSourcesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SafeBrowsingForTrustedSourcesEnabled\x18\x02 \x01(\x08\"\xaa\x01\n!SecurityKeyPermitAttestationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSecurityKeyPermitAttestation\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17TabFreezingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12TabFreezingEnabled\x18\x02 \x01(\x08\"m\n\x14ImportBookmarksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fImportBookmarks\x18\x02 \x01(\x08\"\x91\x01\n&OnFileTransferEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!OnFileTransferEnterpriseConnector\x18\x02 \x01(\t\"\x91\x01\n&GloballyScopeHTTPAuthCacheEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!GloballyScopeHTTPAuthCacheEnabled\x18\x02 \x01(\x08\"m\n\x14\x46\x61stPairEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x46\x61stPairEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x41llowChromeDataInBackupsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowChromeDataInBackups\x18\x02 \x01(\x08\"\x8f\x01\n%OriginAgentClusterDefaultEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n OriginAgentClusterDefaultEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x44\x65\x66\x61ultDownloadDirectoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultDownloadDirectory\x18\x02 \x01(\t\"\xa4\x01\n\x1eSystemFeaturesDisableListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19SystemFeaturesDisableList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaf\x01\n5ManagedGuestSessionAutoLaunchNotificationReducedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0ManagedGuestSessionAutoLaunchNotificationReduced\x18\x02 \x01(\x08\"\x85\x01\n LensDesktopNTPSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bLensDesktopNTPSearchEnabled\x18\x02 \x01(\x08\"\x9d\x01\n,UserAgentClientHintsGREASEUpdateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'UserAgentClientHintsGREASEUpdateEnabled\x18\x02 \x01(\x08\"\x95\x01\n(OnFileDownloadedEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#OnFileDownloadedEnterpriseConnector\x18\x02 \x01(\t\"y\n\x1aSSLVersionFallbackMinProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SSLVersionFallbackMin\x18\x02 \x01(\t\"\x8b\x01\n#EnableDeprecatedWebBasedSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nableDeprecatedWebBasedSignin\x18\x02 \x01(\x08\"\x85\x01\n VariationsRestrictParameterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bVariationsRestrictParameter\x18\x02 \x01(\t\"\x8b\x01\n#UsbDetectorNotificationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUsbDetectorNotificationEnabled\x18\x02 \x01(\x08\"\xa3\x01\n/CrossOriginWebAssemblyModuleSharingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*CrossOriginWebAssemblyModuleSharingEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#CloudManagementEnrollmentTokenProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x43loudManagementEnrollmentToken\x18\x02 \x01(\t\"}\n\x1cMetricsReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17MetricsReportingEnabled\x18\x02 \x01(\x08\"u\n\x18ShoppingListEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ShoppingListEnabled\x18\x02 \x01(\x08\"y\n\x1aUrlParamFilterEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15UrlParamFilterEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'OnBulkDataEntryEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OnBulkDataEntryEnterpriseConnector\x18\x02 \x01(\t\"\x8d\x01\n$PhoneHubTaskContinuationAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPhoneHubTaskContinuationAllowed\x18\x02 \x01(\x08\"{\n\x1b\x45nterpriseWebStoreNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x45nterpriseWebStoreName\x18\x02 \x01(\t\"\xd8\x01\n8CoalesceH2ConnectionsWithClientCertificatesForHostsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12^\n3CoalesceH2ConnectionsWithClientCertificatesForHosts\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fPreconfiguredDeskTemplatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPreconfiguredDeskTemplates\x18\x02 \x01(\t\"o\n\x15TripleDESEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10TripleDESEnabled\x18\x02 \x01(\x08\"\x87\x01\n!SuppressUnsupportedOSWarningProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSuppressUnsupportedOSWarning\x18\x02 \x01(\x08\"o\n\x15ManagedBookmarksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ManagedBookmarks\x18\x02 \x01(\t\"\x91\x01\n&BuiltinCertificateVerifierEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!BuiltinCertificateVerifierEnabled\x18\x02 \x01(\x08\"q\n\x16\x46ullscreenAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x46ullscreenAllowed\x18\x02 \x01(\x08\"y\n\x1aLocalDiscoveryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15LocalDiscoveryEnabled\x18\x02 \x01(\x08\"\xa3\x01\n/MachineLevelUserCloudPolicyEnrollmentTokenProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*MachineLevelUserCloudPolicyEnrollmentToken\x18\x02 \x01(\t\"o\n\x15TranslateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10TranslateEnabled\x18\x02 \x01(\x08\"{\n\x1bWifiSyncAndroidAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WifiSyncAndroidAllowed\x18\x02 \x01(\x08\"\x87\x01\n!NTPContentSuggestionsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNTPContentSuggestionsEnabled\x18\x02 \x01(\x08\"}\n\x1cInstantTetheringAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17InstantTetheringAllowed\x18\x02 \x01(\x08\"\x85\x01\n AllowSyncXHRInPageDismissalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowSyncXHRInPageDismissal\x18\x02 \x01(\x08\"\x7f\n\x1dPrimaryMouseButtonSwitchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrimaryMouseButtonSwitch\x18\x02 \x01(\x08\"y\n\x1aRelaunchHeadsUpPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15RelaunchHeadsUpPeriod\x18\x02 \x01(\x03\"y\n\x1a\x42\x61\x63kgroundModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x42\x61\x63kgroundModeEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dShowFullUrlsInAddressBarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18ShowFullUrlsInAddressBar\x18\x02 \x01(\x08\"y\n\x1a\x46orceGoogleSafeSearchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46orceGoogleSafeSearch\x18\x02 \x01(\x08\"\xa2\x01\n\x1dNativeMessagingWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1f\x45nableExperimentalPoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x45nableExperimentalPolicies\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"k\n\x13KeyPermissionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eKeyPermissions\x18\x02 \x01(\t\"\x8d\x01\n$UnthrottledNestedTimeoutEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fUnthrottledNestedTimeoutEnabled\x18\x02 \x01(\x08\"{\n\x1bWebAppInstallForceListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WebAppInstallForceList\x18\x02 \x01(\t\"}\n\x1c\x41lwaysOpenPdfExternallyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41lwaysOpenPdfExternally\x18\x02 \x01(\x08\"\x92\x01\n\x15\x41llowedLanguagesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10\x41llowedLanguages\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x94\x01\n\x16\x41utoplayAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoplayAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa3\x01\n/SendMouseEventsDisabledFormControlsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*SendMouseEventsDisabledFormControlsEnabled\x18\x02 \x01(\x08\"\xa0\x01\n\x1cTabDiscardingExceptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17TabDiscardingExceptions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa5\x01\n0ThrottleNonVisibleCrossOriginIframesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+ThrottleNonVisibleCrossOriginIframesAllowed\x18\x02 \x01(\x08\"{\n\x1bWindowOcclusionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WindowOcclusionEnabled\x18\x02 \x01(\x08\"{\n\x1bRunAllFlashInAllowModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RunAllFlashInAllowMode\x18\x02 \x01(\x08\"o\n\x15\x45ventPathEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x45ventPathEnabled\x18\x02 \x01(\x08\"c\n\x0f\x44HEEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nDHEEnabled\x18\x02 \x01(\x08\"y\n\x1aPdfAnnotationsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15PdfAnnotationsEnabled\x18\x02 \x01(\x08\"g\n\x11HeadlessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cHeadlessMode\x18\x02 \x01(\x03\"\x7f\n\x1dLoadCryptoTokenExtensionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18LoadCryptoTokenExtension\x18\x02 \x01(\x08\"q\n\x16\x45nableSyncConsentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45nableSyncConsent\x18\x02 \x01(\x08\"}\n\x1c\x42rowserGuestModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42rowserGuestModeEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x44isableSSLRecordSplittingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44isableSSLRecordSplitting\x18\x02 \x01(\x08\"\xa3\x01\n/CloudUserPolicyOverridesCloudMachinePolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*CloudUserPolicyOverridesCloudMachinePolicy\x18\x02 \x01(\x08\"}\n\x1cSafeSitesFilterBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SafeSitesFilterBehavior\x18\x02 \x01(\x03\"\x8b\x01\n#UserDataSnapshotRetentionLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUserDataSnapshotRetentionLimit\x18\x02 \x01(\x03\"\x7f\n\x1dU2fSecurityKeyApiEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18U2fSecurityKeyApiEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'ClientCertificateManagementAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"ClientCertificateManagementAllowed\x18\x02 \x01(\x03\"s\n\x17\x41udioOutputAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x41udioOutputAllowed\x18\x02 \x01(\x08\"\x98\x01\n\x18\x41llowedInputMethodsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n\x13\x41llowedInputMethods\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9d\x01\n,FetchKeepaliveDurationSecondsOnShutdownProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'FetchKeepaliveDurationSecondsOnShutdown\x18\x02 \x01(\x03\"\x83\x01\n\x1fRelaunchNotificationPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aRelaunchNotificationPeriod\x18\x02 \x01(\x03\"w\n\x19\x43hromeCleanupEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x43hromeCleanupEnabled\x18\x02 \x01(\x08\"o\n\x15WebRtcIPHandlingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10WebRtcIPHandling\x18\x02 \x01(\t\"\x7f\n\x1dNetworkPredictionOptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NetworkPredictionOptions\x18\x02 \x01(\x03\"w\n\x19ImportSavedPasswordsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14ImportSavedPasswords\x18\x02 \x01(\x08\"\x99\x01\n*ForceLogoutUnauthenticatedUserEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%ForceLogoutUnauthenticatedUserEnabled\x18\x02 \x01(\x08\"{\n\x1bPromotionalTabsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PromotionalTabsEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'ProfilePickerOnStartupAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"ProfilePickerOnStartupAvailability\x18\x02 \x01(\x03\"}\n\x1c\x46orceMaximizeOnFirstRunProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x46orceMaximizeOnFirstRun\x18\x02 \x01(\x08\"\xa8\x01\n NativePrintersBulkWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNativePrintersBulkWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"e\n\x10\x45\x63heAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x45\x63heAllowed\x18\x02 \x01(\x08\"\x93\x01\n\'DataLeakPreventionReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DataLeakPreventionReportingEnabled\x18\x02 \x01(\x08\"\x85\x01\n AllowPopupsDuringPageUnloadProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowPopupsDuringPageUnload\x18\x02 \x01(\x08\"i\n\x12ImportHistoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rImportHistory\x18\x02 \x01(\x08\"\xa1\x01\n.SafeBrowsingExtendedReportingOptInAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)SafeBrowsingExtendedReportingOptInAllowed\x18\x02 \x01(\x08\"y\n\x1aIsolateOriginsAndroidProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15IsolateOriginsAndroid\x18\x02 \x01(\t\"\xa8\x01\n ClearBrowsingDataOnExitListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1b\x43learBrowsingDataOnExitList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x45\x63ryptfsMigrationStrategyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x45\x63ryptfsMigrationStrategy\x18\x02 \x01(\x03\"w\n\x19PrivacyScreenEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrivacyScreenEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1f\x41\x64\x64itionalLaunchParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41\x64\x64itionalLaunchParameters\x18\x02 \x01(\t\"q\n\x16SkipMetadataCheckProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SkipMetadataCheck\x18\x02 \x01(\x08\"\xa0\x01\n\x1cRenderInChromeFrameListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17RenderInChromeFrameList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x92\x01\n\x15RenderInHostListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10RenderInHostList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n ChromeFrameRendererSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x43hromeFrameRendererSettings\x18\x02 \x01(\x03\"\x87\x01\n!NetBiosShareDiscoveryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNetBiosShareDiscoveryEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dNetworkFileSharesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NetworkFileSharesAllowed\x18\x02 \x01(\x08\"\x97\x01\n)NetworkFileSharesPreconfiguredSharesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$NetworkFileSharesPreconfiguredShares\x18\x02 \x01(\t\"\x8b\x01\n#NTLMShareAuthenticationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eNTLMShareAuthenticationEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"ScreenCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dScreenCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1fTabCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aTabCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19ScreenCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14ScreenCaptureAllowed\x18\x02 \x01(\x08\"\xac\x01\n\"WindowCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xba\x01\n)SameOriginTabCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12O\n$SameOriginTabCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#ArcBackupRestoreServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41rcBackupRestoreServiceEnabled\x18\x02 \x01(\x03\"c\n\x0f\x41rcEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nArcEnabled\x18\x02 \x01(\x08\"}\n\x1c\x41rcCertificatesSyncModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41rcCertificatesSyncMode\x18\x02 \x01(\x03\"\x87\x01\n!ArcAppToWebAppSharingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x41rcAppToWebAppSharingEnabled\x18\x02 \x01(\x08\"\x91\x01\n&AppRecommendationZeroStateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!AppRecommendationZeroStateEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x41rcLocationServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41rcLocationServiceEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ArcGoogleLocationServicesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ArcGoogleLocationServicesEnabled\x18\x02 \x01(\x03\"\x8f\x01\n%ArcAppInstallEventLoggingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ArcAppInstallEventLoggingEnabled\x18\x02 \x01(\x08\"}\n\x1c\x41rcBackupRestoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41rcBackupRestoreEnabled\x18\x02 \x01(\x08\"a\n\x0e\x41rcPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x11\n\tArcPolicy\x18\x02 \x01(\t\"\xab\x03\n\x17\x43hromeSettingsSubProto1\x12p\n%ShowCastSessionsStartedByOtherDevices\x18\x02 \x01(\x0b\x32\x41.enterprise_management.ShowCastSessionsStartedByOtherDevicesProto\x12J\n\x12\x43loudAPAuthEnabled\x18\x03 \x01(\x0b\x32..enterprise_management.CloudAPAuthEnabledProto\x12n\n$NewBaseUrlInheritanceBehaviorAllowed\x18\x01 \x01(\x0b\x32@.enterprise_management.NewBaseUrlInheritanceBehaviorAllowedProto\x12\x62\n\x1eUsbDetectorNotificationEnabled\x18\x04 \x01(\x0b\x32:.enterprise_management.UsbDetectorNotificationEnabledProto\"\xb6\xbb\x04\n\x13\x43hromeSettingsProto\x12[\n\x1a\x43\x61lendarIntegrationEnabled\x18\xf9\x07 \x01(\x0b\x32\x36.enterprise_management.CalendarIntegrationEnabledProto\x12S\n\x16\x42rowserSwitcherEnabled\x18\x87\x04 \x01(\x0b\x32\x32.enterprise_management.BrowserSwitcherEnabledProto\x12[\n\x1a\x42rowserSwitcherUrlGreylist\x18\xf3\x03 \x01(\x0b\x32\x36.enterprise_management.BrowserSwitcherUrlGreylistProto\x12[\n\x1a\x42rowserSwitcherParsingMode\x18\xe4\x06 \x01(\x0b\x32\x36.enterprise_management.BrowserSwitcherParsingModeProto\x12O\n\x14\x42rowserSwitcherDelay\x18\x8e\x04 \x01(\x0b\x32\x30.enterprise_management.BrowserSwitcherDelayProto\x12_\n\x1c\x42rowserSwitcherUseIeSitelist\x18\xf4\x03 \x01(\x0b\x32\x38.enterprise_management.BrowserSwitcherUseIeSitelistProto\x12k\n\"BrowserSwitcherExternalGreylistUrl\x18\xb6\x04 \x01(\x0b\x32>.enterprise_management.BrowserSwitcherExternalGreylistUrlProto\x12Y\n\x19\x42rowserSwitcherChromePath\x18\x94\x04 \x01(\x0b\x32\x35.enterprise_management.BrowserSwitcherChromePathProto\x12g\n BrowserSwitcherKeepLastChromeTab\x18\x89\x04 \x01(\x0b\x32<.enterprise_management.BrowserSwitcherKeepLastChromeTabProto\x12S\n\x16\x41lternativeBrowserPath\x18\xf0\x03 \x01(\x0b\x32\x32.enterprise_management.AlternativeBrowserPathProto\x12S\n\x16\x42rowserSwitcherUrlList\x18\xf2\x03 \x01(\x0b\x32\x32.enterprise_management.BrowserSwitcherUrlListProto\x12_\n\x1c\x41lternativeBrowserParameters\x18\xf1\x03 \x01(\x0b\x32\x38.enterprise_management.AlternativeBrowserParametersProto\x12k\n\"BrowserSwitcherExternalSitelistUrl\x18\x81\x04 \x01(\x0b\x32>.enterprise_management.BrowserSwitcherExternalSitelistUrlProto\x12\x65\n\x1f\x42rowserSwitcherChromeParameters\x18\x95\x04 \x01(\x0b\x32;.enterprise_management.BrowserSwitcherChromeParametersProto\x12Q\n\x15\x46irstPartySetsEnabled\x18\xb6\x07 \x01(\x0b\x32\x31.enterprise_management.FirstPartySetsEnabledProto\x12U\n\x17\x46irstPartySetsOverrides\x18\xcb\x07 \x01(\x0b\x32\x33.enterprise_management.FirstPartySetsOverridesProto\x12\x63\n\x1e\x41uthNegotiateDelegateAllowlist\x18\xec\x05 \x01(\x0b\x32:.enterprise_management.AuthNegotiateDelegateAllowlistProto\x12\x41\n\rNtlmV2Enabled\x18\x8b\x03 \x01(\x0b\x32).enterprise_management.NtlmV2EnabledProto\x12m\n#AllHttpAuthSchemesAllowedForOrigins\x18\xb8\x07 \x01(\x0b\x32?.enterprise_management.AllHttpAuthSchemesAllowedForOriginsProto\x12Z\n\x1a\x41llowCrossOriginAuthPrompt\x18[ \x01(\x0b\x32\x36.enterprise_management.AllowCrossOriginAuthPromptProto\x12g\n AuthNegotiateDelegateByKdcPolicy\x18\x92\x04 \x01(\x0b\x32<.enterprise_management.AuthNegotiateDelegateByKdcPolicyProto\x12\x64\n\x1f\x44isableAuthNegotiateCnameLookup\x18\x1d \x01(\x0b\x32;.enterprise_management.DisableAuthNegotiateCnameLookupProto\x12k\n\"IntegratedWebAuthenticationAllowed\x18\xaa\x06 \x01(\x0b\x32>.enterprise_management.IntegratedWebAuthenticationAllowedProto\x12M\n\x13\x41uthServerAllowlist\x18\xed\x05 \x01(\x0b\x32/.enterprise_management.AuthServerAllowlistProto\x12T\n\x17\x45nableAuthNegotiatePort\x18\x1e \x01(\x0b\x32\x33.enterprise_management.EnableAuthNegotiatePortProto\x12<\n\x0b\x41uthSchemes\x18\x1c \x01(\x0b\x32\'.enterprise_management.AuthSchemesProto\x12\x65\n\x1f\x41uthAndroidNegotiateAccountType\x18\xb3\x02 \x01(\x0b\x32;.enterprise_management.AuthAndroidNegotiateAccountTypeProto\x12H\n\x11GSSAPILibraryName\x18! \x01(\x0b\x32-.enterprise_management.GSSAPILibraryNameProto\x12W\n\x18\x42\x61sicAuthOverHttpEnabled\x18\xa8\x06 \x01(\x0b\x32\x34.enterprise_management.BasicAuthOverHttpEnabledProto\x12<\n\x0bProxyServer\x18\x19 \x01(\x0b\x32\'.enterprise_management.ProxyServerProto\x12\x38\n\tProxyMode\x18\x17 \x01(\x0b\x32%.enterprise_management.ProxyModeProto\x12\x44\n\x0fProxyBypassList\x18\x1b \x01(\x0b\x32+.enterprise_management.ProxyBypassListProto\x12\x44\n\x0fProxyServerMode\x18\x18 \x01(\x0b\x32+.enterprise_management.ProxyServerModeProto\x12<\n\x0bProxyPacUrl\x18\x1a \x01(\x0b\x32\'.enterprise_management.ProxyPacUrlProto\x12w\n(SamlPasswordExpirationAdvanceWarningDays\x18\xad\x04 \x01(\x0b\x32\x44.enterprise_management.SamlPasswordExpirationAdvanceWarningDaysProto\x12[\n\x1aSAMLOfflineSigninTimeLimit\x18\x80\x02 \x01(\x0b\x32\x36.enterprise_management.SAMLOfflineSigninTimeLimitProto\x12i\n!LockScreenReauthenticationEnabled\x18\xd1\x05 \x01(\x0b\x32=.enterprise_management.LockScreenReauthenticationEnabledProto\x12k\n\"SamlInSessionPasswordChangeEnabled\x18\xa3\x04 \x01(\x0b\x32>.enterprise_management.SamlInSessionPasswordChangeEnabledProto\x12S\n\x16ReportArcStatusEnabled\x18\xdf\x02 \x01(\x0b\x32\x32.enterprise_management.ReportArcStatusEnabledProto\x12G\n\x10ProjectorEnabled\x18\xa9\x07 \x01(\x0b\x32,.enterprise_management.ProjectorEnabledProto\x12o\n$ProjectorDogfoodForFamilyLinkEnabled\x18\xd6\x07 \x01(\x0b\x32@.enterprise_management.ProjectorDogfoodForFamilyLinkEnabledProto\x12\x63\n\x1eReportExtensionsAndPluginsData\x18\xf5\x03 \x01(\x0b\x32:.enterprise_management.ReportExtensionsAndPluginsDataProto\x12G\n\x10ReportPolicyData\x18\xd9\x03 \x01(\x0b\x32,.enterprise_management.ReportPolicyDataProto\x12I\n\x11ReportVersionData\x18\xd8\x03 \x01(\x0b\x32-.enterprise_management.ReportVersionDataProto\x12S\n\x16ReportSafeBrowsingData\x18\xf6\x03 \x01(\x0b\x32\x32.enterprise_management.ReportSafeBrowsingDataProto\x12\x61\n\x1d\x43loudReportingUploadFrequency\x18\xc4\x07 \x01(\x0b\x32\x39.enterprise_management.CloudReportingUploadFrequencyProto\x12G\n\x10ReportUserIDData\x18\xdb\x03 \x01(\x0b\x32,.enterprise_management.ReportUserIDDataProto\x12Q\n\x15\x43loudReportingEnabled\x18\xef\x03 \x01(\x0b\x32\x31.enterprise_management.CloudReportingEnabledProto\x12_\n\x1c\x43loudExtensionRequestEnabled\x18\xe2\x04 \x01(\x0b\x32\x38.enterprise_management.CloudExtensionRequestEnabledProto\x12M\n\x13ReportMachineIDData\x18\xda\x03 \x01(\x0b\x32/.enterprise_management.ReportMachineIDDataProto\x12G\n\x10\x44nsOverHttpsSalt\x18\x8c\x08 \x01(\x0b\x32,.enterprise_management.DnsOverHttpsSaltProto\x12o\n$DnsOverHttpsTemplatesWithIdentifiers\x18\x8d\x08 \x01(\x0b\x32@.enterprise_management.DnsOverHttpsTemplatesWithIdentifiersProto\x12\x93\x01\n6AccessControlAllowMethodsInCORSPreflightSpecConformant\x18\x86\x08 \x01(\x0b\x32R.enterprise_management.AccessControlAllowMethodsInCORSPreflightSpecConformantProto\x12\x41\n\rDriveDisabled\x18\x8d\x01 \x01(\x0b\x32).enterprise_management.DriveDisabledProto\x12Y\n\x19\x44riveDisabledOverCellular\x18\x8e\x01 \x01(\x0b\x32\x35.enterprise_management.DriveDisabledOverCellularProto\x12[\n\x1aPrintingAllowedDuplexModes\x18\xdd\x03 \x01(\x0b\x32\x36.enterprise_management.PrintingAllowedDuplexModesProto\x12\x65\n\x1fNativePrintersBulkConfiguration\x18\x80\x03 \x01(\x0b\x32;.enterprise_management.NativePrintersBulkConfigurationProto\x12T\n\x17\x43loudPrintSubmitEnabled\x18o \x01(\x0b\x32\x33.enterprise_management.CloudPrintSubmitEnabledProto\x12O\n\x14PrintingColorDefault\x18\xdf\x03 \x01(\x0b\x32\x30.enterprise_management.PrintingColorDefaultProto\x12L\n\x13\x44isablePrintPreview\x18w \x01(\x0b\x32/.enterprise_management.DisablePrintPreviewProto\x12U\n\x17\x44\x65\x66\x61ultPrinterSelection\x18\xb6\x02 \x01(\x0b\x32\x33.enterprise_management.DefaultPrinterSelectionProto\x12R\n\x16\x43loudPrintProxyEnabled\x18\x0f \x01(\x0b\x32\x32.enterprise_management.CloudPrintProxyEnabledProto\x12\x61\n\x1d\x45xternalPrintServersAllowlist\x18\xf0\x05 \x01(\x0b\x32\x39.enterprise_management.ExternalPrintServersAllowlistProto\x12\x37\n\x08Printers\x18\x83\x06 \x01(\x0b\x32$.enterprise_management.PrintersProto\x12M\n\x13UserPrintersAllowed\x18\x82\x06 \x01(\x0b\x32/.enterprise_management.UserPrintersAllowedProto\x12W\n\x18PrintingPaperSizeDefault\x18\xe1\x03 \x01(\x0b\x32\x34.enterprise_management.PrintingPaperSizeDefaultProto\x12K\n\x12PrintingPinDefault\x18\x90\x04 \x01(\x0b\x32..enterprise_management.PrintingPinDefaultProto\x12_\n\x1c\x43loudPrintWarningsSuppressed\x18\x8f\x06 \x01(\x0b\x32\x38.enterprise_management.CloudPrintWarningsSuppressedProto\x12M\n\x13PrinterTypeDenyList\x18\x89\x05 \x01(\x0b\x32/.enterprise_management.PrinterTypeDenyListProto\x12s\n&PrintingSendUsernameAndFilenameEnabled\x18\xfc\x03 \x01(\x0b\x32\x42.enterprise_management.PrintingSendUsernameAndFilenameEnabledProto\x12W\n\x18PrintingMaxSheetsAllowed\x18\xb6\x05 \x01(\x0b\x32\x34.enterprise_management.PrintingMaxSheetsAllowedProto\x12i\n!PrintingBackgroundGraphicsDefault\x18\xf0\x04 \x01(\x0b\x32=.enterprise_management.PrintingBackgroundGraphicsDefaultProto\x12S\n\x16PrintersBulkAccessMode\x18\x86\x06 \x01(\x0b\x32\x32.enterprise_management.PrintersBulkAccessModeProto\x12O\n\x14PrintRasterizePdfDpi\x18\xfc\x06 \x01(\x0b\x32\x30.enterprise_management.PrintRasterizePdfDpiProto\x12U\n\x17PrintingAllowedPinModes\x18\x8f\x04 \x01(\x0b\x32\x33.enterprise_management.PrintingAllowedPinModesProto\x12Y\n\x19PrintersBulkConfiguration\x18\x84\x06 \x01(\x0b\x32\x35.enterprise_management.PrintersBulkConfigurationProto\x12O\n\x14\x45xternalPrintServers\x18\xbe\x04 \x01(\x0b\x32\x30.enterprise_management.ExternalPrintServersProto\x12\x63\n\x1ePrintingAPIExtensionsAllowlist\x18\x91\x06 \x01(\x0b\x32:.enterprise_management.PrintingAPIExtensionsAllowlistProto\x12Y\n\x19PrintingAllowedColorModes\x18\xdc\x03 \x01(\x0b\x32\x35.enterprise_management.PrintingAllowedColorModesProto\x12Q\n\x15PrintersBulkAllowlist\x18\x8e\x06 \x01(\x0b\x32\x31.enterprise_management.PrintersBulkAllowlistProto\x12M\n\x13PrintPostScriptMode\x18\x81\x07 \x01(\x0b\x32/.enterprise_management.PrintPostScriptModeProto\x12S\n\x16PrintPdfAsImageDefault\x18\x82\x07 \x01(\x0b\x32\x32.enterprise_management.PrintPdfAsImageDefaultProto\x12I\n\x11PrintHeaderFooter\x18\xe2\x03 \x01(\x0b\x32-.enterprise_management.PrintHeaderFooterProto\x12Q\n\x15PrintingDuplexDefault\x18\xe0\x03 \x01(\x0b\x32\x31.enterprise_management.PrintingDuplexDefaultProto\x12]\n\x1bPrintPdfAsImageAvailability\x18\xfb\x06 \x01(\x0b\x32\x37.enterprise_management.PrintPdfAsImageAvailabilityProto\x12_\n\x1cNativePrintersBulkAccessMode\x18\x81\x03 \x01(\x0b\x32\x38.enterprise_management.NativePrintersBulkAccessModeProto\x12\x65\n\x1fPrintJobHistoryExpirationPeriod\x18\xf3\x04 \x01(\x0b\x32;.enterprise_management.PrintJobHistoryExpirationPeriodProto\x12Q\n\x15PrintersBulkBlocklist\x18\x8d\x06 \x01(\x0b\x32\x31.enterprise_management.PrintersBulkBlocklistProto\x12\x43\n\x0eNativePrinters\x18\xe0\x02 \x01(\x0b\x32*.enterprise_management.NativePrintersProto\x12S\n\x16PrintRasterizationMode\x18\xc4\x05 \x01(\x0b\x32\x32.enterprise_management.PrintRasterizationModeProto\x12\x44\n\x0fPrintingEnabled\x18\x0e \x01(\x0b\x32+.enterprise_management.PrintingEnabledProto\x12Y\n\x19UserNativePrintersAllowed\x18\xb3\x03 \x01(\x0b\x32\x35.enterprise_management.UserNativePrintersAllowedProto\x12s\n&PrintingAllowedBackgroundGraphicsModes\x18\xef\x04 \x01(\x0b\x32\x42.enterprise_management.PrintingAllowedBackgroundGraphicsModesProto\x12_\n\x1c\x44\x65letePrintJobHistoryAllowed\x18\xd2\x05 \x01(\x0b\x32\x38.enterprise_management.DeletePrintJobHistoryAllowedProto\x12m\n#PrintPreviewUseSystemDefaultPrinter\x18\xf7\x02 \x01(\x0b\x32?.enterprise_management.PrintPreviewUseSystemDefaultPrinterProto\x12M\n\x13UserBorealisAllowed\x18\xc1\x06 \x01(\x0b\x32/.enterprise_management.UserBorealisAllowedProto\x12\x62\n\x1e\x44\x65\x66\x61ultSearchProviderSearchURL\x18- \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderSearchURLProto\x12\x83\x01\n.DefaultSearchProviderSearchTermsReplacementKey\x18\xad\x01 \x01(\x0b\x32J.enterprise_management.DefaultSearchProviderSearchTermsReplacementKeyProto\x12w\n(DefaultSearchProviderSearchURLPostParams\x18\xe8\x01 \x01(\x0b\x32\x44.enterprise_management.DefaultSearchProviderSearchURLPostParamsProto\x12u\n\'DefaultSearchProviderImageURLPostParams\x18\xeb\x01 \x01(\x0b\x32\x43.enterprise_management.DefaultSearchProviderImageURLPostParamsProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderIconURL\x18\x30 \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderIconURLProto\x12\x61\n\x1d\x44\x65\x66\x61ultSearchProviderImageURL\x18\xe7\x01 \x01(\x0b\x32\x39.enterprise_management.DefaultSearchProviderImageURLProto\x12y\n)DefaultSearchProviderInstantURLPostParams\x18\xea\x01 \x01(\x0b\x32\x45.enterprise_management.DefaultSearchProviderInstantURLPostParamsProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderKeyword\x18, \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderKeywordProto\x12X\n\x19\x44\x65\x66\x61ultSearchProviderName\x18+ \x01(\x0b\x32\x35.enterprise_management.DefaultSearchProviderNameProto\x12\x64\n\x1f\x44\x65\x66\x61ultSearchProviderSuggestURL\x18. \x01(\x0b\x32;.enterprise_management.DefaultSearchProviderSuggestURLProto\x12k\n\"DefaultSearchProviderAlternateURLs\x18\xa3\x01 \x01(\x0b\x32>.enterprise_management.DefaultSearchProviderAlternateURLsProto\x12\x62\n\x1e\x44\x65\x66\x61ultSearchProviderEncodings\x18\x31 \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderEncodingsProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderEnabled\x18* \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderEnabledProto\x12y\n)DefaultSearchProviderSuggestURLPostParams\x18\xe9\x01 \x01(\x0b\x32\x45.enterprise_management.DefaultSearchProviderSuggestURLPostParamsProto\x12\x63\n\x1e\x44\x65\x66\x61ultSearchProviderNewTabURL\x18\xef\x01 \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderNewTabURLProto\x12\x64\n\x1f\x44\x65\x66\x61ultSearchProviderInstantURL\x18/ \x01(\x0b\x32;.enterprise_management.DefaultSearchProviderInstantURLProto\x12\x63\n\x1eGaiaOfflineSigninTimeLimitDays\x18\xb7\x06 \x01(\x0b\x32:.enterprise_management.GaiaOfflineSigninTimeLimitDaysProto\x12N\n\x14HomepageIsNewTabPage\x18\x04 \x01(\x0b\x32\x30.enterprise_management.HomepageIsNewTabPageProto\x12K\n\x12NewTabPageLocation\x18\xea\x02 \x01(\x0b\x32..enterprise_management.NewTabPageLocationProto\x12N\n\x14RestoreOnStartupURLs\x18( \x01(\x0b\x32\x30.enterprise_management.RestoreOnStartupURLsProto\x12\x46\n\x10HomepageLocation\x18\x03 \x01(\x0b\x32,.enterprise_management.HomepageLocationProto\x12\x46\n\x10RestoreOnStartup\x18\' \x01(\x0b\x32,.enterprise_management.RestoreOnStartupProto\x12\x42\n\x0eShowHomeButton\x18% \x01(\x0b\x32*.enterprise_management.ShowHomeButtonProto\x12K\n\x12IdleTimeoutActions\x18\x8e\x08 \x01(\x0b\x32..enterprise_management.IdleTimeoutActionsProto\x12=\n\x0bIdleTimeout\x18\xe4\x07 \x01(\x0b\x32\'.enterprise_management.IdleTimeoutProto\x12\x61\n\x1dNativeMessagingUserLevelHosts\x18\xff\x01 \x01(\x0b\x32\x39.enterprise_management.NativeMessagingUserLevelHostsProto\x12W\n\x18NativeMessagingBlocklist\x18\xea\x05 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingBlocklistProto\x12W\n\x18NativeMessagingAllowlist\x18\xeb\x05 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingAllowlistProto\x12\x65\n\x1fUserActivityScreenDimDelayScale\x18\xd4\x01 \x01(\x0b\x32;.enterprise_management.UserActivityScreenDimDelayScaleProto\x12G\n\x10IdleDelayBattery\x18\xb5\x01 \x01(\x0b\x32,.enterprise_management.IdleDelayBatteryProto\x12;\n\nIdleAction\x18\xb6\x01 \x01(\x0b\x32&.enterprise_management.IdleActionProto\x12g\n PowerManagementUsesVideoActivity\x18\xb9\x01 \x01(\x0b\x32<.enterprise_management.PowerManagementUsesVideoActivityProto\x12G\n\x10ScreenDimDelayAC\x18\xae\x01 \x01(\x0b\x32,.enterprise_management.ScreenDimDelayACProto\x12O\n\x14\x41llowScreenWakeLocks\x18\xcd\x01 \x01(\x0b\x32\x30.enterprise_management.AllowScreenWakeLocksProto\x12[\n\x1aPresentationIdleDelayScale\x18\xba\x01 \x01(\x0b\x32\x36.enterprise_management.PresentationIdleDelayScaleProto\x12\x43\n\x0eLidCloseAction\x18\xb7\x01 \x01(\x0b\x32*.enterprise_management.LidCloseActionProto\x12\x43\n\x0e\x41llowWakeLocks\x18\xed\x03 \x01(\x0b\x32*.enterprise_management.AllowWakeLocksProto\x12O\n\x14PowerSmartDimEnabled\x18\xd3\x03 \x01(\x0b\x32\x30.enterprise_management.PowerSmartDimEnabledProto\x12Q\n\x15ScreenOffDelayBattery\x18\xb3\x01 \x01(\x0b\x32\x31.enterprise_management.ScreenOffDelayBatteryProto\x12\x65\n\x1fPresentationScreenDimDelayScale\x18\xde\x01 \x01(\x0b\x32;.enterprise_management.PresentationScreenDimDelayScaleProto\x12K\n\x12IdleWarningDelayAC\x18\xc7\x01 \x01(\x0b\x32..enterprise_management.IdleWarningDelayACProto\x12Q\n\x15ScreenDimDelayBattery\x18\xb2\x01 \x01(\x0b\x32\x31.enterprise_management.ScreenDimDelayBatteryProto\x12g\n PowerManagementUsesAudioActivity\x18\xb8\x01 \x01(\x0b\x32<.enterprise_management.PowerManagementUsesAudioActivityProto\x12=\n\x0bIdleDelayAC\x18\xb1\x01 \x01(\x0b\x32\'.enterprise_management.IdleDelayACProto\x12]\n\x1bPowerManagementIdleSettings\x18\x84\x02 \x01(\x0b\x32\x37.enterprise_management.PowerManagementIdleSettingsProto\x12I\n\x11ScreenLockDelayAC\x18\xb0\x01 \x01(\x0b\x32-.enterprise_management.ScreenLockDelayACProto\x12I\n\x11IdleActionBattery\x18\xe0\x01 \x01(\x0b\x32-.enterprise_management.IdleActionBatteryProto\x12k\n\"DevicePowerAdaptiveChargingEnabled\x18\xcd\x07 \x01(\x0b\x32>.enterprise_management.DevicePowerAdaptiveChargingEnabledProto\x12G\n\x10ScreenLockDelays\x18\x85\x02 \x01(\x0b\x32,.enterprise_management.ScreenLockDelaysProto\x12G\n\x10ScreenOffDelayAC\x18\xaf\x01 \x01(\x0b\x32,.enterprise_management.ScreenOffDelayACProto\x12?\n\x0cIdleActionAC\x18\xe4\x01 \x01(\x0b\x32(.enterprise_management.IdleActionACProto\x12U\n\x17ScreenBrightnessPercent\x18\xee\x03 \x01(\x0b\x32\x33.enterprise_management.ScreenBrightnessPercentProto\x12U\n\x17IdleWarningDelayBattery\x18\xc8\x01 \x01(\x0b\x32\x33.enterprise_management.IdleWarningDelayBatteryProto\x12S\n\x16ScreenLockDelayBattery\x18\xb4\x01 \x01(\x0b\x32\x32.enterprise_management.ScreenLockDelayBatteryProto\x12[\n\x1aWaitForInitialUserActivity\x18\xf9\x01 \x01(\x0b\x32\x36.enterprise_management.WaitForInitialUserActivityProto\x12O\n\x14KeygenAllowedForUrls\x18\xbc\x02 \x01(\x0b\x32\x30.enterprise_management.KeygenAllowedForUrlsProto\x12\x61\n\x1d\x44\x65\x66\x61ultInsecureContentSetting\x18\xfb\x04 \x01(\x0b\x32\x39.enterprise_management.DefaultInsecureContentSettingProto\x12Q\n\x15SensorsBlockedForUrls\x18\xf6\x05 \x01(\x0b\x32\x31.enterprise_management.SensorsBlockedForUrlsProto\x12m\n#PdfLocalFileAccessAllowedForDomains\x18\x90\x08 \x01(\x0b\x32?.enterprise_management.PdfLocalFileAccessAllowedForDomainsProto\x12W\n\x18\x44\x65\x66\x61ultLocalFontsSetting\x18\xd3\x07 \x01(\x0b\x32\x34.enterprise_management.DefaultLocalFontsSettingProto\x12N\n\x14PopupsBlockedForUrls\x18N \x01(\x0b\x32\x30.enterprise_management.PopupsBlockedForUrlsProto\x12W\n\x18\x46ileSystemReadAskForUrls\x18\x89\x06 \x01(\x0b\x32\x34.enterprise_management.FileSystemReadAskForUrlsProto\x12O\n\x14KeygenBlockedForUrls\x18\xbd\x02 \x01(\x0b\x32\x30.enterprise_management.KeygenBlockedForUrlsProto\x12W\n\x18LocalFontsAllowedForUrls\x18\xd4\x07 \x01(\x0b\x32\x34.enterprise_management.LocalFontsAllowedForUrlsProto\x12G\n\x10WebHidAskForUrls\x18\xb2\x07 \x01(\x0b\x32,.enterprise_management.WebHidAskForUrlsProto\x12O\n\x14WebUsbBlockedForUrls\x18\xba\x03 \x01(\x0b\x32\x30.enterprise_management.WebUsbBlockedForUrlsProto\x12Y\n\x19\x44\x65\x66\x61ultMediaStreamSetting\x18\x97\x01 \x01(\x0b\x32\x35.enterprise_management.DefaultMediaStreamSettingProto\x12V\n\x18\x44\x65\x66\x61ultJavaScriptSetting\x18\x34 \x01(\x0b\x32\x34.enterprise_management.DefaultJavaScriptSettingProto\x12N\n\x14\x44\x65\x66\x61ultPopupsSetting\x18\x36 \x01(\x0b\x32\x30.enterprise_management.DefaultPopupsSettingProto\x12N\n\x14ImagesAllowedForUrls\x18G \x01(\x0b\x32\x30.enterprise_management.ImagesAllowedForUrlsProto\x12O\n\x14\x44\x65\x66\x61ultKeygenSetting\x18\xbb\x02 \x01(\x0b\x32\x30.enterprise_management.DefaultKeygenSettingProto\x12P\n\x15PluginsBlockedForUrls\x18L \x01(\x0b\x32\x31.enterprise_management.PluginsBlockedForUrlsProto\x12\x85\x01\n/FileSystemSyncAccessHandleAsyncInterfaceEnabled\x18\xfe\x07 \x01(\x0b\x32K.enterprise_management.FileSystemSyncAccessHandleAsyncInterfaceEnabledProto\x12U\n\x17\x43lipboardBlockedForUrls\x18\xdb\x07 \x01(\x0b\x32\x33.enterprise_management.ClipboardBlockedForUrlsProto\x12\x61\n\x1d\x44\x65\x66\x61ultWindowPlacementSetting\x18\xb9\x07 \x01(\x0b\x32\x39.enterprise_management.DefaultWindowPlacementSettingProto\x12X\n\x19\x43ookiesSessionOnlyForUrls\x18\x46 \x01(\x0b\x32\x35.enterprise_management.CookiesSessionOnlyForUrlsProto\x12\\\n\x1b\x44\x65\x66\x61ultNotificationsSetting\x18\x37 \x01(\x0b\x32\x37.enterprise_management.DefaultNotificationsSettingProto\x12_\n\x1cWebHidAllowAllDevicesForUrls\x18\xbb\x07 \x01(\x0b\x32\x38.enterprise_management.WebHidAllowAllDevicesForUrlsProto\x12Y\n\x19\x44\x65\x66\x61ultWebHidGuardSetting\x18\xb1\x07 \x01(\x0b\x32\x35.enterprise_management.DefaultWebHidGuardSettingProto\x12_\n\x1cSerialAllowUsbDevicesForUrls\x18\xc8\x06 \x01(\x0b\x32\x38.enterprise_management.SerialAllowUsbDevicesForUrlsProto\x12O\n\x14SerialBlockedForUrls\x18\xf3\x05 \x01(\x0b\x32\x30.enterprise_management.SerialBlockedForUrlsProto\x12O\n\x14WebHidBlockedForUrls\x18\xb3\x07 \x01(\x0b\x32\x30.enterprise_management.WebHidBlockedForUrlsProto\x12P\n\x15\x43ookiesAllowedForUrls\x18O \x01(\x0b\x32\x31.enterprise_management.CookiesAllowedForUrlsProto\x12Q\n\x15SensorsAllowedForUrls\x18\xf5\x05 \x01(\x0b\x32\x31.enterprise_management.SensorsAllowedForUrlsProto\x12P\n\x15PluginsAllowedForUrls\x18K \x01(\x0b\x32\x31.enterprise_management.PluginsAllowedForUrlsProto\x12[\n\x1a\x46ileHandlingBlockedForUrls\x18\xd1\x06 \x01(\x0b\x32\x36.enterprise_management.FileHandlingBlockedForUrlsProto\x12[\n\x1aRegisteredProtocolHandlers\x18\x8e\x02 \x01(\x0b\x32\x36.enterprise_management.RegisteredProtocolHandlersProto\x12G\n\x10SerialAskForUrls\x18\xf2\x05 \x01(\x0b\x32,.enterprise_management.SerialAskForUrlsProto\x12P\n\x15\x44\x65\x66\x61ultCookiesSetting\x18\x32 \x01(\x0b\x32\x31.enterprise_management.DefaultCookiesSettingProto\x12m\n#LegacySameSiteCookieBehaviorEnabled\x18\xf1\x04 \x01(\x0b\x32?.enterprise_management.LegacySameSiteCookieBehaviorEnabledProto\x12V\n\x18JavaScriptBlockedForUrls\x18J \x01(\x0b\x32\x34.enterprise_management.JavaScriptBlockedForUrlsProto\x12i\n!DefaultFileSystemReadGuardSetting\x18\x87\x06 \x01(\x0b\x32=.enterprise_management.DefaultFileSystemReadGuardSettingProto\x12\\\n\x1bNotificationsAllowedForUrls\x18k \x01(\x0b\x32\x37.enterprise_management.NotificationsAllowedForUrlsProto\x12Y\n\x19\x44\x65\x66\x61ultWebUsbGuardSetting\x18\xb4\x03 \x01(\x0b\x32\x35.enterprise_management.DefaultWebUsbGuardSettingProto\x12Y\n\x19WebUsbAllowDevicesForUrls\x18\xe8\x03 \x01(\x0b\x32\x35.enterprise_management.WebUsbAllowDevicesForUrlsProto\x12U\n\x17\x44\x65\x66\x61ultClipboardSetting\x18\xd9\x07 \x01(\x0b\x32\x33.enterprise_management.DefaultClipboardSettingProto\x12\x61\n\x1dWindowPlacementAllowedForUrls\x18\xc2\x07 \x01(\x0b\x32\x39.enterprise_management.WindowPlacementAllowedForUrlsProto\x12\x87\x01\n0LegacySameSiteCookieBehaviorEnabledForDomainList\x18\xf2\x04 \x01(\x0b\x32L.enterprise_management.LegacySameSiteCookieBehaviorEnabledForDomainListProto\x12W\n\x18LocalFontsBlockedForUrls\x18\xd5\x07 \x01(\x0b\x32\x34.enterprise_management.LocalFontsBlockedForUrlsProto\x12X\n\x19\x44\x65\x66\x61ultGeolocationSetting\x18\x38 \x01(\x0b\x32\x35.enterprise_management.DefaultGeolocationSettingProto\x12_\n\x1c\x46ileSystemReadBlockedForUrls\x18\x8a\x06 \x01(\x0b\x32\x38.enterprise_management.FileSystemReadBlockedForUrlsProto\x12Y\n\x19\x44\x65\x66\x61ultSerialGuardSetting\x18\xf1\x05 \x01(\x0b\x32\x35.enterprise_management.DefaultSerialGuardSettingProto\x12Y\n\x19WebHidAllowDevicesForUrls\x18\xbc\x07 \x01(\x0b\x32\x35.enterprise_management.WebHidAllowDevicesForUrlsProto\x12^\n\x1c\x41utoSelectCertificateForUrls\x18h \x01(\x0b\x32\x38.enterprise_management.AutoSelectCertificateForUrlsProto\x12P\n\x15\x44\x65\x66\x61ultPluginsSetting\x18\x35 \x01(\x0b\x32\x31.enterprise_management.DefaultPluginsSettingProto\x12N\n\x14\x44\x65\x66\x61ultImagesSetting\x18\x33 \x01(\x0b\x32\x30.enterprise_management.DefaultImagesSettingProto\x12N\n\x14PopupsAllowedForUrls\x18M \x01(\x0b\x32\x30.enterprise_management.PopupsAllowedForUrlsProto\x12\x65\n\x1f\x44\x65\x66\x61ultWebBluetoothGuardSetting\x18\xc2\x02 \x01(\x0b\x32;.enterprise_management.DefaultWebBluetoothGuardSettingProto\x12U\n\x17\x43lipboardAllowedForUrls\x18\xda\x07 \x01(\x0b\x32\x33.enterprise_management.ClipboardAllowedForUrlsProto\x12\x61\n\x1dWindowPlacementBlockedForUrls\x18\xc3\x07 \x01(\x0b\x32\x39.enterprise_management.WindowPlacementBlockedForUrlsProto\x12\x61\n\x1dInsecureContentBlockedForUrls\x18\xfd\x04 \x01(\x0b\x32\x39.enterprise_management.InsecureContentBlockedForUrlsProto\x12[\n\x1a\x46ileHandlingAllowedForUrls\x18\xd0\x06 \x01(\x0b\x32\x36.enterprise_management.FileHandlingAllowedForUrlsProto\x12G\n\x10WebUsbAskForUrls\x18\xb9\x03 \x01(\x0b\x32,.enterprise_management.WebUsbAskForUrlsProto\x12Q\n\x15\x44\x65\x66\x61ultSensorsSetting\x18\xf4\x05 \x01(\x0b\x32\x31.enterprise_management.DefaultSensorsSettingProto\x12s\n&WebHidAllowDevicesWithHidUsagesForUrls\x18\xbd\x07 \x01(\x0b\x32\x42.enterprise_management.WebHidAllowDevicesWithHidUsagesForUrlsProto\x12\\\n\x1bNotificationsBlockedForUrls\x18l \x01(\x0b\x32\x37.enterprise_management.NotificationsBlockedForUrlsProto\x12]\n\x1b\x44\x65\x66\x61ultJavaScriptJitSetting\x18\xe5\x06 \x01(\x0b\x32\x37.enterprise_management.DefaultJavaScriptJitSettingProto\x12Y\n\x19\x46ileSystemWriteAskForUrls\x18\x8b\x06 \x01(\x0b\x32\x35.enterprise_management.FileSystemWriteAskForUrlsProto\x12\x61\n\x1dInsecureContentAllowedForUrls\x18\xfc\x04 \x01(\x0b\x32\x39.enterprise_management.InsecureContentAllowedForUrlsProto\x12P\n\x15\x43ookiesBlockedForUrls\x18\x45 \x01(\x0b\x32\x31.enterprise_management.CookiesBlockedForUrlsProto\x12[\n\x1aSerialAllowAllPortsForUrls\x18\xc7\x06 \x01(\x0b\x32\x36.enterprise_management.SerialAllowAllPortsForUrlsProto\x12N\n\x14ImagesBlockedForUrls\x18H \x01(\x0b\x32\x30.enterprise_management.ImagesBlockedForUrlsProto\x12_\n\x1cJavaScriptJitAllowedForSites\x18\xe6\x06 \x01(\x0b\x32\x38.enterprise_management.JavaScriptJitAllowedForSitesProto\x12k\n\"DefaultFileSystemWriteGuardSetting\x18\x88\x06 \x01(\x0b\x32>.enterprise_management.DefaultFileSystemWriteGuardSettingProto\x12\x65\n\x1f\x44\x65\x66\x61ultFileHandlingGuardSetting\x18\xcf\x06 \x01(\x0b\x32;.enterprise_management.DefaultFileHandlingGuardSettingProto\x12_\n\x1cJavaScriptJitBlockedForSites\x18\xe7\x06 \x01(\x0b\x32\x38.enterprise_management.JavaScriptJitBlockedForSitesProto\x12V\n\x18JavaScriptAllowedForUrls\x18I \x01(\x0b\x32\x34.enterprise_management.JavaScriptAllowedForUrlsProto\x12\x61\n\x1d\x46ileSystemWriteBlockedForUrls\x18\x8c\x06 \x01(\x0b\x32\x39.enterprise_management.FileSystemWriteBlockedForUrlsProto\x12\x65\n\x1fKerberosRememberPasswordEnabled\x18\xb0\x04 \x01(\x0b\x32;.enterprise_management.KerberosRememberPasswordEnabledProto\x12[\n\x1aKerberosDomainAutocomplete\x18\xe9\x07 \x01(\x0b\x32\x36.enterprise_management.KerberosDomainAutocompleteProto\x12G\n\x10KerberosAccounts\x18\xb2\x04 \x01(\x0b\x32,.enterprise_management.KerberosAccountsProto\x12_\n\x1cKerberosDefaultConfiguration\x18\xea\x07 \x01(\x0b\x32\x38.enterprise_management.KerberosDefaultConfigurationProto\x12[\n\x1aKerberosAddAccountsAllowed\x18\xb1\x04 \x01(\x0b\x32\x36.enterprise_management.KerberosAddAccountsAllowedProto\x12\x45\n\x0fKerberosEnabled\x18\xaf\x04 \x01(\x0b\x32+.enterprise_management.KerberosEnabledProto\x12T\n\x17\x43hromeFrameContentTypes\x18> \x01(\x0b\x32\x33.enterprise_management.ChromeFrameContentTypesProto\x12\x61\n\x1dQuickAnswersDefinitionEnabled\x18\x98\x07 \x01(\x0b\x32\x39.enterprise_management.QuickAnswersDefinitionEnabledProto\x12\x63\n\x1eQuickAnswersTranslationEnabled\x18\x99\x07 \x01(\x0b\x32:.enterprise_management.QuickAnswersTranslationEnabledProto\x12i\n!QuickAnswersUnitConversionEnabled\x18\x9a\x07 \x01(\x0b\x32=.enterprise_management.QuickAnswersUnitConversionEnabledProto\x12M\n\x13QuickAnswersEnabled\x18\x97\x07 \x01(\x0b\x32/.enterprise_management.QuickAnswersEnabledProto\x12o\n$SupervisedUserContentProviderEnabled\x18\xba\x02 \x01(\x0b\x32@.enterprise_management.SupervisedUserContentProviderEnabledProto\x12\x61\n\x1dSupervisedUserCreationEnabled\x18\xe1\x01 \x01(\x0b\x32\x39.enterprise_management.SupervisedUserCreationEnabledProto\x12k\n\"RemoteAccessHostTokenValidationUrl\x18\xa1\x02 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostTokenValidationUrlProto\x12\x87\x01\n0RemoteAccessHostTokenValidationCertificateIssuer\x18\xa2\x02 \x01(\x0b\x32L.enterprise_management.RemoteAccessHostTokenValidationCertificateIssuerProto\x12\x81\x01\n-RemoteAccessHostAllowRemoteSupportConnections\x18\x9d\x07 \x01(\x0b\x32I.enterprise_management.RemoteAccessHostAllowRemoteSupportConnectionsProto\x12\x63\n\x1eRemoteAccessHostRequireCurtain\x18\x9f\x01 \x01(\x0b\x32:.enterprise_management.RemoteAccessHostRequireCurtainProto\x12\x7f\n,RemoteAccessHostAllowRemoteAccessConnections\x18\xae\x06 \x01(\x0b\x32H.enterprise_management.RemoteAccessHostAllowRemoteAccessConnectionsProto\x12_\n\x1cRemoteAccessHostUdpPortRange\x18\x8a\x02 \x01(\x0b\x32\x38.enterprise_management.RemoteAccessHostUdpPortRangeProto\x12\x65\n\x1fRemoteAccessHostAllowGnubbyAuth\x18\x83\x02 \x01(\x0b\x32;.enterprise_management.RemoteAccessHostAllowGnubbyAuthProto\x12m\n#RemoteAccessHostEnableUserInterface\x18\xa5\x06 \x01(\x0b\x32?.enterprise_management.RemoteAccessHostEnableUserInterfaceProto\x12g\n RemoteAccessHostTalkGadgetPrefix\x18\x9e\x01 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostTalkGadgetPrefixProto\x12g\n RemoteAccessHostClientDomainList\x18\xf3\x02 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostClientDomainListProto\x12\x87\x01\n0RemoteAccessHostAllowUiAccessForRemoteAssistance\x18\xda\x02 \x01(\x0b\x32L.enterprise_management.RemoteAccessHostAllowUiAccessForRemoteAssistanceProto\x12\x61\n\x1dRemoteAccessHostMatchUsername\x18\x9f\x02 \x01(\x0b\x32\x39.enterprise_management.RemoteAccessHostMatchUsernameProto\x12l\n#RemoteAccessClientFirewallTraversal\x18` \x01(\x0b\x32?.enterprise_management.RemoteAccessClientFirewallTraversalProto\x12s\n&RemoteAccessHostAllowRelayedConnection\x18\x89\x02 \x01(\x0b\x32\x42.enterprise_management.RemoteAccessHostAllowRelayedConnectionProto\x12\x81\x01\n-RemoteAccessHostMaximumSessionDurationMinutes\x18\xb0\x06 \x01(\x0b\x32I.enterprise_management.RemoteAccessHostMaximumSessionDurationMinutesProto\x12_\n\x1cRemoteAccessHostClientDomain\x18\xbe\x02 \x01(\x0b\x32\x38.enterprise_management.RemoteAccessHostClientDomainProto\x12g\n RemoteAccessHostRequireTwoFactor\x18\x9d\x01 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostRequireTwoFactorProto\x12q\n%RemoteAccessHostDebugOverridePolicies\x18\xa3\x02 \x01(\x0b\x32\x41.enterprise_management.RemoteAccessHostDebugOverridePoliciesProto\x12k\n\"RemoteAccessHostClipboardSizeBytes\x18\x9c\x07 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostClipboardSizeBytesProto\x12W\n\x18RemoteAccessHostTokenUrl\x18\xa0\x02 \x01(\x0b\x32\x34.enterprise_management.RemoteAccessHostTokenUrlProto\x12[\n\x1aRemoteAccessHostDomainList\x18\xf2\x02 \x01(\x0b\x32\x36.enterprise_management.RemoteAccessHostDomainListProto\x12h\n!RemoteAccessHostFirewallTraversal\x18\x61 \x01(\x0b\x32=.enterprise_management.RemoteAccessHostFirewallTraversalProto\x12S\n\x16RemoteAccessHostDomain\x18\x9c\x01 \x01(\x0b\x32\x32.enterprise_management.RemoteAccessHostDomainProto\x12i\n!RemoteAccessHostAllowFileTransfer\x18\x98\x04 \x01(\x0b\x32=.enterprise_management.RemoteAccessHostAllowFileTransferProto\x12k\n\"RemoteAccessHostAllowClientPairing\x18\xec\x01 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostAllowClientPairingProto\x12W\n\x18NewWindowsInKioskAllowed\x18\xe5\x07 \x01(\x0b\x32\x34.enterprise_management.NewWindowsInKioskAllowedProto\x12\x61\n\x1d\x45xtensionAllowInsecureUpdates\x18\x86\x04 \x01(\x0b\x32\x39.enterprise_management.ExtensionAllowInsecureUpdatesProto\x12Y\n\x19\x45xtensionInstallAllowlist\x18\xe4\x05 \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallAllowlistProto\x12Y\n\x19\x45xtensionInstallBlocklist\x18\xe6\x05 \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallBlocklistProto\x12X\n\x19\x45xtensionInstallForcelist\x18$ \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallForcelistProto\x12Q\n\x15\x45xtensionAllowedTypes\x18\xaa\x01 \x01(\x0b\x32\x31.enterprise_management.ExtensionAllowedTypesProto\x12U\n\x17\x45xtensionInstallSources\x18\x96\x01 \x01(\x0b\x32\x33.enterprise_management.ExtensionInstallSourcesProto\x12\x65\n\x1f\x45xtensionManifestV2Availability\x18\x88\x08 \x01(\x0b\x32;.enterprise_management.ExtensionManifestV2AvailabilityProto\x12U\n\x17\x42lockExternalExtensions\x18\xff\x04 \x01(\x0b\x32\x33.enterprise_management.BlockExternalExtensionsProto\x12I\n\x11\x45xtensionSettings\x18\x98\x02 \x01(\x0b\x32-.enterprise_management.ExtensionSettingsProto\x12m\n#VoiceInteractionQuickAnswersEnabled\x18\xb8\x05 \x01(\x0b\x32?.enterprise_management.VoiceInteractionQuickAnswersEnabledProto\x12\x63\n\x1eVoiceInteractionContextEnabled\x18\x91\x04 \x01(\x0b\x32:.enterprise_management.VoiceInteractionContextEnabledProto\x12\x63\n\x1eVoiceInteractionHotwordEnabled\x18\x93\x04 \x01(\x0b\x32:.enterprise_management.VoiceInteractionHotwordEnabledProto\x12o\n$AssistantVoiceMatchEnabledDuringOobe\x18\xf7\x06 \x01(\x0b\x32@.enterprise_management.AssistantVoiceMatchEnabledDuringOobeProto\x12U\n\x17\x41ssistantOnboardingMode\x18\xdb\x05 \x01(\x0b\x32\x33.enterprise_management.AssistantOnboardingModeProto\x12M\n\x13\x41ssistantWebEnabled\x18\xf5\x07 \x01(\x0b\x32/.enterprise_management.AssistantWebEnabledProto\x12\x61\n\x1d\x41ttestationExtensionAllowlist\x18\x93\x06 \x01(\x0b\x32\x39.enterprise_management.AttestationExtensionAllowlistProto\x12Y\n\x19\x41ttestationEnabledForUser\x18\xca\x01 \x01(\x0b\x32\x35.enterprise_management.AttestationEnabledForUserProto\x12M\n\x13\x43\x61stReceiverEnabled\x18\xfc\x02 \x01(\x0b\x32/.enterprise_management.CastReceiverEnabledProto\x12S\n\x16RecoveryFactorBehavior\x18\xf8\x07 \x01(\x0b\x32\x32.enterprise_management.RecoveryFactorBehaviorProto\x12Q\n\x15ShowCastIconInToolbar\x18\xec\x02 \x01(\x0b\x32\x31.enterprise_management.ShowCastIconInToolbarProto\x12[\n\x1aMediaRouterCastAllowAllIPs\x18\xb7\x03 \x01(\x0b\x32\x36.enterprise_management.MediaRouterCastAllowAllIPsProto\x12I\n\x11\x45nableMediaRouter\x18\xcf\x02 \x01(\x0b\x32-.enterprise_management.EnableMediaRouterProto\x12G\n\x10\x41utoclickEnabled\x18\xd7\x04 \x01(\x0b\x32,.enterprise_management.AutoclickEnabledProto\x12S\n\x16VirtualKeyboardEnabled\x18\x81\x02 \x01(\x0b\x32\x32.enterprise_management.VirtualKeyboardEnabledProto\x12I\n\x11StickyKeysEnabled\x18\xb3\x04 \x01(\x0b\x32-.enterprise_management.StickyKeysEnabledProto\x12U\n\x17VirtualKeyboardFeatures\x18\xcf\x05 \x01(\x0b\x32\x33.enterprise_management.VirtualKeyboardFeaturesProto\x12M\n\x13HighContrastEnabled\x18\xd7\x01 \x01(\x0b\x32/.enterprise_management.HighContrastEnabledProto\x12\x61\n\x1dKeyboardDefaultToFunctionKeys\x18\x86\x02 \x01(\x0b\x32\x39.enterprise_management.KeyboardDefaultToFunctionKeysProto\x12\x61\n\x1d\x41\x63\x63\x65ssibilityShortcutsEnabled\x18\x95\x05 \x01(\x0b\x32\x39.enterprise_management.AccessibilityShortcutsEnabledProto\x12O\n\x14SelectToSpeakEnabled\x18\xbf\x04 \x01(\x0b\x32\x30.enterprise_management.SelectToSpeakEnabledProto\x12g\n FloatingAccessibilityMenuEnabled\x18\xb5\x05 \x01(\x0b\x32<.enterprise_management.FloatingAccessibilityMenuEnabledProto\x12w\n(ShowAccessibilityOptionsInSystemTrayMenu\x18\xbe\x01 \x01(\x0b\x32\x44.enterprise_management.ShowAccessibilityOptionsInSystemTrayMenuProto\x12S\n\x16\x43ursorHighlightEnabled\x18\xd4\x04 \x01(\x0b\x32\x32.enterprise_management.CursorHighlightEnabledProto\x12Q\n\x15\x43\x61retHighlightEnabled\x18\xd5\x04 \x01(\x0b\x32\x31.enterprise_management.CaretHighlightEnabledProto\x12\x61\n\x1dKeyboardFocusHighlightEnabled\x18\xd3\x04 \x01(\x0b\x32\x39.enterprise_management.KeyboardFocusHighlightEnabledProto\x12M\n\x13ScreenMagnifierType\x18\xd8\x01 \x01(\x0b\x32/.enterprise_management.ScreenMagnifierTypeProto\x12G\n\x10MonoAudioEnabled\x18\xd6\x04 \x01(\x0b\x32,.enterprise_management.MonoAudioEnabledProto\x12}\n+EnhancedNetworkVoicesInSelectToSpeakAllowed\x18\xfa\x06 \x01(\x0b\x32G.enterprise_management.EnhancedNetworkVoicesInSelectToSpeakAllowedProto\x12Q\n\x15SpokenFeedbackEnabled\x18\xd6\x01 \x01(\x0b\x32\x31.enterprise_management.SpokenFeedbackEnabledProto\x12G\n\x10\x44ictationEnabled\x18\xd2\x04 \x01(\x0b\x32,.enterprise_management.DictationEnabledProto\x12K\n\x12LargeCursorEnabled\x18\xd5\x01 \x01(\x0b\x32..enterprise_management.LargeCursorEnabledProto\x12R\n\x16PasswordManagerEnabled\x18\x12 \x01(\x0b\x32\x32.enterprise_management.PasswordManagerEnabledProto\x12s\n&PasswordDismissCompromisedAlertEnabled\x18\xb4\x07 \x01(\x0b\x32\x42.enterprise_management.PasswordDismissCompromisedAlertEnabledProto\x12_\n\x1cPasswordLeakDetectionEnabled\x18\xc6\x04 \x01(\x0b\x32\x38.enterprise_management.PasswordLeakDetectionEnabledProto\x12h\n!PasswordManagerAllowShowPasswords\x18\x13 \x01(\x0b\x32=.enterprise_management.PasswordManagerAllowShowPasswordsProto\x12\x61\n\x1dPluginVmDataCollectionAllowed\x18\xca\x05 \x01(\x0b\x32\x39.enterprise_management.PluginVmDataCollectionAllowedProto\x12\x43\n\x0ePluginVmUserId\x18\xbc\x05 \x01(\x0b\x32*.enterprise_management.PluginVmUserIdProto\x12M\n\x13UserPluginVmAllowed\x18\xc3\x05 \x01(\x0b\x32/.enterprise_management.UserPluginVmAllowedProto\x12\x61\n\x1dPluginVmRequiredFreeDiskSpace\x18\xd6\x05 \x01(\x0b\x32\x39.enterprise_management.PluginVmRequiredFreeDiskSpaceProto\x12\x41\n\rPluginVmImage\x18\xfa\x03 \x01(\x0b\x32).enterprise_management.PluginVmImageProto\x12\x43\n\x0eUsageTimeLimit\x18\xc2\x03 \x01(\x0b\x32*.enterprise_management.UsageTimeLimitProto\x12Y\n\x19PerAppTimeLimitsAllowlist\x18\xfc\x05 \x01(\x0b\x32\x35.enterprise_management.PerAppTimeLimitsAllowlistProto\x12S\n\x16ParentAccessCodeConfig\x18\xfd\x03 \x01(\x0b\x32\x32.enterprise_management.ParentAccessCodeConfigProto\x12G\n\x10PerAppTimeLimits\x18\x83\x05 \x01(\x0b\x32,.enterprise_management.PerAppTimeLimitsProto\x12W\n\x18\x45\x64uCoexistenceToSVersion\x18\x98\x06 \x01(\x0b\x32\x34.enterprise_management.EduCoexistenceToSVersionProto\x12g\n RequiredClientCertificateForUser\x18\xaa\x05 \x01(\x0b\x32<.enterprise_management.RequiredClientCertificateForUserProto\x12o\n$SafeBrowsingExtendedReportingEnabled\x18\xaf\x03 \x01(\x0b\x32@.enterprise_management.SafeBrowsingExtendedReportingEnabledProto\x12]\n\x1bSafeBrowsingProtectionLevel\x18\xae\x05 \x01(\x0b\x32\x37.enterprise_management.SafeBrowsingProtectionLevelProto\x12L\n\x13SafeBrowsingEnabled\x18\x10 \x01(\x0b\x32/.enterprise_management.SafeBrowsingEnabledProto\x12g\n PasswordProtectionWarningTrigger\x18\x9d\x03 \x01(\x0b\x32<.enterprise_management.PasswordProtectionWarningTriggerProto\x12m\n#PasswordProtectionChangePasswordURL\x18\xaa\x03 \x01(\x0b\x32?.enterprise_management.PasswordProtectionChangePasswordURLProto\x12_\n\x1cSafeBrowsingAllowlistDomains\x18\xde\x05 \x01(\x0b\x32\x38.enterprise_management.SafeBrowsingAllowlistDomainsProto\x12]\n\x1bPasswordProtectionLoginURLs\x18\xa9\x03 \x01(\x0b\x32\x37.enterprise_management.PasswordProtectionLoginURLsProto\x12[\n\x1aPinUnlockAutosubmitEnabled\x18\xd0\x05 \x01(\x0b\x32\x36.enterprise_management.PinUnlockAutosubmitEnabledProto\x12W\n\x18PinUnlockWeakPinsAllowed\x18\xe6\x02 \x01(\x0b\x32\x34.enterprise_management.PinUnlockWeakPinsAllowedProto\x12W\n\x18QuickUnlockModeAllowlist\x18\x92\x06 \x01(\x0b\x32\x34.enterprise_management.QuickUnlockModeAllowlistProto\x12S\n\x16PinUnlockMinimumLength\x18\xe4\x02 \x01(\x0b\x32\x32.enterprise_management.PinUnlockMinimumLengthProto\x12S\n\x16PinUnlockMaximumLength\x18\xe5\x02 \x01(\x0b\x32\x32.enterprise_management.PinUnlockMaximumLengthProto\x12K\n\x12QuickUnlockTimeout\x18\xe3\x02 \x01(\x0b\x32..enterprise_management.QuickUnlockTimeoutProto\x12\x61\n\x1d\x43rostiniExportImportUIAllowed\x18\x8d\x04 \x01(\x0b\x32\x39.enterprise_management.CrostiniExportImportUIAllowedProto\x12Y\n\x19\x43rostiniRootAccessAllowed\x18\xc2\x04 \x01(\x0b\x32\x35.enterprise_management.CrostiniRootAccessAllowedProto\x12\x45\n\x0f\x43rostiniAllowed\x18\xe3\x03 \x01(\x0b\x32+.enterprise_management.CrostiniAllowedProto\x12\x61\n\x1d\x43rostiniPortForwardingAllowed\x18\xce\x05 \x01(\x0b\x32\x39.enterprise_management.CrostiniPortForwardingAllowedProto\x12W\n\x18SystemTerminalSshAllowed\x18\xd0\x07 \x01(\x0b\x32\x34.enterprise_management.SystemTerminalSshAllowedProto\x12U\n\x17\x43rostiniAnsiblePlaybook\x18\x81\x05 \x01(\x0b\x32\x33.enterprise_management.CrostiniAnsiblePlaybookProto\x12g\n CrostiniArcAdbSideloadingAllowed\x18\xb4\x05 \x01(\x0b\x32<.enterprise_management.CrostiniArcAdbSideloadingAllowedProto\x12]\n\x1b\x44\x61taCompressionProxyEnabled\x18\xf3\x01 \x01(\x0b\x32\x37.enterprise_management.DataCompressionProxyEnabledProto\x12[\n\x1aHindiInscriptLayoutEnabled\x18\x83\x08 \x01(\x0b\x32\x36.enterprise_management.HindiInscriptLayoutEnabledProto\x12_\n\x1c\x45nableOnlineRevocationChecks\x18\x83\x01 \x01(\x0b\x32\x38.enterprise_management.EnableOnlineRevocationChecksProto\x12m\n#UnsafelyTreatInsecureOriginAsSecure\x18\x92\x03 \x01(\x0b\x32?.enterprise_management.UnsafelyTreatInsecureOriginAsSecureProto\x12S\n\x16\x46orceYouTubeSafetyMode\x18\x9d\x02 \x01(\x0b\x32\x32.enterprise_management.ForceYouTubeSafetyModeProto\x12\x93\x01\n6CertificateTransparencyEnforcementDisabledForLegacyCas\x18\xb6\x03 \x01(\x0b\x32R.enterprise_management.CertificateTransparencyEnforcementDisabledForLegacyCasProto\x12\x41\n\rHttpsOnlyMode\x18\xe8\x06 \x01(\x0b\x32).enterprise_management.HttpsOnlyModeProto\x12g\n SetTimeoutWithout1MsClampEnabled\x18\xc9\x07 \x01(\x0b\x32<.enterprise_management.SetTimeoutWithout1MsClampEnabledProto\x12P\n\x15\x44nsPrefetchingEnabled\x18\t \x01(\x0b\x32\x31.enterprise_management.DnsPrefetchingEnabledProto\x12]\n\x1bSpellcheckLanguageBlocklist\x18\xef\x05 \x01(\x0b\x32\x37.enterprise_management.SpellcheckLanguageBlocklistProto\x12\x44\n\x0f\x44isabledPlugins\x18\x15 \x01(\x0b\x32+.enterprise_management.DisabledPluginsProto\x12S\n\x16SchedulerConfiguration\x18\x8c\x04 \x01(\x0b\x32\x32.enterprise_management.SchedulerConfigurationProto\x12Y\n\x19PolicyAtomicGroupsEnabled\x18\xca\x04 \x01(\x0b\x32\x35.enterprise_management.PolicyAtomicGroupsEnabledProto\x12\x63\n\x1e\x41\x64\x64itionalDnsQueryTypesEnabled\x18\xdb\x06 \x01(\x0b\x32:.enterprise_management.AdditionalDnsQueryTypesEnabledProto\x12q\n%AdvancedProtectionDeepScanningEnabled\x18\x9d\x05 \x01(\x0b\x32\x41.enterprise_management.AdvancedProtectionDeepScanningEnabledProto\x12]\n\x1bScrollToTextFragmentEnabled\x18\xb1\x05 \x01(\x0b\x32\x37.enterprise_management.ScrollToTextFragmentEnabledProto\x12\x62\n\x1e\x41uthNegotiateDelegateWhitelist\x18 \x01(\x0b\x32:.enterprise_management.AuthNegotiateDelegateWhitelistProto\x12]\n\x1bRendererAppContainerEnabled\x18\xdd\x07 \x01(\x0b\x32\x37.enterprise_management.RendererAppContainerEnabledProto\x12\x61\n\x1d\x41ttestationExtensionWhitelist\x18\xcb\x01 \x01(\x0b\x32\x39.enterprise_management.AttestationExtensionWhitelistProto\x12R\n\x16MaxConnectionsPerProxy\x18^ \x01(\x0b\x32\x32.enterprise_management.MaxConnectionsPerProxyProto\x12K\n\x12\x44isableScreenshots\x18\x9b\x01 \x01(\x0b\x32..enterprise_management.DisableScreenshotsProto\x12\x89\x01\n1CertificateTransparencyEnforcementDisabledForUrls\x18\xd1\x02 \x01(\x0b\x32M.enterprise_management.CertificateTransparencyEnforcementDisabledForUrlsProto\x12S\n\x16ShowLogoutButtonInTray\x18\xa6\x01 \x01(\x0b\x32\x32.enterprise_management.ShowLogoutButtonInTrayProto\x12G\n\x10VpnConfigAllowed\x18\xe7\x03 \x01(\x0b\x32,.enterprise_management.VpnConfigAllowedProto\x12\x42\n\x0e\x45nabledPlugins\x18P \x01(\x0b\x32*.enterprise_management.EnabledPluginsProto\x12\x63\n\x1e\x45nableDeprecatedPrivetPrinting\x18\xb1\x06 \x01(\x0b\x32:.enterprise_management.EnableDeprecatedPrivetPrintingProto\x12\x63\n\x1e\x45nterpriseRealTimeUrlCheckMode\x18\xda\x05 \x01(\x0b\x32:.enterprise_management.EnterpriseRealTimeUrlCheckModeProto\x12Y\n\x19\x41\x64vancedProtectionAllowed\x18\xaf\x05 \x01(\x0b\x32\x35.enterprise_management.AdvancedProtectionAllowedProto\x12R\n\x16\x41pplicationLocaleValue\x18\x06 \x01(\x0b\x32\x32.enterprise_management.ApplicationLocaleValueProto\x12O\n\x14\x41ppCacheForceEnabled\x18\xc2\x05 \x01(\x0b\x32\x30.enterprise_management.AppCacheForceEnabledProto\x12q\n%EnterpriseAuthenticationAppLinkPolicy\x18\xd2\x07 \x01(\x0b\x32\x41.enterprise_management.EnterpriseAuthenticationAppLinkPolicyProto\x12_\n\x1cTaskManagerEndProcessEnabled\x18\xc9\x02 \x01(\x0b\x32\x38.enterprise_management.TaskManagerEndProcessEnabledProto\x12Q\n\x15SitePerProcessAndroid\x18\xc0\x03 \x01(\x0b\x32\x31.enterprise_management.SitePerProcessAndroidProto\x12W\n\x18IntranetRedirectBehavior\x18\x9a\x06 \x01(\x0b\x32\x34.enterprise_management.IntranetRedirectBehaviorProto\x12g\n DefaultHandlersForFileExtensions\x18\xff\x07 \x01(\x0b\x32<.enterprise_management.DefaultHandlersForFileExtensionsProto\x12W\n\x18\x42rowserGuestModeEnforced\x18\xc0\x04 \x01(\x0b\x32\x34.enterprise_management.BrowserGuestModeEnforcedProto\x12\x41\n\rSSLVersionMax\x18\xeb\x02 \x01(\x0b\x32).enterprise_management.SSLVersionMaxProto\x12Y\n\x19PerAppTimeLimitsWhitelist\x18\x94\x05 \x01(\x0b\x32\x35.enterprise_management.PerAppTimeLimitsWhitelistProto\x12\x46\n\x10IncognitoEnabled\x18\x0c \x01(\x0b\x32,.enterprise_management.IncognitoEnabledProto\x12Y\n\x19\x42ruschettaVMConfiguration\x18\x8b\x08 \x01(\x0b\x32\x35.enterprise_management.BruschettaVMConfigurationProto\x12]\n\x1bPacHttpsUrlStrippingEnabled\x18\xce\x02 \x01(\x0b\x32\x37.enterprise_management.PacHttpsUrlStrippingEnabledProto\x12k\n\"OffsetParentNewSpecBehaviorEnabled\x18\x89\x08 \x01(\x0b\x32>.enterprise_management.OffsetParentNewSpecBehaviorEnabledProto\x12k\n\"CloudPolicyOverridesPlatformPolicy\x18\xff\x02 \x01(\x0b\x32>.enterprise_management.CloudPolicyOverridesPlatformPolicyProto\x12m\n#SecondaryGoogleAccountSigninAllowed\x18\x98\x03 \x01(\x0b\x32?.enterprise_management.SecondaryGoogleAccountSigninAllowedProto\x12O\n\x14\x44ownloadRestrictions\x18\xf5\x02 \x01(\x0b\x32\x30.enterprise_management.DownloadRestrictionsProto\x12Z\n\x1a\x41lternateErrorPagesEnabled\x18\x07 \x01(\x0b\x32\x36.enterprise_management.AlternateErrorPagesEnabledProto\x12\x63\n\x1e\x41utoLaunchProtocolsFromOrigins\x18\xd4\x05 \x01(\x0b\x32:.enterprise_management.AutoLaunchProtocolsFromOriginsProto\x12\x43\n\x0eWallpaperImage\x18\x88\x02 \x01(\x0b\x32*.enterprise_management.WallpaperImageProto\x12o\n$AbusiveExperienceInterventionEnforce\x18\x96\x03 \x01(\x0b\x32@.enterprise_management.AbusiveExperienceInterventionEnforceProto\x12g\n ChromeOsMultiProfileUserBehavior\x18\xf6\x01 \x01(\x0b\x32<.enterprise_management.ChromeOsMultiProfileUserBehaviorProto\x12O\n\x14RelaunchNotification\x18\xa5\x03 \x01(\x0b\x32\x30.enterprise_management.RelaunchNotificationProto\x12\x42\n\x0eImportHomepage\x18\x65 \x01(\x0b\x32*.enterprise_management.ImportHomepageProto\x12\x43\n\x0eRelaunchWindow\x18\xd8\x06 \x01(\x0b\x32*.enterprise_management.RelaunchWindowProto\x12\x43\n\x0eShelfAlignment\x18\xee\x04 \x01(\x0b\x32*.enterprise_management.ShelfAlignmentProto\x12J\n\x12\x42ookmarkBarEnabled\x18T \x01(\x0b\x32..enterprise_management.BookmarkBarEnabledProto\x12g\n ManagedAccountsSigninRestriction\x18\xde\x06 \x01(\x0b\x32<.enterprise_management.ManagedAccountsSigninRestrictionProto\x12_\n\x1cPhoneHubNotificationsAllowed\x18\x9e\x06 \x01(\x0b\x32\x38.enterprise_management.PhoneHubNotificationsAllowedProto\x12o\n$CORSNonWildcardRequestHeadersSupport\x18\x9b\x07 \x01(\x0b\x32@.enterprise_management.CORSNonWildcardRequestHeadersSupportProto\x12\x65\n\x1fHardwareAccelerationModeEnabled\x18\xb2\x02 \x01(\x0b\x32;.enterprise_management.HardwareAccelerationModeEnabledProto\x12U\n\x17\x43ontextualSearchEnabled\x18\x9b\x02 \x01(\x0b\x32\x33.enterprise_management.ContextualSearchEnabledProto\x12I\n\x11\x45\x61syUnlockAllowed\x18\x92\x02 \x01(\x0b\x32-.enterprise_management.EasyUnlockAllowedProto\x12U\n\x17\x45xternalStorageReadOnly\x18\xd9\x02 \x01(\x0b\x32\x33.enterprise_management.ExternalStorageReadOnlyProto\x12_\n\x1cSecurityTokenSessionBehavior\x18\xa1\x06 \x01(\x0b\x32\x38.enterprise_management.SecurityTokenSessionBehaviorProto\x12M\n\x13UserFeedbackAllowed\x18\xbc\x04 \x01(\x0b\x32/.enterprise_management.UserFeedbackAllowedProto\x12]\n\x1bLockIconInAddressBarEnabled\x18\xdf\x06 \x01(\x0b\x32\x37.enterprise_management.LockIconInAddressBarEnabledProto\x12g\n LookalikeWarningAllowlistDomains\x18\x90\x06 \x01(\x0b\x32<.enterprise_management.LookalikeWarningAllowlistDomainsProto\x12\x95\x01\n7RestrictedManagedGuestSessionExtensionCleanupExemptList\x18\xf1\x06 \x01(\x0b\x32S.enterprise_management.RestrictedManagedGuestSessionExtensionCleanupExemptListProto\x12g\n IsolatedAppsDeveloperModeAllowed\x18\xc0\x07 \x01(\x0b\x32<.enterprise_management.IsolatedAppsDeveloperModeAllowedProto\x12N\n\x14SearchSuggestEnabled\x18\x08 \x01(\x0b\x32\x30.enterprise_management.SearchSuggestEnabledProto\x12?\n\x0cTrashEnabled\x18\xfb\x07 \x01(\x0b\x32(.enterprise_management.TrashEnabledProto\x12U\n\x17VideoCaptureAllowedUrls\x18\xd3\x01 \x01(\x0b\x32\x33.enterprise_management.VideoCaptureAllowedUrlsProto\x12K\n\x12\x42rowserLabsEnabled\x18\xb2\x06 \x01(\x0b\x32..enterprise_management.BrowserLabsEnabledProto\x12w\n(SamlLockScreenOfflineSigninTimeLimitDays\x18\xc4\x06 \x01(\x0b\x32\x44.enterprise_management.SamlLockScreenOfflineSigninTimeLimitDaysProto\x12\x63\n\x1eIsolatedWebAppInstallForceList\x18\x80\x08 \x01(\x0b\x32:.enterprise_management.IsolatedWebAppInstallForceListProto\x12\x87\x01\n0GetDisplayMediaSetSelectAllScreensAllowedForUrls\x18\xce\x07 \x01(\x0b\x32L.enterprise_management.GetDisplayMediaSetSelectAllScreensAllowedForUrlsProto\x12K\n\x12SessionLengthLimit\x18\xac\x01 \x01(\x0b\x32..enterprise_management.SessionLengthLimitProto\x12I\n\x11\x42rowserThemeColor\x18\xca\x06 \x01(\x0b\x32-.enterprise_management.BrowserThemeColorProto\x12\x81\x01\n-WebAuthenticationRemoteProxiedRequestsAllowed\x18\xc7\x07 \x01(\x0b\x32I.enterprise_management.WebAuthenticationRemoteProxiedRequestsAllowedProto\x12o\n$PromptOnMultipleMatchingCertificates\x18\x8b\x07 \x01(\x0b\x32@.enterprise_management.PromptOnMultipleMatchingCertificatesProto\x12_\n\x1cInsecureFormsWarningsEnabled\x18\xee\x05 \x01(\x0b\x32\x38.enterprise_management.InsecureFormsWarningsEnabledProto\x12\x42\n\x0eGCFUserDataDir\x18Y \x01(\x0b\x32*.enterprise_management.GCFUserDataDirProto\x12]\n\x1bSecondaryGoogleAccountUsage\x18\xbe\x07 \x01(\x0b\x32\x37.enterprise_management.SecondaryGoogleAccountUsageProto\x12O\n\x14PolicyScopeDetection\x18\xdf\x07 \x01(\x0b\x32\x30.enterprise_management.PolicyScopeDetectionProto\x12@\n\rDisable3DAPIs\x18\x39 \x01(\x0b\x32).enterprise_management.Disable3DAPIsProto\x12\x63\n\x1eUnifiedDesktopEnabledByDefault\x18\xb5\x02 \x01(\x0b\x32:.enterprise_management.UnifiedDesktopEnabledByDefaultProto\x12Y\n\x19PaymentMethodQueryEnabled\x18\x8d\x05 \x01(\x0b\x32\x35.enterprise_management.PaymentMethodQueryEnabledProto\x12M\n\x13VideoCaptureAllowed\x18\xa9\x01 \x01(\x0b\x32/.enterprise_management.VideoCaptureAllowedProto\x12\x65\n\x1fLacrosDataBackwardMigrationMode\x18\xf6\x07 \x01(\x0b\x32;.enterprise_management.LacrosDataBackwardMigrationModeProto\x12g\n IntensiveWakeUpThrottlingEnabled\x18\xcb\x05 \x01(\x0b\x32<.enterprise_management.IntensiveWakeUpThrottlingEnabledProto\x12Q\n\x15ShelfAutoHideBehavior\x18\xa8\x01 \x01(\x0b\x32\x31.enterprise_management.ShelfAutoHideBehaviorProto\x12>\n\x0cSyncDisabled\x18\x16 \x01(\x0b\x32(.enterprise_management.SyncDisabledProto\x12>\n\x0c\x44iskCacheDir\x18Z \x01(\x0b\x32(.enterprise_management.DiskCacheDirProto\x12y\n)DataLeakPreventionClipboardCheckSizeLimit\x18\xef\x06 \x01(\x0b\x32\x45.enterprise_management.DataLeakPreventionClipboardCheckSizeLimitProto\x12_\n\x1c\x41\x63\x63\x65ssCodeCastDeviceDuration\x18\x8e\x07 \x01(\x0b\x32\x38.enterprise_management.AccessCodeCastDeviceDurationProto\x12]\n\x1b\x44\x61taLeakPreventionRulesList\x18\x94\x06 \x01(\x0b\x32\x37.enterprise_management.DataLeakPreventionRulesListProto\x12>\n\x0cURLWhitelist\x18j \x01(\x0b\x32(.enterprise_management.URLWhitelistProto\x12s\n&SuppressDifferentOriginSubframeDialogs\x18\xbf\x06 \x01(\x0b\x32\x42.enterprise_management.SuppressDifferentOriginSubframeDialogsProto\x12U\n\x17\x43omponentUpdatesEnabled\x18\xd8\x02 \x01(\x0b\x32\x33.enterprise_management.ComponentUpdatesEnabledProto\x12\x65\n\x1fWebRtcEventLogCollectionAllowed\x18\xd2\x03 \x01(\x0b\x32;.enterprise_management.WebRtcEventLogCollectionAllowedProto\x12]\n\x1b\x45ncryptedClientHelloEnabled\x18\xe6\x07 \x01(\x0b\x32\x37.enterprise_management.EncryptedClientHelloEnabledProto\x12Q\n\x15SyncTypesListDisabled\x18\x8b\x05 \x01(\x0b\x32\x31.enterprise_management.SyncTypesListDisabledProto\x12U\n\x17WebXRImmersiveArEnabled\x18\xb6\x06 \x01(\x0b\x32\x33.enterprise_management.WebXRImmersiveArEnabledProto\x12g\n OptimizationGuideFetchingEnabled\x18\xc5\x07 \x01(\x0b\x32<.enterprise_management.OptimizationGuideFetchingEnabledProto\x12\x61\n\x1d\x45xplicitlyAllowedNetworkPorts\x18\xd3\x06 \x01(\x0b\x32\x39.enterprise_management.ExplicitlyAllowedNetworkPortsProto\x12K\n\x12PinnedLauncherApps\x18\x92\x01 \x01(\x0b\x32..enterprise_management.PinnedLauncherAppsProto\x12M\n\x13\x43\x43TToSDialogEnabled\x18\xfa\x05 \x01(\x0b\x32/.enterprise_management.CCTToSDialogEnabledProto\x12U\n\x17\x41udioCaptureAllowedUrls\x18\xd2\x01 \x01(\x0b\x32\x33.enterprise_management.AudioCaptureAllowedUrlsProto\x12i\n!NoteTakingAppsLockScreenAllowlist\x18\xf9\x05 \x01(\x0b\x32=.enterprise_management.NoteTakingAppsLockScreenAllowlistProto\x12_\n\x1cRoamingProfileSupportEnabled\x18\xe8\x02 \x01(\x0b\x32\x38.enterprise_management.RoamingProfileSupportEnabledProto\x12R\n\x16\x41lwaysAuthorizePlugins\x18X \x01(\x0b\x32\x32.enterprise_management.AlwaysAuthorizePluginsProto\x12S\n\x16PersistentQuotaEnabled\x18\xec\x07 \x01(\x0b\x32\x32.enterprise_management.PersistentQuotaEnabledProto\x12\x43\n\x0eWebAppSettings\x18\xba\x06 \x01(\x0b\x32*.enterprise_management.WebAppSettingsProto\x12K\n\x12\x43lickToCallEnabled\x18\x87\x05 \x01(\x0b\x32..enterprise_management.ClickToCallEnabledProto\x12K\n\x12NearbyShareAllowed\x18\xfb\x05 \x01(\x0b\x32..enterprise_management.NearbyShareAllowedProto\x12Q\n\x15\x41\x63\x63\x65ssCodeCastEnabled\x18\x8d\x07 \x01(\x0b\x32\x31.enterprise_management.AccessCodeCastEnabledProto\x12N\n\x14\x45\x64itBookmarksEnabled\x18U \x01(\x0b\x32\x30.enterprise_management.EditBookmarksEnabledProto\x12\x61\n\x1dWelcomePageOnOSUpgradeEnabled\x18\xb1\x02 \x01(\x0b\x32\x39.enterprise_management.WelcomePageOnOSUpgradeEnabledProto\x12w\n(UnmanagedDeviceSignalsConsentFlowEnabled\x18\xeb\x07 \x01(\x0b\x32\x44.enterprise_management.UnmanagedDeviceSignalsConsentFlowEnabledProto\x12\x91\x01\n5ExemptDomainFileTypePairsFromFileTypeDownloadWarnings\x18\xb5\x07 \x01(\x0b\x32Q.enterprise_management.ExemptDomainFileTypePairsFromFileTypeDownloadWarningsProto\x12]\n\x1bUserAgentClientHintsEnabled\x18\xd7\x05 \x01(\x0b\x32\x37.enterprise_management.UserAgentClientHintsEnabledProto\x12_\n\x1c\x43loudProfileReportingEnabled\x18\xb0\x07 \x01(\x0b\x32\x38.enterprise_management.CloudProfileReportingEnabledProto\x12M\n\x13\x41udioSandboxEnabled\x18\xf5\x04 \x01(\x0b\x32/.enterprise_management.AudioSandboxEnabledProto\x12K\n\x12SpellcheckLanguage\x18\x97\x03 \x01(\x0b\x32..enterprise_management.SpellcheckLanguageProto\x12R\n\x16\x42lockThirdPartyCookies\x18) \x01(\x0b\x32\x32.enterprise_management.BlockThirdPartyCookiesProto\x12@\n\rDiskCacheSize\x18p \x01(\x0b\x32).enterprise_management.DiskCacheSizeProto\x12_\n\x1cNativeWindowOcclusionEnabled\x18\xa5\x05 \x01(\x0b\x32\x38.enterprise_management.NativeWindowOcclusionEnabledProto\x12<\n\x0bUserDataDir\x18\x41 \x01(\x0b\x32\'.enterprise_management.UserDataDirProto\x12^\n\x1cSavingBrowserHistoryDisabled\x18\r \x01(\x0b\x32\x38.enterprise_management.SavingBrowserHistoryDisabledProto\x12X\n\x19\x41llowFileSelectionDialogs\x18V \x01(\x0b\x32\x35.enterprise_management.AllowFileSelectionDialogsProto\x12U\n\x17\x42\x61\x63kForwardCacheEnabled\x18\xf8\x05 \x01(\x0b\x32\x33.enterprise_management.BackForwardCacheEnabledProto\x12G\n\x10\x43hromeVariations\x18\x99\x05 \x01(\x0b\x32,.enterprise_management.ChromeVariationsProto\x12I\n\x11SideSearchEnabled\x18\x8c\x07 \x01(\x0b\x32-.enterprise_management.SideSearchEnabledProto\x12[\n\x1a\x44\x65veloperToolsAvailability\x18\xbd\x03 \x01(\x0b\x32\x36.enterprise_management.DeveloperToolsAvailabilityProto\x12Q\n\x15\x43orsLegacyModeEnabled\x18\xf8\x04 \x01(\x0b\x32\x31.enterprise_management.CorsLegacyModeEnabledProto\x12W\n\x18SpellCheckServiceEnabled\x18\x99\x01 \x01(\x0b\x32\x34.enterprise_management.SpellCheckServiceEnabledProto\x12k\n\"ContextAwareAccessSignalsAllowlist\x18\xbc\x06 \x01(\x0b\x32>.enterprise_management.ContextAwareAccessSignalsAllowlistProto\x12U\n\x17SSLErrorOverrideAllowed\x18\xae\x02 \x01(\x0b\x32\x33.enterprise_management.SSLErrorOverrideAllowedProto\x12<\n\x0b\x44isableSpdy\x18\n \x01(\x0b\x32\'.enterprise_management.DisableSpdyProto\x12\x41\n\rLacrosAllowed\x18\x9b\x06 \x01(\x0b\x32).enterprise_management.LacrosAllowedProto\x12\x45\n\x0fNTPCardsVisible\x18\xa7\x06 \x01(\x0b\x32+.enterprise_management.NTPCardsVisibleProto\x12S\n\x16WebComponentsV0Enabled\x18\x86\x05 \x01(\x0b\x32\x32.enterprise_management.WebComponentsV0EnabledProto\x12H\n\x11\x44ownloadDirectory\x18\x42 \x01(\x0b\x32-.enterprise_management.DownloadDirectoryProto\x12S\n\x16\x46orceEphemeralProfiles\x18\xf7\x01 \x01(\x0b\x32\x32.enterprise_management.ForceEphemeralProfilesProto\x12U\n\x17\x42rowserAddPersonEnabled\x18\x96\x02 \x01(\x0b\x32\x33.enterprise_management.BrowserAddPersonEnabledProto\x12;\n\nRC4Enabled\x18\xb8\x02 \x01(\x0b\x32&.enterprise_management.RC4EnabledProto\x12\x42\n\x0eInstantEnabled\x18@ \x01(\x0b\x32*.enterprise_management.InstantEnabledProto\x12=\n\x0bOsColorMode\x18\xdc\x07 \x01(\x0b\x32\'.enterprise_management.OsColorModeProto\x12i\n!NoteTakingAppsLockScreenWhitelist\x18\xfb\x02 \x01(\x0b\x32=.enterprise_management.NoteTakingAppsLockScreenWhitelistProto\x12I\n\x11\x43hromeAppsEnabled\x18\xfe\x06 \x01(\x0b\x32-.enterprise_management.ChromeAppsEnabledProto\x12y\n)EnterpriseProfileCreationKeepBrowsingData\x18\xe8\x07 \x01(\x0b\x32\x45.enterprise_management.EnterpriseProfileCreationKeepBrowsingDataProto\x12W\n\x18\x44\x65sktopSharingHubEnabled\x18\xe9\x06 \x01(\x0b\x32\x34.enterprise_management.DesktopSharingHubEnabledProto\x12W\n\x18QuickUnlockModeWhitelist\x18\xe2\x02 \x01(\x0b\x32\x34.enterprise_management.QuickUnlockModeWhitelistProto\x12\x45\n\x0fTabUnderAllowed\x18\xb2\x03 \x01(\x0b\x32+.enterprise_management.TabUnderAllowedProto\x12\x61\n\x1d\x43hromeCleanupReportingEnabled\x18\xbc\x03 \x01(\x0b\x32\x39.enterprise_management.ChromeCleanupReportingEnabledProto\x12L\n\x13\x43learSiteDataOnExit\x18\x43 \x01(\x0b\x32/.enterprise_management.ClearSiteDataOnExitProto\x12_\n\x1c\x44NSInterceptionChecksEnabled\x18\x90\x05 \x01(\x0b\x32\x38.enterprise_management.DNSInterceptionChecksEnabledProto\x12\x44\n\x0f\x44isabledSchemes\x18W \x01(\x0b\x32+.enterprise_management.DisabledSchemesProto\x12[\n\x1a\x46loatingWorkspaceV2Enabled\x18\x91\x08 \x01(\x0b\x32\x36.enterprise_management.FloatingWorkspaceV2EnabledProto\x12i\n!SuppressChromeFrameTurndownPrompt\x18\xdf\x01 \x01(\x0b\x32=.enterprise_management.SuppressChromeFrameTurndownPromptProto\x12U\n\x17\x45xternalStorageDisabled\x18\x9a\x01 \x01(\x0b\x32\x33.enterprise_management.ExternalStorageDisabledProto\x12m\n#BrowserLegacyExtensionPointsBlocked\x18\xff\x06 \x01(\x0b\x32?.enterprise_management.BrowserLegacyExtensionPointsBlockedProto\x12Y\n\x19SignedHTTPExchangeEnabled\x18\xa0\x04 \x01(\x0b\x32\x35.enterprise_management.SignedHTTPExchangeEnabledProto\x12u\n\'SecurityTokenSessionNotificationSeconds\x18\xa2\x06 \x01(\x0b\x32\x43.enterprise_management.SecurityTokenSessionNotificationSecondsProto\x12U\n\x17SuggestedContentEnabled\x18\xd8\x05 \x01(\x0b\x32\x33.enterprise_management.SuggestedContentEnabledProto\x12s\n&WebDriverOverridesIncompatiblePolicies\x18\xa0\x03 \x01(\x0b\x32\x42.enterprise_management.WebDriverOverridesIncompatiblePoliciesProto\x12W\n\x18\x41llowNativeNotifications\x18\xa8\x05 \x01(\x0b\x32\x34.enterprise_management.AllowNativeNotificationsProto\x12g\n BrowserNetworkTimeQueriesEnabled\x18\xf4\x02 \x01(\x0b\x32<.enterprise_management.BrowserNetworkTimeQueriesEnabledProto\x12O\n\x14HSTSPolicyBypassList\x18\xdb\x04 \x01(\x0b\x32\x30.enterprise_management.HSTSPolicyBypassListProto\x12[\n\x1aPrefixedStorageInfoEnabled\x18\xee\x07 \x01(\x0b\x32\x36.enterprise_management.PrefixedStorageInfoEnabledProto\x12S\n\x16\x41llowDinosaurEasterEgg\x18\xb7\x02 \x01(\x0b\x32\x32.enterprise_management.AllowDinosaurEasterEggProto\x12X\n\x19\x45xtensionInstallBlacklist\x18\" \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallBlacklistProto\x12\x45\n\x0fWebAuthnFactors\x18\xc6\x07 \x01(\x0b\x32+.enterprise_management.WebAuthnFactorsProto\x12\x65\n\x1f\x41\x63\x63\x65ssibilityImageLabelsEnabled\x18\xc1\x05 \x01(\x0b\x32;.enterprise_management.AccessibilityImageLabelsEnabledProto\x12Q\n\x15\x44ownloadBubbleEnabled\x18\xcc\x07 \x01(\x0b\x32\x31.enterprise_management.DownloadBubbleEnabledProto\x12\x7f\n,ExternalProtocolDialogShowAlwaysOpenCheckbox\x18\xfa\x04 \x01(\x0b\x32H.enterprise_management.ExternalProtocolDialogShowAlwaysOpenCheckboxProto\x12q\n%InsecurePrivateNetworkRequestsAllowed\x18\x80\x06 \x01(\x0b\x32\x41.enterprise_management.InsecurePrivateNetworkRequestsAllowedProto\x12Y\n\x19HighEfficiencyModeEnabled\x18\xf0\x07 \x01(\x0b\x32\x35.enterprise_management.HighEfficiencyModeEnabledProto\x12\x81\x01\n-KeepFullscreenWithoutNotificationUrlAllowList\x18\xa4\x07 \x01(\x0b\x32I.enterprise_management.KeepFullscreenWithoutNotificationUrlAllowListProto\x12\x45\n\x0f\x41llowScreenLock\x18\xcb\x02 \x01(\x0b\x32+.enterprise_management.AllowScreenLockProto\x12J\n\x12ImportSearchEngine\x18\x66 \x01(\x0b\x32..enterprise_management.ImportSearchEngineProto\x12K\n\x12\x43orsMitigationList\x18\xf7\x04 \x01(\x0b\x32..enterprise_management.CorsMitigationListProto\x12Y\n\x19ThirdPartyBlockingEnabled\x18\x99\x03 \x01(\x0b\x32\x35.enterprise_management.ThirdPartyBlockingEnabledProto\x12s\n&DisplayCapturePermissionsPolicyEnabled\x18\xf2\x06 \x01(\x0b\x32\x42.enterprise_management.DisplayCapturePermissionsPolicyEnabledProto\x12\x61\n\x1dWebSQLNonSecureContextEnabled\x18\xe3\x07 \x01(\x0b\x32\x39.enterprise_management.WebSQLNonSecureContextEnabledProto\x12k\n\"EnableSymantecLegacyInfrastructure\x18\x9f\x03 \x01(\x0b\x32>.enterprise_management.EnableSymantecLegacyInfrastructureProto\x12\x7f\n,RequireOnlineRevocationChecksForLocalAnchors\x18\xed\x01 \x01(\x0b\x32H.enterprise_management.RequireOnlineRevocationChecksForLocalAnchorsProto\x12\x61\n\x1dWebRtcAllowLegacyTLSProtocols\x18\x95\x06 \x01(\x0b\x32\x39.enterprise_management.WebRtcAllowLegacyTLSProtocolsProto\x12U\n\x17LensRegionSearchEnabled\x18\xf8\x06 \x01(\x0b\x32\x33.enterprise_management.LensRegionSearchEnabledProto\x12}\n+ForceMajorVersionToMinorPositionInUserAgent\x18\xb7\x07 \x01(\x0b\x32G.enterprise_management.ForceMajorVersionToMinorPositionInUserAgentProto\x12S\n\x16RoamingProfileLocation\x18\xe9\x02 \x01(\x0b\x32\x32.enterprise_management.RoamingProfileLocationProto\x12\x41\n\rCECPQ2Enabled\x18\xcb\x06 \x01(\x0b\x32).enterprise_management.CECPQ2EnabledProto\x12\x65\n\x1fLensCameraAssistedSearchEnabled\x18\xd7\x06 \x01(\x0b\x32;.enterprise_management.LensCameraAssistedSearchEnabledProto\x12X\n\x19\x45xtensionInstallWhitelist\x18# \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallWhitelistProto\x12\x63\n\x1eHttp09OnNonDefaultPortsEnabled\x18\xdb\x02 \x01(\x0b\x32:.enterprise_management.Http09OnNonDefaultPortsEnabledProto\x12\x63\n\x1eSandboxExternalProtocolBlocked\x18\x93\x07 \x01(\x0b\x32:.enterprise_management.SandboxExternalProtocolBlockedProto\x12S\n\x16SharedClipboardEnabled\x18\xe4\x04 \x01(\x0b\x32\x32.enterprise_management.SharedClipboardEnabledProto\x12k\n\"CloudManagementEnrollmentMandatory\x18\xfb\x03 \x01(\x0b\x32>.enterprise_management.CloudManagementEnrollmentMandatoryProto\x12u\n\'EnableCommonNameFallbackForLocalAnchors\x18\xf0\x02 \x01(\x0b\x32\x43.enterprise_management.EnableCommonNameFallbackForLocalAnchorsProto\x12g\n ForceLegacyDefaultReferrerPolicy\x18\x8a\x05 \x01(\x0b\x32<.enterprise_management.ForceLegacyDefaultReferrerPolicyProto\x12\x45\n\x0fUserAvatarImage\x18\xfb\x01 \x01(\x0b\x32+.enterprise_management.UserAvatarImageProto\x12u\n\'UrlKeyedAnonymizedDataCollectionEnabled\x18\xcf\x03 \x01(\x0b\x32\x43.enterprise_management.UrlKeyedAnonymizedDataCollectionEnabledProto\x12m\n#SuggestLogoutAfterClosingLastWindow\x18\xd5\x06 \x01(\x0b\x32?.enterprise_management.SuggestLogoutAfterClosingLastWindowProto\x12Q\n\x15\x41llowedDomainsForApps\x18\xcd\x02 \x01(\x0b\x32\x31.enterprise_management.AllowedDomainsForAppsProto\x12>\n\x0cURLBlacklist\x18i \x01(\x0b\x32(.enterprise_management.URLBlacklistProto\x12Y\n\x19\x41utofillCreditCardEnabled\x18\x8a\x03 \x01(\x0b\x32\x35.enterprise_management.AutofillCreditCardEnabledProto\x12@\n\rProxySettings\x18v \x01(\x0b\x32).enterprise_management.ProxySettingsProto\x12\x43\n\x0eIsolateOrigins\x18\x90\x03 \x01(\x0b\x32*.enterprise_management.IsolateOriginsProto\x12{\n*StrictMimetypeCheckForWorkerScriptsEnabled\x18\xf7\x07 \x01(\x0b\x32\x46.enterprise_management.StrictMimetypeCheckForWorkerScriptsEnabledProto\x12U\n\x17RestrictSigninToPattern\x18\x95\x01 \x01(\x0b\x32\x33.enterprise_management.RestrictSigninToPatternProto\x12{\n*SharedArrayBufferUnrestrictedAccessAllowed\x18\xd6\x06 \x01(\x0b\x32\x46.enterprise_management.SharedArrayBufferUnrestrictedAccessAllowedProto\x12K\n\x12\x46ullRestoreEnabled\x18\x83\x07 \x01(\x0b\x32..enterprise_management.FullRestoreEnabledProto\x12O\n\x14\x44\x65skTemplatesEnabled\x18\x90\x07 \x01(\x0b\x32\x30.enterprise_management.DeskTemplatesEnabledProto\x12Y\n\x19PromptForDownloadLocation\x18\x8d\x03 \x01(\x0b\x32\x35.enterprise_management.PromptForDownloadLocationProto\x12[\n\x1aOnPrintEnterpriseConnector\x18\xa5\x07 \x01(\x0b\x32\x36.enterprise_management.OnPrintEnterpriseConnectorProto\x12M\n\x13\x41udioCaptureAllowed\x18\xa2\x01 \x01(\x0b\x32/.enterprise_management.AudioCaptureAllowedProto\x12X\n\x19IncognitoModeAvailability\x18_ \x01(\x0b\x32\x35.enterprise_management.IncognitoModeAvailabilityProto\x12\x63\n\x1e\x44\x65skAPIThirdPartyAccessEnabled\x18\xfd\x07 \x01(\x0b\x32:.enterprise_management.DeskAPIThirdPartyAccessEnabledProto\x12i\n!SSLErrorOverrideAllowedForOrigins\x18\xb5\x06 \x01(\x0b\x32=.enterprise_management.SSLErrorOverrideAllowedForOriginsProto\x12\x43\n\x0eSitePerProcess\x18\x91\x03 \x01(\x0b\x32*.enterprise_management.SitePerProcessProto\x12w\n(GaiaLockScreenOfflineSigninTimeLimitDays\x18\xc3\x06 \x01(\x0b\x32\x44.enterprise_management.GaiaLockScreenOfflineSigninTimeLimitDaysProto\x12W\n\x18\x46loatingWorkspaceEnabled\x18\xc1\x07 \x01(\x0b\x32\x34.enterprise_management.FloatingWorkspaceEnabledProto\x12K\n\x12WebRtcUdpPortRange\x18\xd5\x02 \x01(\x0b\x32..enterprise_management.WebRtcUdpPortRangeProto\x12S\n\x16RemoteDebuggingAllowed\x18\xe2\x06 \x01(\x0b\x32\x32.enterprise_management.RemoteDebuggingAllowedProto\x12\x63\n\x1ePrintingAPIExtensionsWhitelist\x18\x9a\x05 \x01(\x0b\x32:.enterprise_management.PrintingAPIExtensionsWhitelistProto\x12\x45\n\x0fUserDisplayName\x18\xab\x01 \x01(\x0b\x32+.enterprise_management.UserDisplayNameProto\x12[\n\x1aReportCrostiniUsageEnabled\x18\xe6\x03 \x01(\x0b\x32\x36.enterprise_management.ReportCrostiniUsageEnabledProto\x12i\n!OnFileAttachedEnterpriseConnector\x18\xb7\x05 \x01(\x0b\x32=.enterprise_management.OnFileAttachedEnterpriseConnectorProto\x12\x63\n\x1e\x43\x41\x43\x65rtificateManagementAllowed\x18\xc5\x04 \x01(\x0b\x32:.enterprise_management.CACertificateManagementAllowedProto\x12\x61\n\x1d\x45xternalPrintServersWhitelist\x18\xf9\x04 \x01(\x0b\x32\x39.enterprise_management.ExternalPrintServersWhitelistProto\x12{\n*AmbientAuthenticationInPrivateModesEnabled\x18\x8c\x05 \x01(\x0b\x32\x46.enterprise_management.AmbientAuthenticationInPrivateModesEnabledProto\x12O\n\x14\x46orceYouTubeRestrict\x18\xde\x02 \x01(\x0b\x32\x30.enterprise_management.ForceYouTubeRestrictProto\x12S\n\x16\x43opyPreventionSettings\x18\xa2\x07 \x01(\x0b\x32\x32.enterprise_management.CopyPreventionSettingsProto\x12=\n\x0bQuicAllowed\x18\xaf\x02 \x01(\x0b\x32\'.enterprise_management.QuicAllowedProto\x12S\n\x16\x45mojiSuggestionEnabled\x18\xd3\x05 \x01(\x0b\x32\x32.enterprise_management.EmojiSuggestionEnabledProto\x12u\n\'DeviceLocalAccountManagedSessionEnabled\x18\xd1\x03 \x01(\x0b\x32\x43.enterprise_management.DeviceLocalAccountManagedSessionEnabledProto\x12g\n NTPMiddleSlotAnnouncementVisible\x18\xaf\x07 \x01(\x0b\x32<.enterprise_management.NTPMiddleSlotAnnouncementVisibleProto\x12N\n\x14\x41llowOutdatedPlugins\x18S \x01(\x0b\x32\x30.enterprise_management.AllowOutdatedPluginsProto\x12I\n\x11SpellcheckEnabled\x18\x9a\x03 \x01(\x0b\x32-.enterprise_management.SpellcheckEnabledProto\x12m\n#ExtensionInstallEventLoggingEnabled\x18\xd9\x05 \x01(\x0b\x32?.enterprise_management.ExtensionInstallEventLoggingEnabledProto\x12O\n\x14\x42rowsingDataLifetime\x18\x99\x06 \x01(\x0b\x32\x30.enterprise_management.BrowsingDataLifetimeProto\x12u\n\'CaptivePortalAuthenticationIgnoresProxy\x18\xa9\x02 \x01(\x0b\x32\x43.enterprise_management.CaptivePortalAuthenticationIgnoresProxyProto\x12[\n\x1aNTPCustomBackgroundEnabled\x18\x8f\x05 \x01(\x0b\x32\x36.enterprise_management.NTPCustomBackgroundEnabledProto\x12S\n\x16SmartLockSigninAllowed\x18\xea\x03 \x01(\x0b\x32\x32.enterprise_management.SmartLockSigninAllowedProto\x12R\n\x16\x44\x65veloperToolsDisabled\x18& \x01(\x0b\x32\x32.enterprise_management.DeveloperToolsDisabledProto\x12Q\n\x15WPADQuickCheckEnabled\x18\x87\x02 \x01(\x0b\x32\x31.enterprise_management.WPADQuickCheckEnabledProto\x12_\n\x1c\x42\x61tterySaverModeAvailability\x18\xf3\x07 \x01(\x0b\x32\x38.enterprise_management.BatterySaverModeAvailabilityProto\x12K\n\x12UserAgentReduction\x18\xa6\x07 \x01(\x0b\x32..enterprise_management.UserAgentReductionProto\x12G\n\x10HideWebStoreIcon\x18\xbf\x01 \x01(\x0b\x32,.enterprise_management.HideWebStoreIconProto\x12W\n\x18InsightsExtensionEnabled\x18\xd1\x07 \x01(\x0b\x32\x34.enterprise_management.InsightsExtensionEnabledProto\x12I\n\x11\x41utoplayWhitelist\x18\xb1\x03 \x01(\x0b\x32-.enterprise_management.AutoplayWhitelistProto\x12\x41\n\rSSLVersionMin\x18\x99\x02 \x01(\x0b\x32).enterprise_management.SSLVersionMinProto\x12\x43\n\x0eSessionLocales\x18\x94\x02 \x01(\x0b\x32*.enterprise_management.SessionLocalesProto\x12[\n\x1aRestrictAccountsToPatterns\x18\x9c\x03 \x01(\x0b\x32\x36.enterprise_management.RestrictAccountsToPatternsProto\x12Y\n\x19MaxInvalidationFetchDelay\x18\xe6\x01 \x01(\x0b\x32\x35.enterprise_management.MaxInvalidationFetchDelayProto\x12[\n\x1a\x44\x65skAPIThirdPartyAllowlist\x18\x81\x08 \x01(\x0b\x32\x36.enterprise_management.DeskAPIThirdPartyAllowlistProto\x12q\n%VirtualKeyboardResizesLayoutByDefault\x18\x82\x08 \x01(\x0b\x32\x41.enterprise_management.VirtualKeyboardResizesLayoutByDefaultProto\x12?\n\x0cWebSQLAccess\x18\xc8\x07 \x01(\x0b\x32(.enterprise_management.WebSQLAccessProto\x12\x7f\n,OverrideSecurityRestrictionsOnInsecureOrigin\x18\xcb\x03 \x01(\x0b\x32H.enterprise_management.OverrideSecurityRestrictionsOnInsecureOriginProto\x12\x63\n\x1e\x41\x64sSettingForIntrusiveAdsSites\x18\x9b\x03 \x01(\x0b\x32:.enterprise_management.AdsSettingForIntrusiveAdsSitesProto\x12V\n\x18OpenNetworkConfiguration\x18m \x01(\x0b\x32\x34.enterprise_management.OpenNetworkConfigurationProto\x12Q\n\x15\x44nsOverHttpsTemplates\x18\x84\x05 \x01(\x0b\x32\x31.enterprise_management.DnsOverHttpsTemplatesProto\x12X\n\x19\x44isabledPluginsExceptions\x18Q \x01(\x0b\x32\x35.enterprise_management.DisabledPluginsExceptionsProto\x12Q\n\x15UseLegacyFormControls\x18\xad\x05 \x01(\x0b\x32\x31.enterprise_management.UseLegacyFormControlsProto\x12g\n DisableSafeBrowsingProceedAnyway\x18\x98\x01 \x01(\x0b\x32<.enterprise_management.DisableSafeBrowsingProceedAnywayProto\x12\x45\n\x0f\x46orcedLanguages\x18\xc9\x06 \x01(\x0b\x32+.enterprise_management.ForcedLanguagesProto\x12^\n\x1c\x44\x65\x66\x61ultBrowserSettingEnabled\x18\x05 \x01(\x0b\x32\x38.enterprise_management.DefaultBrowserSettingEnabledProto\x12i\n!LoginDisplayPasswordButtonEnabled\x18\xbf\x05 \x01(\x0b\x32=.enterprise_management.LoginDisplayPasswordButtonEnabledProto\x12]\n\x1b\x41llowDeletingBrowserHistory\x18\xbd\x01 \x01(\x0b\x32\x37.enterprise_management.AllowDeletingBrowserHistoryProto\x12]\n\x1bSpellcheckLanguageBlacklist\x18\x9a\x04 \x01(\x0b\x32\x37.enterprise_management.SpellcheckLanguageBlacklistProto\x12]\n\x1bTouchVirtualKeyboardEnabled\x18\x8f\x02 \x01(\x0b\x32\x37.enterprise_management.TouchVirtualKeyboardEnabledProto\x12\x7f\n,InsecurePrivateNetworkRequestsAllowedForUrls\x18\x81\x06 \x01(\x0b\x32H.enterprise_management.InsecurePrivateNetworkRequestsAllowedForUrlsProto\x12L\n\x13\x41uthServerWhitelist\x18\x1f \x01(\x0b\x32/.enterprise_management.AuthServerWhitelistProto\x12S\n\x16\x41utoOpenAllowedForURLs\x18\xc5\x05 \x01(\x0b\x32\x32.enterprise_management.AutoOpenAllowedForURLsProto\x12I\n\x11\x41utoOpenFileTypes\x18\xbe\x05 \x01(\x0b\x32-.enterprise_management.AutoOpenFileTypesProto\x12m\n#EnableDeprecatedWebPlatformFeatures\x18\x90\x02 \x01(\x0b\x32?.enterprise_management.EnableDeprecatedWebPlatformFeaturesProto\x12S\n\x16VmManagementCliAllowed\x18\xc3\x04 \x01(\x0b\x32\x32.enterprise_management.VmManagementCliAllowedProto\x12o\n$StartupBrowserWindowLaunchSuppressed\x18\xba\x04 \x01(\x0b\x32@.enterprise_management.StartupBrowserWindowLaunchSuppressedProto\x12Y\n\x19PhoneHubCameraRollAllowed\x18\xaa\x07 \x01(\x0b\x32\x35.enterprise_management.PhoneHubCameraRollAllowedProto\x12Y\n\x19SigninInterceptionEnabled\x18\xad\x06 \x01(\x0b\x32\x35.enterprise_management.SigninInterceptionEnabledProto\x12]\n\x1bMediaRecommendationsEnabled\x18\x96\x06 \x01(\x0b\x32\x37.enterprise_management.MediaRecommendationsEnabledProto\x12\x63\n\x1eLockScreenMediaPlaybackEnabled\x18\xc7\x04 \x01(\x0b\x32:.enterprise_management.LockScreenMediaPlaybackEnabledProto\x12K\n\x12LacrosAvailability\x18\xd9\x06 \x01(\x0b\x32..enterprise_management.LacrosAvailabilityProto\x12_\n\x1cNetworkServiceSandboxEnabled\x18\x8f\x07 \x01(\x0b\x32\x38.enterprise_management.NetworkServiceSandboxEnabledProto\x12\x45\n\x0fPhoneHubAllowed\x18\x9d\x06 \x01(\x0b\x32+.enterprise_management.PhoneHubAllowedProto\x12K\n\x12GhostWindowEnabled\x18\x84\x07 \x01(\x0b\x32..enterprise_management.GhostWindowEnabledProto\x12_\n\x1cSafeBrowsingWhitelistDomains\x18\xa8\x03 \x01(\x0b\x32\x38.enterprise_management.SafeBrowsingWhitelistDomainsProto\x12\x42\n\x0eMediaCacheSize\x18q \x01(\x0b\x32*.enterprise_management.MediaCacheSizeProto\x12\x44\n\x0f\x41utoFillEnabled\x18\x14 \x01(\x0b\x32+.enterprise_management.AutoFillEnabledProto\x12Y\n\x19WebRtcLocalIpsAllowedUrls\x18\x82\x05 \x01(\x0b\x32\x35.enterprise_management.WebRtcLocalIpsAllowedUrlsProto\x12H\n\x11HideWebStorePromo\x18\x62 \x01(\x0b\x32-.enterprise_management.HideWebStorePromoProto\x12k\n\"OnSecurityEventEnterpriseConnector\x18\xbd\x05 \x01(\x0b\x32>.enterprise_management.OnSecurityEventEnterpriseConnectorProto\x12U\n\x17\x42uiltInDnsClientEnabled\x18\xa7\x01 \x01(\x0b\x32\x33.enterprise_management.BuiltInDnsClientEnabledProto\x12\x65\n\x1f\x41udioProcessHighPriorityEnabled\x18\xc6\x06 \x01(\x0b\x32;.enterprise_management.AudioProcessHighPriorityEnabledProto\x12L\n\x13\x44isablePluginFinder\x18\x44 \x01(\x0b\x32/.enterprise_management.DisablePluginFinderProto\x12S\n\x16HistoryClustersVisible\x18\xa0\x07 \x01(\x0b\x32\x32.enterprise_management.HistoryClustersVisibleProto\x12K\n\x12SmsMessagesAllowed\x18\xd7\x03 \x01(\x0b\x32..enterprise_management.SmsMessagesAllowedProto\x12?\n\x0cURLBlocklist\x18\xe2\x05 \x01(\x0b\x32(.enterprise_management.URLBlocklistProto\x12_\n\x1c\x43ontextualSuggestionsEnabled\x18\xc6\x03 \x01(\x0b\x32\x38.enterprise_management.ContextualSuggestionsEnabledProto\x12X\n\x19\x43hromeOsLockOnIdleSuspend\x18? \x01(\x0b\x32\x35.enterprise_management.ChromeOsLockOnIdleSuspendProto\x12Y\n\x19SystemFeaturesDisableMode\x18\xa9\x06 \x01(\x0b\x32\x35.enterprise_management.SystemFeaturesDisableModeProto\x12I\n\x11TermsOfServiceURL\x18\xbc\x01 \x01(\x0b\x32-.enterprise_management.TermsOfServiceURLProto\x12G\n\x10\x44nsOverHttpsMode\x18\xc8\x04 \x01(\x0b\x32,.enterprise_management.DnsOverHttpsModeProto\x12K\n\x12\x46orceBrowserSignin\x18\xdc\x02 \x01(\x0b\x32..enterprise_management.ForceBrowserSigninProto\x12\x41\n\rBrowserSignin\x18\xe9\x03 \x01(\x0b\x32).enterprise_management.BrowserSigninProto\x12Y\n\x19\x45nableSha1ForLocalAnchors\x18\xd6\x02 \x01(\x0b\x32\x35.enterprise_management.EnableSha1ForLocalAnchorsProto\x12K\n\x12TotalMemoryLimitMb\x18\xea\x04 \x01(\x0b\x32..enterprise_management.TotalMemoryLimitMbProto\x12S\n\x16ImportAutofillFormData\x18\x97\x02 \x01(\x0b\x32\x32.enterprise_management.ImportAutofillFormDataProto\x12S\n\x16\x41utofillAddressEnabled\x18\xcd\x03 \x01(\x0b\x32\x32.enterprise_management.AutofillAddressEnabledProto\x12i\n!PolicyListMultipleSourceMergeList\x18\xac\x04 \x01(\x0b\x32=.enterprise_management.PolicyListMultipleSourceMergeListProto\x12\x81\x01\n-DefaultSearchProviderContextMenuAccessAllowed\x18\xcd\x05 \x01(\x0b\x32I.enterprise_management.DefaultSearchProviderContextMenuAccessAllowedProto\x12P\n\x15\x45nterpriseWebStoreURL\x18r \x01(\x0b\x32\x31.enterprise_management.EnterpriseWebStoreURLProto\x12?\n\x0cURLAllowlist\x18\xe3\x05 \x01(\x0b\x32(.enterprise_management.URLAllowlistProto\x12]\n\x1bNativePrintersBulkBlacklist\x18\x82\x03 \x01(\x0b\x32\x37.enterprise_management.NativePrintersBulkBlacklistProto\x12I\n\x11ScreenTimeEnabled\x18\xd8\x07 \x01(\x0b\x32-.enterprise_management.ScreenTimeEnabledProto\x12_\n\x1cRendererCodeIntegrityEnabled\x18\xd8\x04 \x01(\x0b\x32\x38.enterprise_management.RendererCodeIntegrityEnabledProto\x12Y\n\x19WarnBeforeQuittingEnabled\x18\xcf\x07 \x01(\x0b\x32\x35.enterprise_management.WarnBeforeQuittingEnabledProto\x12[\n\x1aTargetBlankImpliesNoOpener\x18\xa4\x06 \x01(\x0b\x32\x36.enterprise_management.TargetBlankImpliesNoOpenerProto\x12\x45\n\x0f\x41utoplayAllowed\x18\xb0\x03 \x01(\x0b\x32+.enterprise_management.AutoplayAllowedProto\x12s\n&CommandLineFlagSecurityWarningsEnabled\x18\xb8\x04 \x01(\x0b\x32\x42.enterprise_management.CommandLineFlagSecurityWarningsEnabledProto\x12S\n\x16\x43hromeRootStoreEnabled\x18\xe2\x07 \x01(\x0b\x32\x32.enterprise_management.ChromeRootStoreEnabledProto\x12H\n\x11PolicyRefreshRate\x18: \x01(\x0b\x32-.enterprise_management.PolicyRefreshRateProto\x12g\n WebSQLInThirdPartyContextEnabled\x18\x88\x07 \x01(\x0b\x32<.enterprise_management.WebSQLInThirdPartyContextEnabledProto\x12\x87\x01\n0CertificateTransparencyEnforcementDisabledForCas\x18\xb5\x03 \x01(\x0b\x32L.enterprise_management.CertificateTransparencyEnforcementDisabledForCasProto\x12W\n\x18NativeMessagingBlacklist\x18\xfd\x01 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingBlacklistProto\x12S\n\x16\x46ullscreenAlertEnabled\x18\xa6\x06 \x01(\x0b\x32\x32.enterprise_management.FullscreenAlertEnabledProto\x12\x63\n\x1eLacrosSecondaryProfilesAllowed\x18\xc2\x06 \x01(\x0b\x32:.enterprise_management.LacrosSecondaryProfilesAllowedProto\x12O\n\x14\x43loudUserPolicyMerge\x18\xdd\x06 \x01(\x0b\x32\x30.enterprise_management.CloudUserPolicyMergeProto\x12H\n\x11JavascriptEnabled\x18\x0b \x01(\x0b\x32-.enterprise_management.JavascriptEnabledProto\x12W\n\x18\x41llowSystemNotifications\x18\xbe\x06 \x01(\x0b\x32\x34.enterprise_management.AllowSystemNotificationsProto\x12u\n\'PolicyDictionaryMultipleSourceMergeList\x18\xb7\x04 \x01(\x0b\x32\x43.enterprise_management.PolicyDictionaryMultipleSourceMergeListProto\x12\x65\n\x1f\x41llowWebAuthnWithBrokenTlsCerts\x18\x87\x08 \x01(\x0b\x32;.enterprise_management.AllowWebAuthnWithBrokenTlsCertsProto\x12\x45\n\x0f\x46orceSafeSearch\x18\xa4\x01 \x01(\x0b\x32+.enterprise_management.ForceSafeSearchProto\x12o\n$EnterpriseHardwarePlatformAPIEnabled\x18\xe5\x03 \x01(\x0b\x32@.enterprise_management.EnterpriseHardwarePlatformAPIEnabledProto\x12\x61\n\x1dShowAppsShortcutInBookmarkBar\x18\x8d\x02 \x01(\x0b\x32\x39.enterprise_management.ShowAppsShortcutInBookmarkBarProto\x12\x61\n\x1dManagedConfigurationPerOrigin\x18\xaf\x06 \x01(\x0b\x32\x39.enterprise_management.ManagedConfigurationPerOriginProto\x12\x41\n\rSigninAllowed\x18\xc0\x01 \x01(\x0b\x32).enterprise_management.SigninAllowedProto\x12I\n\x11TosDialogBehavior\x18\xa3\x06 \x01(\x0b\x32-.enterprise_management.TosDialogBehaviorProto\x12o\n$StricterMixedContentTreatmentEnabled\x18\x8e\x05 \x01(\x0b\x32@.enterprise_management.StricterMixedContentTreatmentEnabledProto\x12i\n!DeviceAttributesAllowedForOrigins\x18\xe3\x06 \x01(\x0b\x32=.enterprise_management.DeviceAttributesAllowedForOriginsProto\x12Q\n\x15\x46orceNetworkInProcess\x18\x8b\x04 \x01(\x0b\x32\x31.enterprise_management.ForceNetworkInProcessProto\x12o\n$TLS13HardeningForLocalAnchorsEnabled\x18\xf4\x04 \x01(\x0b\x32@.enterprise_management.TLS13HardeningForLocalAnchorsEnabledProto\x12o\n$SafeBrowsingForTrustedSourcesEnabled\x18\xf9\x02 \x01(\x0b\x32@.enterprise_management.SafeBrowsingForTrustedSourcesEnabledProto\x12_\n\x1cSecurityKeyPermitAttestation\x18\x94\x03 \x01(\x0b\x32\x38.enterprise_management.SecurityKeyPermitAttestationProto\x12K\n\x12TabFreezingEnabled\x18\xce\x03 \x01(\x0b\x32..enterprise_management.TabFreezingEnabledProto\x12\x44\n\x0fImportBookmarks\x18\x63 \x01(\x0b\x32+.enterprise_management.ImportBookmarksProto\x12i\n!OnFileTransferEnterpriseConnector\x18\xe1\x07 \x01(\x0b\x32=.enterprise_management.OnFileTransferEnterpriseConnectorProto\x12i\n!GloballyScopeHTTPAuthCacheEnabled\x18\x85\x05 \x01(\x0b\x32=.enterprise_management.GloballyScopeHTTPAuthCacheEnabledProto\x12\x45\n\x0f\x46\x61stPairEnabled\x18\x92\x07 \x01(\x0b\x32+.enterprise_management.FastPairEnabledProto\x12W\n\x18\x41llowChromeDataInBackups\x18\xca\x07 \x01(\x0b\x32\x34.enterprise_management.AllowChromeDataInBackupsProto\x12g\n OriginAgentClusterDefaultEnabled\x18\xa7\x07 \x01(\x0b\x32<.enterprise_management.OriginAgentClusterDefaultEnabledProto\x12W\n\x18\x44\x65\x66\x61ultDownloadDirectory\x18\x93\x03 \x01(\x0b\x32\x34.enterprise_management.DefaultDownloadDirectoryProto\x12Y\n\x19SystemFeaturesDisableList\x18\xb3\x05 \x01(\x0b\x32\x35.enterprise_management.SystemFeaturesDisableListProto\x12\x87\x01\n0ManagedGuestSessionAutoLaunchNotificationReduced\x18\xb2\x05 \x01(\x0b\x32L.enterprise_management.ManagedGuestSessionAutoLaunchNotificationReducedProto\x12]\n\x1bLensDesktopNTPSearchEnabled\x18\x85\x08 \x01(\x0b\x32\x37.enterprise_management.LensDesktopNTPSearchEnabledProto\x12u\n\'UserAgentClientHintsGREASEUpdateEnabled\x18\x9e\x07 \x01(\x0b\x32\x43.enterprise_management.UserAgentClientHintsGREASEUpdateEnabledProto\x12m\n#OnFileDownloadedEnterpriseConnector\x18\xba\x05 \x01(\x0b\x32?.enterprise_management.OnFileDownloadedEnterpriseConnectorProto\x12Q\n\x15SSLVersionFallbackMin\x18\x9a\x02 \x01(\x0b\x32\x31.enterprise_management.SSLVersionFallbackMinProto\x12\x63\n\x1e\x45nableDeprecatedWebBasedSignin\x18\x8b\x02 \x01(\x0b\x32:.enterprise_management.EnableDeprecatedWebBasedSigninProto\x12]\n\x1bVariationsRestrictParameter\x18\xc6\x01 \x01(\x0b\x32\x37.enterprise_management.VariationsRestrictParameterProto\x12{\n*CrossOriginWebAssemblyModuleSharingEnabled\x18\xf0\x06 \x01(\x0b\x32\x46.enterprise_management.CrossOriginWebAssemblyModuleSharingEnabledProto\x12\x63\n\x1e\x43loudManagementEnrollmentToken\x18\x80\x04 \x01(\x0b\x32:.enterprise_management.CloudManagementEnrollmentTokenProto\x12T\n\x17MetricsReportingEnabled\x18\x11 \x01(\x0b\x32\x33.enterprise_management.MetricsReportingEnabledProto\x12M\n\x13ShoppingListEnabled\x18\xfc\x07 \x01(\x0b\x32/.enterprise_management.ShoppingListEnabledProto\x12Q\n\x15UrlParamFilterEnabled\x18\xd7\x07 \x01(\x0b\x32\x31.enterprise_management.UrlParamFilterEnabledProto\x12k\n\"OnBulkDataEntryEnterpriseConnector\x18\xbb\x05 \x01(\x0b\x32>.enterprise_management.OnBulkDataEntryEnterpriseConnectorProto\x12\x65\n\x1fPhoneHubTaskContinuationAllowed\x18\x9f\x06 \x01(\x0b\x32;.enterprise_management.PhoneHubTaskContinuationAllowedProto\x12R\n\x16\x45nterpriseWebStoreName\x18s \x01(\x0b\x32\x32.enterprise_management.EnterpriseWebStoreNameProto\x12\x8d\x01\n3CoalesceH2ConnectionsWithClientCertificatesForHosts\x18\xd4\x03 \x01(\x0b\x32O.enterprise_management.CoalesceH2ConnectionsWithClientCertificatesForHostsProto\x12[\n\x1aPreconfiguredDeskTemplates\x18\x91\x07 \x01(\x0b\x32\x36.enterprise_management.PreconfiguredDeskTemplatesProto\x12G\n\x10TripleDESEnabled\x18\xdc\x06 \x01(\x0b\x32,.enterprise_management.TripleDESEnabledProto\x12_\n\x1cSuppressUnsupportedOSWarning\x18\xc6\x02 \x01(\x0b\x32\x38.enterprise_management.SuppressUnsupportedOSWarningProto\x12G\n\x10ManagedBookmarks\x18\xe5\x01 \x01(\x0b\x32,.enterprise_management.ManagedBookmarksProto\x12i\n!BuiltinCertificateVerifierEnabled\x18\xc1\x04 \x01(\x0b\x32=.enterprise_management.BuiltinCertificateVerifierEnabledProto\x12I\n\x11\x46ullscreenAllowed\x18\xf2\x01 \x01(\x0b\x32-.enterprise_management.FullscreenAllowedProto\x12Q\n\x15LocalDiscoveryEnabled\x18\x98\x05 \x01(\x0b\x32\x31.enterprise_management.LocalDiscoveryEnabledProto\x12{\n*MachineLevelUserCloudPolicyEnrollmentToken\x18\xae\x03 \x01(\x0b\x32\x46.enterprise_management.MachineLevelUserCloudPolicyEnrollmentTokenProto\x12\x46\n\x10TranslateEnabled\x18R \x01(\x0b\x32,.enterprise_management.TranslateEnabledProto\x12S\n\x16WifiSyncAndroidAllowed\x18\xa0\x06 \x01(\x0b\x32\x32.enterprise_management.WifiSyncAndroidAllowedProto\x12_\n\x1cNTPContentSuggestionsEnabled\x18\xd4\x02 \x01(\x0b\x32\x38.enterprise_management.NTPContentSuggestionsEnabledProto\x12U\n\x17InstantTetheringAllowed\x18\xf1\x02 \x01(\x0b\x32\x33.enterprise_management.InstantTetheringAllowedProto\x12]\n\x1b\x41llowSyncXHRInPageDismissal\x18\xde\x04 \x01(\x0b\x32\x37.enterprise_management.AllowSyncXHRInPageDismissalProto\x12W\n\x18PrimaryMouseButtonSwitch\x18\x91\x05 \x01(\x0b\x32\x34.enterprise_management.PrimaryMouseButtonSwitchProto\x12Q\n\x15RelaunchHeadsUpPeriod\x18\xb9\x04 \x01(\x0b\x32\x31.enterprise_management.RelaunchHeadsUpPeriodProto\x12Q\n\x15\x42\x61\x63kgroundModeEnabled\x18\x8c\x01 \x01(\x0b\x32\x31.enterprise_management.BackgroundModeEnabledProto\x12W\n\x18ShowFullUrlsInAddressBar\x18\xe5\x05 \x01(\x0b\x32\x34.enterprise_management.ShowFullUrlsInAddressBarProto\x12Q\n\x15\x46orceGoogleSafeSearch\x18\x9c\x02 \x01(\x0b\x32\x31.enterprise_management.ForceGoogleSafeSearchProto\x12W\n\x18NativeMessagingWhitelist\x18\xfe\x01 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingWhitelistProto\x12[\n\x1a\x45nableExperimentalPolicies\x18\xc9\x05 \x01(\x0b\x32\x36.enterprise_management.EnableExperimentalPoliciesProto\x12\x43\n\x0eKeyPermissions\x18\xb0\x02 \x01(\x0b\x32*.enterprise_management.KeyPermissionsProto\x12\x65\n\x1fUnthrottledNestedTimeoutEnabled\x18\xde\x07 \x01(\x0b\x32;.enterprise_management.UnthrottledNestedTimeoutEnabledProto\x12S\n\x16WebAppInstallForceList\x18\xd6\x03 \x01(\x0b\x32\x32.enterprise_management.WebAppInstallForceListProto\x12U\n\x17\x41lwaysOpenPdfExternally\x18\xdd\x02 \x01(\x0b\x32\x33.enterprise_management.AlwaysOpenPdfExternallyProto\x12G\n\x10\x41llowedLanguages\x18\xbe\x03 \x01(\x0b\x32,.enterprise_management.AllowedLanguagesProto\x12I\n\x11\x41utoplayAllowlist\x18\xe8\x05 \x01(\x0b\x32-.enterprise_management.AutoplayAllowlistProto\x12{\n*SendMouseEventsDisabledFormControlsEnabled\x18\x8a\x08 \x01(\x0b\x32\x46.enterprise_management.SendMouseEventsDisabledFormControlsEnabledProto\x12U\n\x17TabDiscardingExceptions\x18\xf4\x07 \x01(\x0b\x32\x33.enterprise_management.TabDiscardingExceptionsProto\x12}\n+ThrottleNonVisibleCrossOriginIframesAllowed\x18\x8f\x08 \x01(\x0b\x32G.enterprise_management.ThrottleNonVisibleCrossOriginIframesAllowedProto\x12S\n\x16WindowOcclusionEnabled\x18\xb3\x06 \x01(\x0b\x32\x32.enterprise_management.WindowOcclusionEnabledProto\x12S\n\x16RunAllFlashInAllowMode\x18\x89\x03 \x01(\x0b\x32\x32.enterprise_management.RunAllFlashInAllowModeProto\x12G\n\x10\x45ventPathEnabled\x18\xe0\x07 \x01(\x0b\x32,.enterprise_management.EventPathEnabledProto\x12;\n\nDHEEnabled\x18\xd0\x02 \x01(\x0b\x32&.enterprise_management.DHEEnabledProto\x12Q\n\x15PdfAnnotationsEnabled\x18\xce\x06 \x01(\x0b\x32\x31.enterprise_management.PdfAnnotationsEnabledProto\x12?\n\x0cHeadlessMode\x18\xcc\x06 \x01(\x0b\x32(.enterprise_management.HeadlessModeProto\x12W\n\x18LoadCryptoTokenExtension\x18\xef\x07 \x01(\x0b\x32\x34.enterprise_management.LoadCryptoTokenExtensionProto\x12I\n\x11\x45nableSyncConsent\x18\xc5\x03 \x01(\x0b\x32-.enterprise_management.EnableSyncConsentProto\x12U\n\x17\x42rowserGuestModeEnabled\x18\x95\x02 \x01(\x0b\x32\x33.enterprise_management.BrowserGuestModeEnabledProto\x12X\n\x19\x44isableSSLRecordSplitting\x18x \x01(\x0b\x32\x35.enterprise_management.DisableSSLRecordSplittingProto\x12{\n*CloudUserPolicyOverridesCloudMachinePolicy\x18\x85\x07 \x01(\x0b\x32\x46.enterprise_management.CloudUserPolicyOverridesCloudMachinePolicyProto\x12U\n\x17SafeSitesFilterBehavior\x18\xc9\x03 \x01(\x0b\x32\x33.enterprise_management.SafeSitesFilterBehaviorProto\x12\x63\n\x1eUserDataSnapshotRetentionLimit\x18\xa3\x05 \x01(\x0b\x32:.enterprise_management.UserDataSnapshotRetentionLimitProto\x12W\n\x18U2fSecurityKeyApiEnabled\x18\x89\x07 \x01(\x0b\x32\x34.enterprise_management.U2fSecurityKeyApiEnabledProto\x12k\n\"ClientCertificateManagementAllowed\x18\x88\x04 \x01(\x0b\x32>.enterprise_management.ClientCertificateManagementAllowedProto\x12K\n\x12\x41udioOutputAllowed\x18\xa1\x01 \x01(\x0b\x32..enterprise_management.AudioOutputAllowedProto\x12M\n\x13\x41llowedInputMethods\x18\xca\x03 \x01(\x0b\x32/.enterprise_management.AllowedInputMethodsProto\x12u\n\'FetchKeepaliveDurationSecondsOnShutdown\x18\xbd\x06 \x01(\x0b\x32\x43.enterprise_management.FetchKeepaliveDurationSecondsOnShutdownProto\x12[\n\x1aRelaunchNotificationPeriod\x18\xa6\x03 \x01(\x0b\x32\x36.enterprise_management.RelaunchNotificationPeriodProto\x12O\n\x14\x43hromeCleanupEnabled\x18\xbb\x03 \x01(\x0b\x32\x30.enterprise_management.ChromeCleanupEnabledProto\x12G\n\x10WebRtcIPHandling\x18\xcd\x06 \x01(\x0b\x32,.enterprise_management.WebRtcIPHandlingProto\x12W\n\x18NetworkPredictionOptions\x18\x93\x02 \x01(\x0b\x32\x34.enterprise_management.NetworkPredictionOptionsProto\x12N\n\x14ImportSavedPasswords\x18g \x01(\x0b\x32\x30.enterprise_management.ImportSavedPasswordsProto\x12q\n%ForceLogoutUnauthenticatedUserEnabled\x18\xa9\x05 \x01(\x0b\x32\x41.enterprise_management.ForceLogoutUnauthenticatedUserEnabledProto\x12S\n\x16PromotionalTabsEnabled\x18\xc8\x03 \x01(\x0b\x32\x32.enterprise_management.PromotionalTabsEnabledProto\x12k\n\"ProfilePickerOnStartupAvailability\x18\xac\x06 \x01(\x0b\x32>.enterprise_management.ProfilePickerOnStartupAvailabilityProto\x12U\n\x17\x46orceMaximizeOnFirstRun\x18\xac\x02 \x01(\x0b\x32\x33.enterprise_management.ForceMaximizeOnFirstRunProto\x12]\n\x1bNativePrintersBulkWhitelist\x18\x83\x03 \x01(\x0b\x32\x37.enterprise_management.NativePrintersBulkWhitelistProto\x12=\n\x0b\x45\x63heAllowed\x18\xab\x07 \x01(\x0b\x32\'.enterprise_management.EcheAllowedProto\x12k\n\"DataLeakPreventionReportingEnabled\x18\xda\x06 \x01(\x0b\x32>.enterprise_management.DataLeakPreventionReportingEnabledProto\x12]\n\x1b\x41llowPopupsDuringPageUnload\x18\x97\x04 \x01(\x0b\x32\x37.enterprise_management.AllowPopupsDuringPageUnloadProto\x12@\n\rImportHistory\x18\x64 \x01(\x0b\x32).enterprise_management.ImportHistoryProto\x12y\n)SafeBrowsingExtendedReportingOptInAllowed\x18\xad\x02 \x01(\x0b\x32\x45.enterprise_management.SafeBrowsingExtendedReportingOptInAllowedProto\x12Q\n\x15IsolateOriginsAndroid\x18\xbf\x03 \x01(\x0b\x32\x31.enterprise_management.IsolateOriginsAndroidProto\x12]\n\x1b\x43learBrowsingDataOnExitList\x18\xab\x06 \x01(\x0b\x32\x37.enterprise_management.ClearBrowsingDataOnExitListProto\x12Y\n\x19\x45\x63ryptfsMigrationStrategy\x18\xfa\x02 \x01(\x0b\x32\x35.enterprise_management.EcryptfsMigrationStrategyProto\x12O\n\x14PrivacyScreenEnabled\x18\xa7\x05 \x01(\x0b\x32\x30.enterprise_management.PrivacyScreenEnabledProto\x12[\n\x1a\x41\x64\x64itionalLaunchParameters\x18\x8f\x01 \x01(\x0b\x32\x36.enterprise_management.AdditionalLaunchParametersProto\x12I\n\x11SkipMetadataCheck\x18\xf0\x01 \x01(\x0b\x32-.enterprise_management.SkipMetadataCheckProto\x12T\n\x17RenderInChromeFrameList\x18< \x01(\x0b\x32\x33.enterprise_management.RenderInChromeFrameListProto\x12\x46\n\x10RenderInHostList\x18= \x01(\x0b\x32,.enterprise_management.RenderInHostListProto\x12\\\n\x1b\x43hromeFrameRendererSettings\x18; \x01(\x0b\x32\x37.enterprise_management.ChromeFrameRendererSettingsProto\x12_\n\x1cNetBiosShareDiscoveryEnabled\x18\xd5\x03 \x01(\x0b\x32\x38.enterprise_management.NetBiosShareDiscoveryEnabledProto\x12W\n\x18NetworkFileSharesAllowed\x18\xd0\x03 \x01(\x0b\x32\x34.enterprise_management.NetworkFileSharesAllowedProto\x12o\n$NetworkFileSharesPreconfiguredShares\x18\xec\x03 \x01(\x0b\x32@.enterprise_management.NetworkFileSharesPreconfiguredSharesProto\x12\x63\n\x1eNTLMShareAuthenticationEnabled\x18\xeb\x03 \x01(\x0b\x32:.enterprise_management.NTLMShareAuthenticationEnabledProto\x12\x61\n\x1dScreenCaptureAllowedByOrigins\x18\xf3\x06 \x01(\x0b\x32\x39.enterprise_management.ScreenCaptureAllowedByOriginsProto\x12[\n\x1aTabCaptureAllowedByOrigins\x18\xf5\x06 \x01(\x0b\x32\x36.enterprise_management.TabCaptureAllowedByOriginsProto\x12O\n\x14ScreenCaptureAllowed\x18\x9c\x05 \x01(\x0b\x32\x30.enterprise_management.ScreenCaptureAllowedProto\x12\x61\n\x1dWindowCaptureAllowedByOrigins\x18\xf4\x06 \x01(\x0b\x32\x39.enterprise_management.WindowCaptureAllowedByOriginsProto\x12o\n$SameOriginTabCaptureAllowedByOrigins\x18\xf6\x06 \x01(\x0b\x32@.enterprise_management.SameOriginTabCaptureAllowedByOriginsProto\x12\x63\n\x1e\x41rcBackupRestoreServiceEnabled\x18\xc3\x03 \x01(\x0b\x32:.enterprise_management.ArcBackupRestoreServiceEnabledProto\x12;\n\nArcEnabled\x18\xbf\x02 \x01(\x0b\x32&.enterprise_management.ArcEnabledProto\x12U\n\x17\x41rcCertificatesSyncMode\x18\xcc\x02 \x01(\x0b\x32\x33.enterprise_management.ArcCertificatesSyncModeProto\x12_\n\x1c\x41rcAppToWebAppSharingEnabled\x18\xf9\x06 \x01(\x0b\x32\x38.enterprise_management.ArcAppToWebAppSharingEnabledProto\x12i\n!AppRecommendationZeroStateEnabled\x18\xb5\x04 \x01(\x0b\x32=.enterprise_management.AppRecommendationZeroStateEnabledProto\x12Y\n\x19\x41rcLocationServiceEnabled\x18\xed\x02 \x01(\x0b\x32\x35.enterprise_management.ArcLocationServiceEnabledProto\x12g\n ArcGoogleLocationServicesEnabled\x18\xc4\x03 \x01(\x0b\x32<.enterprise_management.ArcGoogleLocationServicesEnabledProto\x12g\n ArcAppInstallEventLoggingEnabled\x18\xc1\x03 \x01(\x0b\x32<.enterprise_management.ArcAppInstallEventLoggingEnabledProto\x12U\n\x17\x41rcBackupRestoreEnabled\x18\xd3\x02 \x01(\x0b\x32\x33.enterprise_management.ArcBackupRestoreEnabledProto\x12\x39\n\tArcPolicy\x18\xc0\x02 \x01(\x0b\x32%.enterprise_management.ArcPolicyProto\x12\x42\n\tsubProto1\x18\x93\x08 \x01(\x0b\x32..enterprise_management.ChromeSettingsSubProto1B-Z+chromium/policy/enterprise_management_proto') - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chrome_settings_full_runtime_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'Z+chromium/policy/enterprise_management_proto' - _CALENDARINTEGRATIONENABLEDPROTO._serialized_start=108 - _CALENDARINTEGRATIONENABLEDPROTO._serialized_end=239 - _BROWSERSWITCHERENABLEDPROTO._serialized_start=241 - _BROWSERSWITCHERENABLEDPROTO._serialized_end=364 - _BROWSERSWITCHERURLGREYLISTPROTO._serialized_start=367 - _BROWSERSWITCHERURLGREYLISTPROTO._serialized_end=533 - _BROWSERSWITCHERPARSINGMODEPROTO._serialized_start=536 - _BROWSERSWITCHERPARSINGMODEPROTO._serialized_end=667 - _BROWSERSWITCHERDELAYPROTO._serialized_start=669 - _BROWSERSWITCHERDELAYPROTO._serialized_end=788 - _BROWSERSWITCHERUSEIESITELISTPROTO._serialized_start=791 - _BROWSERSWITCHERUSEIESITELISTPROTO._serialized_end=926 - _BROWSERSWITCHEREXTERNALGREYLISTURLPROTO._serialized_start=929 - _BROWSERSWITCHEREXTERNALGREYLISTURLPROTO._serialized_end=1076 - _BROWSERSWITCHERCHROMEPATHPROTO._serialized_start=1079 - _BROWSERSWITCHERCHROMEPATHPROTO._serialized_end=1208 - _BROWSERSWITCHERKEEPLASTCHROMETABPROTO._serialized_start=1211 - _BROWSERSWITCHERKEEPLASTCHROMETABPROTO._serialized_end=1354 - _ALTERNATIVEBROWSERPATHPROTO._serialized_start=1356 - _ALTERNATIVEBROWSERPATHPROTO._serialized_end=1479 - _BROWSERSWITCHERURLLISTPROTO._serialized_start=1482 - _BROWSERSWITCHERURLLISTPROTO._serialized_end=1640 - _ALTERNATIVEBROWSERPARAMETERSPROTO._serialized_start=1643 - _ALTERNATIVEBROWSERPARAMETERSPROTO._serialized_end=1813 - _BROWSERSWITCHEREXTERNALSITELISTURLPROTO._serialized_start=1816 - _BROWSERSWITCHEREXTERNALSITELISTURLPROTO._serialized_end=1963 - _BROWSERSWITCHERCHROMEPARAMETERSPROTO._serialized_start=1966 - _BROWSERSWITCHERCHROMEPARAMETERSPROTO._serialized_end=2142 - _FIRSTPARTYSETSENABLEDPROTO._serialized_start=2144 - _FIRSTPARTYSETSENABLEDPROTO._serialized_end=2265 - _FIRSTPARTYSETSOVERRIDESPROTO._serialized_start=2267 - _FIRSTPARTYSETSOVERRIDESPROTO._serialized_end=2392 - _AUTHNEGOTIATEDELEGATEALLOWLISTPROTO._serialized_start=2395 - _AUTHNEGOTIATEDELEGATEALLOWLISTPROTO._serialized_end=2534 - _NTLMV2ENABLEDPROTO._serialized_start=2536 - _NTLMV2ENABLEDPROTO._serialized_end=2641 - _ALLHTTPAUTHSCHEMESALLOWEDFORORIGINSPROTO._serialized_start=2644 - _ALLHTTPAUTHSCHEMESALLOWEDFORORIGINSPROTO._serialized_end=2828 - _ALLOWCROSSORIGINAUTHPROMPTPROTO._serialized_start=2831 - _ALLOWCROSSORIGINAUTHPROMPTPROTO._serialized_end=2962 - _AUTHNEGOTIATEDELEGATEBYKDCPOLICYPROTO._serialized_start=2965 - _AUTHNEGOTIATEDELEGATEBYKDCPOLICYPROTO._serialized_end=3108 - _DISABLEAUTHNEGOTIATECNAMELOOKUPPROTO._serialized_start=3111 - _DISABLEAUTHNEGOTIATECNAMELOOKUPPROTO._serialized_end=3252 - _INTEGRATEDWEBAUTHENTICATIONALLOWEDPROTO._serialized_start=3255 - _INTEGRATEDWEBAUTHENTICATIONALLOWEDPROTO._serialized_end=3402 - _AUTHSERVERALLOWLISTPROTO._serialized_start=3404 - _AUTHSERVERALLOWLISTPROTO._serialized_end=3521 - _ENABLEAUTHNEGOTIATEPORTPROTO._serialized_start=3523 - _ENABLEAUTHNEGOTIATEPORTPROTO._serialized_end=3648 - _AUTHSCHEMESPROTO._serialized_start=3650 - _AUTHSCHEMESPROTO._serialized_end=3751 - _AUTHANDROIDNEGOTIATEACCOUNTTYPEPROTO._serialized_start=3754 - _AUTHANDROIDNEGOTIATEACCOUNTTYPEPROTO._serialized_end=3895 - _GSSAPILIBRARYNAMEPROTO._serialized_start=3897 - _GSSAPILIBRARYNAMEPROTO._serialized_end=4010 - _BASICAUTHOVERHTTPENABLEDPROTO._serialized_start=4012 - _BASICAUTHOVERHTTPENABLEDPROTO._serialized_end=4139 - _PROXYSERVERPROTO._serialized_start=4141 - _PROXYSERVERPROTO._serialized_end=4242 - _PROXYMODEPROTO._serialized_start=4244 - _PROXYMODEPROTO._serialized_end=4341 - _PROXYBYPASSLISTPROTO._serialized_start=4343 - _PROXYBYPASSLISTPROTO._serialized_end=4452 - _PROXYSERVERMODEPROTO._serialized_start=4454 - _PROXYSERVERMODEPROTO._serialized_end=4563 - _PROXYPACURLPROTO._serialized_start=4565 - _PROXYPACURLPROTO._serialized_end=4666 - _SAMLPASSWORDEXPIRATIONADVANCEWARNINGDAYSPROTO._serialized_start=4669 - _SAMLPASSWORDEXPIRATIONADVANCEWARNINGDAYSPROTO._serialized_end=4828 - _SAMLOFFLINESIGNINTIMELIMITPROTO._serialized_start=4831 - _SAMLOFFLINESIGNINTIMELIMITPROTO._serialized_end=4962 - _LOCKSCREENREAUTHENTICATIONENABLEDPROTO._serialized_start=4965 - _LOCKSCREENREAUTHENTICATIONENABLEDPROTO._serialized_end=5110 - _SAMLINSESSIONPASSWORDCHANGEENABLEDPROTO._serialized_start=5113 - _SAMLINSESSIONPASSWORDCHANGEENABLEDPROTO._serialized_end=5260 - _REPORTARCSTATUSENABLEDPROTO._serialized_start=5262 - _REPORTARCSTATUSENABLEDPROTO._serialized_end=5385 - _PROJECTORENABLEDPROTO._serialized_start=5387 - _PROJECTORENABLEDPROTO._serialized_end=5498 - _PROJECTORDOGFOODFORFAMILYLINKENABLEDPROTO._serialized_start=5501 - _PROJECTORDOGFOODFORFAMILYLINKENABLEDPROTO._serialized_end=5652 - _REPORTEXTENSIONSANDPLUGINSDATAPROTO._serialized_start=5655 - _REPORTEXTENSIONSANDPLUGINSDATAPROTO._serialized_end=5794 - _REPORTPOLICYDATAPROTO._serialized_start=5796 - _REPORTPOLICYDATAPROTO._serialized_end=5907 - _REPORTVERSIONDATAPROTO._serialized_start=5909 - _REPORTVERSIONDATAPROTO._serialized_end=6022 - _REPORTSAFEBROWSINGDATAPROTO._serialized_start=6024 - _REPORTSAFEBROWSINGDATAPROTO._serialized_end=6147 - _CLOUDREPORTINGUPLOADFREQUENCYPROTO._serialized_start=6150 - _CLOUDREPORTINGUPLOADFREQUENCYPROTO._serialized_end=6287 - _REPORTUSERIDDATAPROTO._serialized_start=6289 - _REPORTUSERIDDATAPROTO._serialized_end=6400 - _CLOUDREPORTINGENABLEDPROTO._serialized_start=6402 - _CLOUDREPORTINGENABLEDPROTO._serialized_end=6523 - _CLOUDEXTENSIONREQUESTENABLEDPROTO._serialized_start=6526 - _CLOUDEXTENSIONREQUESTENABLEDPROTO._serialized_end=6661 - _REPORTMACHINEIDDATAPROTO._serialized_start=6663 - _REPORTMACHINEIDDATAPROTO._serialized_end=6780 - _DNSOVERHTTPSSALTPROTO._serialized_start=6782 - _DNSOVERHTTPSSALTPROTO._serialized_end=6893 - _DNSOVERHTTPSTEMPLATESWITHIDENTIFIERSPROTO._serialized_start=6896 - _DNSOVERHTTPSTEMPLATESWITHIDENTIFIERSPROTO._serialized_end=7047 - _ACCESSCONTROLALLOWMETHODSINCORSPREFLIGHTSPECCONFORMANTPROTO._serialized_start=7050 - _ACCESSCONTROLALLOWMETHODSINCORSPREFLIGHTSPECCONFORMANTPROTO._serialized_end=7237 - _DRIVEDISABLEDPROTO._serialized_start=7239 - _DRIVEDISABLEDPROTO._serialized_end=7344 - _DRIVEDISABLEDOVERCELLULARPROTO._serialized_start=7347 - _DRIVEDISABLEDOVERCELLULARPROTO._serialized_end=7476 - _PRINTINGALLOWEDDUPLEXMODESPROTO._serialized_start=7479 - _PRINTINGALLOWEDDUPLEXMODESPROTO._serialized_end=7610 - _NATIVEPRINTERSBULKCONFIGURATIONPROTO._serialized_start=7613 - _NATIVEPRINTERSBULKCONFIGURATIONPROTO._serialized_end=7754 - _CLOUDPRINTSUBMITENABLEDPROTO._serialized_start=7756 - _CLOUDPRINTSUBMITENABLEDPROTO._serialized_end=7881 - _PRINTINGCOLORDEFAULTPROTO._serialized_start=7883 - _PRINTINGCOLORDEFAULTPROTO._serialized_end=8002 - _DISABLEPRINTPREVIEWPROTO._serialized_start=8004 - _DISABLEPRINTPREVIEWPROTO._serialized_end=8121 - _DEFAULTPRINTERSELECTIONPROTO._serialized_start=8123 - _DEFAULTPRINTERSELECTIONPROTO._serialized_end=8248 - _CLOUDPRINTPROXYENABLEDPROTO._serialized_start=8250 - _CLOUDPRINTPROXYENABLEDPROTO._serialized_end=8373 - _EXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_start=8376 - _EXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_end=8548 - _PRINTERSPROTO._serialized_start=8551 - _PRINTERSPROTO._serialized_end=8681 - _USERPRINTERSALLOWEDPROTO._serialized_start=8683 - _USERPRINTERSALLOWEDPROTO._serialized_end=8800 - _PRINTINGPAPERSIZEDEFAULTPROTO._serialized_start=8802 - _PRINTINGPAPERSIZEDEFAULTPROTO._serialized_end=8929 - _PRINTINGPINDEFAULTPROTO._serialized_start=8931 - _PRINTINGPINDEFAULTPROTO._serialized_end=9046 - _CLOUDPRINTWARNINGSSUPPRESSEDPROTO._serialized_start=9049 - _CLOUDPRINTWARNINGSSUPPRESSEDPROTO._serialized_end=9184 - _PRINTERTYPEDENYLISTPROTO._serialized_start=9187 - _PRINTERTYPEDENYLISTPROTO._serialized_end=9339 - _PRINTINGSENDUSERNAMEANDFILENAMEENABLEDPROTO._serialized_start=9342 - _PRINTINGSENDUSERNAMEANDFILENAMEENABLEDPROTO._serialized_end=9497 - _PRINTINGMAXSHEETSALLOWEDPROTO._serialized_start=9499 - _PRINTINGMAXSHEETSALLOWEDPROTO._serialized_end=9626 - _PRINTINGBACKGROUNDGRAPHICSDEFAULTPROTO._serialized_start=9629 - _PRINTINGBACKGROUNDGRAPHICSDEFAULTPROTO._serialized_end=9774 - _PRINTERSBULKACCESSMODEPROTO._serialized_start=9776 - _PRINTERSBULKACCESSMODEPROTO._serialized_end=9899 - _PRINTRASTERIZEPDFDPIPROTO._serialized_start=9901 - _PRINTRASTERIZEPDFDPIPROTO._serialized_end=10020 - _PRINTINGALLOWEDPINMODESPROTO._serialized_start=10022 - _PRINTINGALLOWEDPINMODESPROTO._serialized_end=10147 - _PRINTERSBULKCONFIGURATIONPROTO._serialized_start=10150 - _PRINTERSBULKCONFIGURATIONPROTO._serialized_end=10279 - _EXTERNALPRINTSERVERSPROTO._serialized_start=10281 - _EXTERNALPRINTSERVERSPROTO._serialized_end=10400 - _PRINTINGAPIEXTENSIONSALLOWLISTPROTO._serialized_start=10403 - _PRINTINGAPIEXTENSIONSALLOWLISTPROTO._serialized_end=10577 - _PRINTINGALLOWEDCOLORMODESPROTO._serialized_start=10580 - _PRINTINGALLOWEDCOLORMODESPROTO._serialized_end=10709 - _PRINTERSBULKALLOWLISTPROTO._serialized_start=10712 - _PRINTERSBULKALLOWLISTPROTO._serialized_end=10868 - _PRINTPOSTSCRIPTMODEPROTO._serialized_start=10870 - _PRINTPOSTSCRIPTMODEPROTO._serialized_end=10987 - _PRINTPDFASIMAGEDEFAULTPROTO._serialized_start=10989 - _PRINTPDFASIMAGEDEFAULTPROTO._serialized_end=11112 - _PRINTHEADERFOOTERPROTO._serialized_start=11114 - _PRINTHEADERFOOTERPROTO._serialized_end=11227 - _PRINTINGDUPLEXDEFAULTPROTO._serialized_start=11229 - _PRINTINGDUPLEXDEFAULTPROTO._serialized_end=11350 - _PRINTPDFASIMAGEAVAILABILITYPROTO._serialized_start=11353 - _PRINTPDFASIMAGEAVAILABILITYPROTO._serialized_end=11486 - _NATIVEPRINTERSBULKACCESSMODEPROTO._serialized_start=11489 - _NATIVEPRINTERSBULKACCESSMODEPROTO._serialized_end=11624 - _PRINTJOBHISTORYEXPIRATIONPERIODPROTO._serialized_start=11627 - _PRINTJOBHISTORYEXPIRATIONPERIODPROTO._serialized_end=11768 - _PRINTERSBULKBLOCKLISTPROTO._serialized_start=11771 - _PRINTERSBULKBLOCKLISTPROTO._serialized_end=11927 - _NATIVEPRINTERSPROTO._serialized_start=11930 - _NATIVEPRINTERSPROTO._serialized_end=12072 - _PRINTRASTERIZATIONMODEPROTO._serialized_start=12074 - _PRINTRASTERIZATIONMODEPROTO._serialized_end=12197 - _PRINTINGENABLEDPROTO._serialized_start=12199 - _PRINTINGENABLEDPROTO._serialized_end=12308 - _USERNATIVEPRINTERSALLOWEDPROTO._serialized_start=12311 - _USERNATIVEPRINTERSALLOWEDPROTO._serialized_end=12440 - _PRINTINGALLOWEDBACKGROUNDGRAPHICSMODESPROTO._serialized_start=12443 - _PRINTINGALLOWEDBACKGROUNDGRAPHICSMODESPROTO._serialized_end=12598 - _DELETEPRINTJOBHISTORYALLOWEDPROTO._serialized_start=12601 - _DELETEPRINTJOBHISTORYALLOWEDPROTO._serialized_end=12736 - _PRINTPREVIEWUSESYSTEMDEFAULTPRINTERPROTO._serialized_start=12739 - _PRINTPREVIEWUSESYSTEMDEFAULTPRINTERPROTO._serialized_end=12888 - _USERBOREALISALLOWEDPROTO._serialized_start=12890 - _USERBOREALISALLOWEDPROTO._serialized_end=13007 - _DEFAULTSEARCHPROVIDERSEARCHURLPROTO._serialized_start=13010 - _DEFAULTSEARCHPROVIDERSEARCHURLPROTO._serialized_end=13149 - _DEFAULTSEARCHPROVIDERSEARCHTERMSREPLACEMENTKEYPROTO._serialized_start=13152 - _DEFAULTSEARCHPROVIDERSEARCHTERMSREPLACEMENTKEYPROTO._serialized_end=13323 - _DEFAULTSEARCHPROVIDERSEARCHURLPOSTPARAMSPROTO._serialized_start=13326 - _DEFAULTSEARCHPROVIDERSEARCHURLPOSTPARAMSPROTO._serialized_end=13485 - _DEFAULTSEARCHPROVIDERIMAGEURLPOSTPARAMSPROTO._serialized_start=13488 - _DEFAULTSEARCHPROVIDERIMAGEURLPOSTPARAMSPROTO._serialized_end=13645 - _DEFAULTSEARCHPROVIDERICONURLPROTO._serialized_start=13648 - _DEFAULTSEARCHPROVIDERICONURLPROTO._serialized_end=13783 - _DEFAULTSEARCHPROVIDERIMAGEURLPROTO._serialized_start=13786 - _DEFAULTSEARCHPROVIDERIMAGEURLPROTO._serialized_end=13923 - _DEFAULTSEARCHPROVIDERINSTANTURLPOSTPARAMSPROTO._serialized_start=13926 - _DEFAULTSEARCHPROVIDERINSTANTURLPOSTPARAMSPROTO._serialized_end=14087 - _DEFAULTSEARCHPROVIDERKEYWORDPROTO._serialized_start=14090 - _DEFAULTSEARCHPROVIDERKEYWORDPROTO._serialized_end=14225 - _DEFAULTSEARCHPROVIDERNAMEPROTO._serialized_start=14228 - _DEFAULTSEARCHPROVIDERNAMEPROTO._serialized_end=14357 - _DEFAULTSEARCHPROVIDERSUGGESTURLPROTO._serialized_start=14360 - _DEFAULTSEARCHPROVIDERSUGGESTURLPROTO._serialized_end=14501 - _DEFAULTSEARCHPROVIDERALTERNATEURLSPROTO._serialized_start=14504 - _DEFAULTSEARCHPROVIDERALTERNATEURLSPROTO._serialized_end=14686 - _DEFAULTSEARCHPROVIDERENCODINGSPROTO._serialized_start=14689 - _DEFAULTSEARCHPROVIDERENCODINGSPROTO._serialized_end=14863 - _DEFAULTSEARCHPROVIDERENABLEDPROTO._serialized_start=14866 - _DEFAULTSEARCHPROVIDERENABLEDPROTO._serialized_end=15001 - _DEFAULTSEARCHPROVIDERSUGGESTURLPOSTPARAMSPROTO._serialized_start=15004 - _DEFAULTSEARCHPROVIDERSUGGESTURLPOSTPARAMSPROTO._serialized_end=15165 - _DEFAULTSEARCHPROVIDERNEWTABURLPROTO._serialized_start=15168 - _DEFAULTSEARCHPROVIDERNEWTABURLPROTO._serialized_end=15307 - _DEFAULTSEARCHPROVIDERINSTANTURLPROTO._serialized_start=15310 - _DEFAULTSEARCHPROVIDERINSTANTURLPROTO._serialized_end=15451 - _GAIAOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=15454 - _GAIAOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=15593 - _HOMEPAGEISNEWTABPAGEPROTO._serialized_start=15595 - _HOMEPAGEISNEWTABPAGEPROTO._serialized_end=15714 - _NEWTABPAGELOCATIONPROTO._serialized_start=15716 - _NEWTABPAGELOCATIONPROTO._serialized_end=15831 - _RESTOREONSTARTUPURLSPROTO._serialized_start=15834 - _RESTOREONSTARTUPURLSPROTO._serialized_end=15988 - _HOMEPAGELOCATIONPROTO._serialized_start=15990 - _HOMEPAGELOCATIONPROTO._serialized_end=16101 - _RESTOREONSTARTUPPROTO._serialized_start=16103 - _RESTOREONSTARTUPPROTO._serialized_end=16214 - _SHOWHOMEBUTTONPROTO._serialized_start=16216 - _SHOWHOMEBUTTONPROTO._serialized_end=16323 - _IDLETIMEOUTACTIONSPROTO._serialized_start=16326 - _IDLETIMEOUTACTIONSPROTO._serialized_end=16476 - _IDLETIMEOUTPROTO._serialized_start=16478 - _IDLETIMEOUTPROTO._serialized_end=16579 - _NATIVEMESSAGINGUSERLEVELHOSTSPROTO._serialized_start=16582 - _NATIVEMESSAGINGUSERLEVELHOSTSPROTO._serialized_end=16719 - _NATIVEMESSAGINGBLOCKLISTPROTO._serialized_start=16722 - _NATIVEMESSAGINGBLOCKLISTPROTO._serialized_end=16884 - _NATIVEMESSAGINGALLOWLISTPROTO._serialized_start=16887 - _NATIVEMESSAGINGALLOWLISTPROTO._serialized_end=17049 - _USERACTIVITYSCREENDIMDELAYSCALEPROTO._serialized_start=17052 - _USERACTIVITYSCREENDIMDELAYSCALEPROTO._serialized_end=17193 - _IDLEDELAYBATTERYPROTO._serialized_start=17195 - _IDLEDELAYBATTERYPROTO._serialized_end=17306 - _IDLEACTIONPROTO._serialized_start=17308 - _IDLEACTIONPROTO._serialized_end=17407 - _POWERMANAGEMENTUSESVIDEOACTIVITYPROTO._serialized_start=17410 - _POWERMANAGEMENTUSESVIDEOACTIVITYPROTO._serialized_end=17553 - _SCREENDIMDELAYACPROTO._serialized_start=17555 - _SCREENDIMDELAYACPROTO._serialized_end=17666 - _ALLOWSCREENWAKELOCKSPROTO._serialized_start=17668 - _ALLOWSCREENWAKELOCKSPROTO._serialized_end=17787 - _PRESENTATIONIDLEDELAYSCALEPROTO._serialized_start=17790 - _PRESENTATIONIDLEDELAYSCALEPROTO._serialized_end=17921 - _LIDCLOSEACTIONPROTO._serialized_start=17923 - _LIDCLOSEACTIONPROTO._serialized_end=18030 - _ALLOWWAKELOCKSPROTO._serialized_start=18032 - _ALLOWWAKELOCKSPROTO._serialized_end=18139 - _POWERSMARTDIMENABLEDPROTO._serialized_start=18141 - _POWERSMARTDIMENABLEDPROTO._serialized_end=18260 - _SCREENOFFDELAYBATTERYPROTO._serialized_start=18262 - _SCREENOFFDELAYBATTERYPROTO._serialized_end=18383 - _PRESENTATIONSCREENDIMDELAYSCALEPROTO._serialized_start=18386 - _PRESENTATIONSCREENDIMDELAYSCALEPROTO._serialized_end=18527 - _IDLEWARNINGDELAYACPROTO._serialized_start=18529 - _IDLEWARNINGDELAYACPROTO._serialized_end=18644 - _SCREENDIMDELAYBATTERYPROTO._serialized_start=18646 - _SCREENDIMDELAYBATTERYPROTO._serialized_end=18767 - _POWERMANAGEMENTUSESAUDIOACTIVITYPROTO._serialized_start=18770 - _POWERMANAGEMENTUSESAUDIOACTIVITYPROTO._serialized_end=18913 - _IDLEDELAYACPROTO._serialized_start=18915 - _IDLEDELAYACPROTO._serialized_end=19016 - _POWERMANAGEMENTIDLESETTINGSPROTO._serialized_start=19019 - _POWERMANAGEMENTIDLESETTINGSPROTO._serialized_end=19152 - _SCREENLOCKDELAYACPROTO._serialized_start=19154 - _SCREENLOCKDELAYACPROTO._serialized_end=19267 - _IDLEACTIONBATTERYPROTO._serialized_start=19269 - _IDLEACTIONBATTERYPROTO._serialized_end=19382 - _DEVICEPOWERADAPTIVECHARGINGENABLEDPROTO._serialized_start=19385 - _DEVICEPOWERADAPTIVECHARGINGENABLEDPROTO._serialized_end=19532 - _SCREENLOCKDELAYSPROTO._serialized_start=19534 - _SCREENLOCKDELAYSPROTO._serialized_end=19645 - _SCREENOFFDELAYACPROTO._serialized_start=19647 - _SCREENOFFDELAYACPROTO._serialized_end=19758 - _IDLEACTIONACPROTO._serialized_start=19760 - _IDLEACTIONACPROTO._serialized_end=19863 - _SCREENBRIGHTNESSPERCENTPROTO._serialized_start=19865 - _SCREENBRIGHTNESSPERCENTPROTO._serialized_end=19990 - _IDLEWARNINGDELAYBATTERYPROTO._serialized_start=19992 - _IDLEWARNINGDELAYBATTERYPROTO._serialized_end=20117 - _SCREENLOCKDELAYBATTERYPROTO._serialized_start=20119 - _SCREENLOCKDELAYBATTERYPROTO._serialized_end=20242 - _WAITFORINITIALUSERACTIVITYPROTO._serialized_start=20245 - _WAITFORINITIALUSERACTIVITYPROTO._serialized_end=20376 - _KEYGENALLOWEDFORURLSPROTO._serialized_start=20379 - _KEYGENALLOWEDFORURLSPROTO._serialized_end=20533 - _DEFAULTINSECURECONTENTSETTINGPROTO._serialized_start=20536 - _DEFAULTINSECURECONTENTSETTINGPROTO._serialized_end=20673 - _SENSORSBLOCKEDFORURLSPROTO._serialized_start=20676 - _SENSORSBLOCKEDFORURLSPROTO._serialized_end=20832 - _PDFLOCALFILEACCESSALLOWEDFORDOMAINSPROTO._serialized_start=20835 - _PDFLOCALFILEACCESSALLOWEDFORDOMAINSPROTO._serialized_end=21019 - _DEFAULTLOCALFONTSSETTINGPROTO._serialized_start=21021 - _DEFAULTLOCALFONTSSETTINGPROTO._serialized_end=21148 - _POPUPSBLOCKEDFORURLSPROTO._serialized_start=21151 - _POPUPSBLOCKEDFORURLSPROTO._serialized_end=21305 - _FILESYSTEMREADASKFORURLSPROTO._serialized_start=21308 - _FILESYSTEMREADASKFORURLSPROTO._serialized_end=21470 - _KEYGENBLOCKEDFORURLSPROTO._serialized_start=21473 - _KEYGENBLOCKEDFORURLSPROTO._serialized_end=21627 - _LOCALFONTSALLOWEDFORURLSPROTO._serialized_start=21630 - _LOCALFONTSALLOWEDFORURLSPROTO._serialized_end=21792 - _WEBHIDASKFORURLSPROTO._serialized_start=21795 - _WEBHIDASKFORURLSPROTO._serialized_end=21941 - _WEBUSBBLOCKEDFORURLSPROTO._serialized_start=21944 - _WEBUSBBLOCKEDFORURLSPROTO._serialized_end=22098 - _DEFAULTMEDIASTREAMSETTINGPROTO._serialized_start=22101 - _DEFAULTMEDIASTREAMSETTINGPROTO._serialized_end=22230 - _DEFAULTJAVASCRIPTSETTINGPROTO._serialized_start=22232 - _DEFAULTJAVASCRIPTSETTINGPROTO._serialized_end=22359 - _DEFAULTPOPUPSSETTINGPROTO._serialized_start=22361 - _DEFAULTPOPUPSSETTINGPROTO._serialized_end=22480 - _IMAGESALLOWEDFORURLSPROTO._serialized_start=22483 - _IMAGESALLOWEDFORURLSPROTO._serialized_end=22637 - _DEFAULTKEYGENSETTINGPROTO._serialized_start=22639 - _DEFAULTKEYGENSETTINGPROTO._serialized_end=22758 - _PLUGINSBLOCKEDFORURLSPROTO._serialized_start=22761 - _PLUGINSBLOCKEDFORURLSPROTO._serialized_end=22917 - _FILESYSTEMSYNCACCESSHANDLEASYNCINTERFACEENABLEDPROTO._serialized_start=22920 - _FILESYSTEMSYNCACCESSHANDLEASYNCINTERFACEENABLEDPROTO._serialized_end=23093 - _CLIPBOARDBLOCKEDFORURLSPROTO._serialized_start=23096 - _CLIPBOARDBLOCKEDFORURLSPROTO._serialized_end=23256 - _DEFAULTWINDOWPLACEMENTSETTINGPROTO._serialized_start=23259 - _DEFAULTWINDOWPLACEMENTSETTINGPROTO._serialized_end=23396 - _COOKIESSESSIONONLYFORURLSPROTO._serialized_start=23399 - _COOKIESSESSIONONLYFORURLSPROTO._serialized_end=23563 - _DEFAULTNOTIFICATIONSSETTINGPROTO._serialized_start=23566 - _DEFAULTNOTIFICATIONSSETTINGPROTO._serialized_end=23699 - _WEBHIDALLOWALLDEVICESFORURLSPROTO._serialized_start=23702 - _WEBHIDALLOWALLDEVICESFORURLSPROTO._serialized_end=23872 - _DEFAULTWEBHIDGUARDSETTINGPROTO._serialized_start=23875 - _DEFAULTWEBHIDGUARDSETTINGPROTO._serialized_end=24004 - _SERIALALLOWUSBDEVICESFORURLSPROTO._serialized_start=24007 - _SERIALALLOWUSBDEVICESFORURLSPROTO._serialized_end=24142 - _SERIALBLOCKEDFORURLSPROTO._serialized_start=24145 - _SERIALBLOCKEDFORURLSPROTO._serialized_end=24299 - _WEBHIDBLOCKEDFORURLSPROTO._serialized_start=24302 - _WEBHIDBLOCKEDFORURLSPROTO._serialized_end=24456 - _COOKIESALLOWEDFORURLSPROTO._serialized_start=24459 - _COOKIESALLOWEDFORURLSPROTO._serialized_end=24615 - _SENSORSALLOWEDFORURLSPROTO._serialized_start=24618 - _SENSORSALLOWEDFORURLSPROTO._serialized_end=24774 - _PLUGINSALLOWEDFORURLSPROTO._serialized_start=24777 - _PLUGINSALLOWEDFORURLSPROTO._serialized_end=24933 - _FILEHANDLINGBLOCKEDFORURLSPROTO._serialized_start=24936 - _FILEHANDLINGBLOCKEDFORURLSPROTO._serialized_end=25102 - _REGISTEREDPROTOCOLHANDLERSPROTO._serialized_start=25105 - _REGISTEREDPROTOCOLHANDLERSPROTO._serialized_end=25236 - _SERIALASKFORURLSPROTO._serialized_start=25239 - _SERIALASKFORURLSPROTO._serialized_end=25385 - _DEFAULTCOOKIESSETTINGPROTO._serialized_start=25387 - _DEFAULTCOOKIESSETTINGPROTO._serialized_end=25508 - _LEGACYSAMESITECOOKIEBEHAVIORENABLEDPROTO._serialized_start=25511 - _LEGACYSAMESITECOOKIEBEHAVIORENABLEDPROTO._serialized_end=25660 - _JAVASCRIPTBLOCKEDFORURLSPROTO._serialized_start=25663 - _JAVASCRIPTBLOCKEDFORURLSPROTO._serialized_end=25825 - _DEFAULTFILESYSTEMREADGUARDSETTINGPROTO._serialized_start=25828 - _DEFAULTFILESYSTEMREADGUARDSETTINGPROTO._serialized_end=25973 - _NOTIFICATIONSALLOWEDFORURLSPROTO._serialized_start=25976 - _NOTIFICATIONSALLOWEDFORURLSPROTO._serialized_end=26144 - _DEFAULTWEBUSBGUARDSETTINGPROTO._serialized_start=26147 - _DEFAULTWEBUSBGUARDSETTINGPROTO._serialized_end=26276 - _WEBUSBALLOWDEVICESFORURLSPROTO._serialized_start=26279 - _WEBUSBALLOWDEVICESFORURLSPROTO._serialized_end=26408 - _DEFAULTCLIPBOARDSETTINGPROTO._serialized_start=26410 - _DEFAULTCLIPBOARDSETTINGPROTO._serialized_end=26535 - _WINDOWPLACEMENTALLOWEDFORURLSPROTO._serialized_start=26538 - _WINDOWPLACEMENTALLOWEDFORURLSPROTO._serialized_end=26710 - _LEGACYSAMESITECOOKIEBEHAVIORENABLEDFORDOMAINLISTPROTO._serialized_start=26713 - _LEGACYSAMESITECOOKIEBEHAVIORENABLEDFORDOMAINLISTPROTO._serialized_end=26923 - _LOCALFONTSBLOCKEDFORURLSPROTO._serialized_start=26926 - _LOCALFONTSBLOCKEDFORURLSPROTO._serialized_end=27088 - _DEFAULTGEOLOCATIONSETTINGPROTO._serialized_start=27091 - _DEFAULTGEOLOCATIONSETTINGPROTO._serialized_end=27220 - _FILESYSTEMREADBLOCKEDFORURLSPROTO._serialized_start=27223 - _FILESYSTEMREADBLOCKEDFORURLSPROTO._serialized_end=27393 - _DEFAULTSERIALGUARDSETTINGPROTO._serialized_start=27396 - _DEFAULTSERIALGUARDSETTINGPROTO._serialized_end=27525 - _WEBHIDALLOWDEVICESFORURLSPROTO._serialized_start=27528 - _WEBHIDALLOWDEVICESFORURLSPROTO._serialized_end=27657 - _AUTOSELECTCERTIFICATEFORURLSPROTO._serialized_start=27660 - _AUTOSELECTCERTIFICATEFORURLSPROTO._serialized_end=27830 - _DEFAULTPLUGINSSETTINGPROTO._serialized_start=27832 - _DEFAULTPLUGINSSETTINGPROTO._serialized_end=27953 - _DEFAULTIMAGESSETTINGPROTO._serialized_start=27955 - _DEFAULTIMAGESSETTINGPROTO._serialized_end=28074 - _POPUPSALLOWEDFORURLSPROTO._serialized_start=28077 - _POPUPSALLOWEDFORURLSPROTO._serialized_end=28231 - _DEFAULTWEBBLUETOOTHGUARDSETTINGPROTO._serialized_start=28234 - _DEFAULTWEBBLUETOOTHGUARDSETTINGPROTO._serialized_end=28375 - _CLIPBOARDALLOWEDFORURLSPROTO._serialized_start=28378 - _CLIPBOARDALLOWEDFORURLSPROTO._serialized_end=28538 - _WINDOWPLACEMENTBLOCKEDFORURLSPROTO._serialized_start=28541 - _WINDOWPLACEMENTBLOCKEDFORURLSPROTO._serialized_end=28713 - _INSECURECONTENTBLOCKEDFORURLSPROTO._serialized_start=28716 - _INSECURECONTENTBLOCKEDFORURLSPROTO._serialized_end=28888 - _FILEHANDLINGALLOWEDFORURLSPROTO._serialized_start=28891 - _FILEHANDLINGALLOWEDFORURLSPROTO._serialized_end=29057 - _WEBUSBASKFORURLSPROTO._serialized_start=29060 - _WEBUSBASKFORURLSPROTO._serialized_end=29206 - _DEFAULTSENSORSSETTINGPROTO._serialized_start=29208 - _DEFAULTSENSORSSETTINGPROTO._serialized_end=29329 - _WEBHIDALLOWDEVICESWITHHIDUSAGESFORURLSPROTO._serialized_start=29332 - _WEBHIDALLOWDEVICESWITHHIDUSAGESFORURLSPROTO._serialized_end=29487 - _NOTIFICATIONSBLOCKEDFORURLSPROTO._serialized_start=29490 - _NOTIFICATIONSBLOCKEDFORURLSPROTO._serialized_end=29658 - _DEFAULTJAVASCRIPTJITSETTINGPROTO._serialized_start=29661 - _DEFAULTJAVASCRIPTJITSETTINGPROTO._serialized_end=29794 - _FILESYSTEMWRITEASKFORURLSPROTO._serialized_start=29797 - _FILESYSTEMWRITEASKFORURLSPROTO._serialized_end=29961 - _INSECURECONTENTALLOWEDFORURLSPROTO._serialized_start=29964 - _INSECURECONTENTALLOWEDFORURLSPROTO._serialized_end=30136 - _COOKIESBLOCKEDFORURLSPROTO._serialized_start=30139 - _COOKIESBLOCKEDFORURLSPROTO._serialized_end=30295 - _SERIALALLOWALLPORTSFORURLSPROTO._serialized_start=30298 - _SERIALALLOWALLPORTSFORURLSPROTO._serialized_end=30464 - _IMAGESBLOCKEDFORURLSPROTO._serialized_start=30467 - _IMAGESBLOCKEDFORURLSPROTO._serialized_end=30621 - _JAVASCRIPTJITALLOWEDFORSITESPROTO._serialized_start=30624 - _JAVASCRIPTJITALLOWEDFORSITESPROTO._serialized_end=30794 - _DEFAULTFILESYSTEMWRITEGUARDSETTINGPROTO._serialized_start=30797 - _DEFAULTFILESYSTEMWRITEGUARDSETTINGPROTO._serialized_end=30944 - _DEFAULTFILEHANDLINGGUARDSETTINGPROTO._serialized_start=30947 - _DEFAULTFILEHANDLINGGUARDSETTINGPROTO._serialized_end=31088 - _JAVASCRIPTJITBLOCKEDFORSITESPROTO._serialized_start=31091 - _JAVASCRIPTJITBLOCKEDFORSITESPROTO._serialized_end=31261 - _JAVASCRIPTALLOWEDFORURLSPROTO._serialized_start=31264 - _JAVASCRIPTALLOWEDFORURLSPROTO._serialized_end=31426 - _FILESYSTEMWRITEBLOCKEDFORURLSPROTO._serialized_start=31429 - _FILESYSTEMWRITEBLOCKEDFORURLSPROTO._serialized_end=31601 - _KERBEROSREMEMBERPASSWORDENABLEDPROTO._serialized_start=31604 - _KERBEROSREMEMBERPASSWORDENABLEDPROTO._serialized_end=31745 - _KERBEROSDOMAINAUTOCOMPLETEPROTO._serialized_start=31748 - _KERBEROSDOMAINAUTOCOMPLETEPROTO._serialized_end=31879 - _KERBEROSACCOUNTSPROTO._serialized_start=31881 - _KERBEROSACCOUNTSPROTO._serialized_end=31992 - _KERBEROSDEFAULTCONFIGURATIONPROTO._serialized_start=31995 - _KERBEROSDEFAULTCONFIGURATIONPROTO._serialized_end=32130 - _KERBEROSADDACCOUNTSALLOWEDPROTO._serialized_start=32133 - _KERBEROSADDACCOUNTSALLOWEDPROTO._serialized_end=32264 - _KERBEROSENABLEDPROTO._serialized_start=32266 - _KERBEROSENABLEDPROTO._serialized_end=32375 - _CHROMEFRAMECONTENTTYPESPROTO._serialized_start=32378 - _CHROMEFRAMECONTENTTYPESPROTO._serialized_end=32538 - _QUICKANSWERSDEFINITIONENABLEDPROTO._serialized_start=32541 - _QUICKANSWERSDEFINITIONENABLEDPROTO._serialized_end=32678 - _QUICKANSWERSTRANSLATIONENABLEDPROTO._serialized_start=32681 - _QUICKANSWERSTRANSLATIONENABLEDPROTO._serialized_end=32820 - _QUICKANSWERSUNITCONVERSIONENABLEDPROTO._serialized_start=32823 - _QUICKANSWERSUNITCONVERSIONENABLEDPROTO._serialized_end=32968 - _QUICKANSWERSENABLEDPROTO._serialized_start=32970 - _QUICKANSWERSENABLEDPROTO._serialized_end=33087 - _SUPERVISEDUSERCONTENTPROVIDERENABLEDPROTO._serialized_start=33090 - _SUPERVISEDUSERCONTENTPROVIDERENABLEDPROTO._serialized_end=33241 - _SUPERVISEDUSERCREATIONENABLEDPROTO._serialized_start=33244 - _SUPERVISEDUSERCREATIONENABLEDPROTO._serialized_end=33381 - _REMOTEACCESSHOSTTOKENVALIDATIONURLPROTO._serialized_start=33384 - _REMOTEACCESSHOSTTOKENVALIDATIONURLPROTO._serialized_end=33531 - _REMOTEACCESSHOSTTOKENVALIDATIONCERTIFICATEISSUERPROTO._serialized_start=33534 - _REMOTEACCESSHOSTTOKENVALIDATIONCERTIFICATEISSUERPROTO._serialized_end=33709 - _REMOTEACCESSHOSTALLOWREMOTESUPPORTCONNECTIONSPROTO._serialized_start=33712 - _REMOTEACCESSHOSTALLOWREMOTESUPPORTCONNECTIONSPROTO._serialized_end=33881 - _REMOTEACCESSHOSTREQUIRECURTAINPROTO._serialized_start=33884 - _REMOTEACCESSHOSTREQUIRECURTAINPROTO._serialized_end=34023 - _REMOTEACCESSHOSTALLOWREMOTEACCESSCONNECTIONSPROTO._serialized_start=34026 - _REMOTEACCESSHOSTALLOWREMOTEACCESSCONNECTIONSPROTO._serialized_end=34193 - _REMOTEACCESSHOSTUDPPORTRANGEPROTO._serialized_start=34196 - _REMOTEACCESSHOSTUDPPORTRANGEPROTO._serialized_end=34331 - _REMOTEACCESSHOSTALLOWGNUBBYAUTHPROTO._serialized_start=34334 - _REMOTEACCESSHOSTALLOWGNUBBYAUTHPROTO._serialized_end=34475 - _REMOTEACCESSHOSTENABLEUSERINTERFACEPROTO._serialized_start=34478 - _REMOTEACCESSHOSTENABLEUSERINTERFACEPROTO._serialized_end=34627 - _REMOTEACCESSHOSTTALKGADGETPREFIXPROTO._serialized_start=34630 - _REMOTEACCESSHOSTTALKGADGETPREFIXPROTO._serialized_end=34773 - _REMOTEACCESSHOSTCLIENTDOMAINLISTPROTO._serialized_start=34776 - _REMOTEACCESSHOSTCLIENTDOMAINLISTPROTO._serialized_end=34954 - _REMOTEACCESSHOSTALLOWUIACCESSFORREMOTEASSISTANCEPROTO._serialized_start=34957 - _REMOTEACCESSHOSTALLOWUIACCESSFORREMOTEASSISTANCEPROTO._serialized_end=35132 - _REMOTEACCESSHOSTMATCHUSERNAMEPROTO._serialized_start=35135 - _REMOTEACCESSHOSTMATCHUSERNAMEPROTO._serialized_end=35272 - _REMOTEACCESSCLIENTFIREWALLTRAVERSALPROTO._serialized_start=35275 - _REMOTEACCESSCLIENTFIREWALLTRAVERSALPROTO._serialized_end=35424 - _REMOTEACCESSHOSTALLOWRELAYEDCONNECTIONPROTO._serialized_start=35427 - _REMOTEACCESSHOSTALLOWRELAYEDCONNECTIONPROTO._serialized_end=35582 - _REMOTEACCESSHOSTMAXIMUMSESSIONDURATIONMINUTESPROTO._serialized_start=35585 - _REMOTEACCESSHOSTMAXIMUMSESSIONDURATIONMINUTESPROTO._serialized_end=35754 - _REMOTEACCESSHOSTCLIENTDOMAINPROTO._serialized_start=35757 - _REMOTEACCESSHOSTCLIENTDOMAINPROTO._serialized_end=35892 - _REMOTEACCESSHOSTREQUIRETWOFACTORPROTO._serialized_start=35895 - _REMOTEACCESSHOSTREQUIRETWOFACTORPROTO._serialized_end=36038 - _REMOTEACCESSHOSTDEBUGOVERRIDEPOLICIESPROTO._serialized_start=36041 - _REMOTEACCESSHOSTDEBUGOVERRIDEPOLICIESPROTO._serialized_end=36194 - _REMOTEACCESSHOSTCLIPBOARDSIZEBYTESPROTO._serialized_start=36197 - _REMOTEACCESSHOSTCLIPBOARDSIZEBYTESPROTO._serialized_end=36344 - _REMOTEACCESSHOSTTOKENURLPROTO._serialized_start=36346 - _REMOTEACCESSHOSTTOKENURLPROTO._serialized_end=36473 - _REMOTEACCESSHOSTDOMAINLISTPROTO._serialized_start=36476 - _REMOTEACCESSHOSTDOMAINLISTPROTO._serialized_end=36642 - _REMOTEACCESSHOSTFIREWALLTRAVERSALPROTO._serialized_start=36645 - _REMOTEACCESSHOSTFIREWALLTRAVERSALPROTO._serialized_end=36790 - _REMOTEACCESSHOSTDOMAINPROTO._serialized_start=36792 - _REMOTEACCESSHOSTDOMAINPROTO._serialized_end=36915 - _REMOTEACCESSHOSTALLOWFILETRANSFERPROTO._serialized_start=36918 - _REMOTEACCESSHOSTALLOWFILETRANSFERPROTO._serialized_end=37063 - _REMOTEACCESSHOSTALLOWCLIENTPAIRINGPROTO._serialized_start=37066 - _REMOTEACCESSHOSTALLOWCLIENTPAIRINGPROTO._serialized_end=37213 - _NEWWINDOWSINKIOSKALLOWEDPROTO._serialized_start=37215 - _NEWWINDOWSINKIOSKALLOWEDPROTO._serialized_end=37342 - _EXTENSIONALLOWINSECUREUPDATESPROTO._serialized_start=37345 - _EXTENSIONALLOWINSECUREUPDATESPROTO._serialized_end=37482 - _EXTENSIONINSTALLALLOWLISTPROTO._serialized_start=37485 - _EXTENSIONINSTALLALLOWLISTPROTO._serialized_end=37649 - _EXTENSIONINSTALLBLOCKLISTPROTO._serialized_start=37652 - _EXTENSIONINSTALLBLOCKLISTPROTO._serialized_end=37816 - _EXTENSIONINSTALLFORCELISTPROTO._serialized_start=37819 - _EXTENSIONINSTALLFORCELISTPROTO._serialized_end=37983 - _EXTENSIONALLOWEDTYPESPROTO._serialized_start=37986 - _EXTENSIONALLOWEDTYPESPROTO._serialized_end=38142 - _EXTENSIONINSTALLSOURCESPROTO._serialized_start=38145 - _EXTENSIONINSTALLSOURCESPROTO._serialized_end=38305 - _EXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_start=38308 - _EXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_end=38449 - _BLOCKEXTERNALEXTENSIONSPROTO._serialized_start=38451 - _BLOCKEXTERNALEXTENSIONSPROTO._serialized_end=38576 - _EXTENSIONSETTINGSPROTO._serialized_start=38578 - _EXTENSIONSETTINGSPROTO._serialized_end=38691 - _VOICEINTERACTIONQUICKANSWERSENABLEDPROTO._serialized_start=38694 - _VOICEINTERACTIONQUICKANSWERSENABLEDPROTO._serialized_end=38843 - _VOICEINTERACTIONCONTEXTENABLEDPROTO._serialized_start=38846 - _VOICEINTERACTIONCONTEXTENABLEDPROTO._serialized_end=38985 - _VOICEINTERACTIONHOTWORDENABLEDPROTO._serialized_start=38988 - _VOICEINTERACTIONHOTWORDENABLEDPROTO._serialized_end=39127 - _ASSISTANTVOICEMATCHENABLEDDURINGOOBEPROTO._serialized_start=39130 - _ASSISTANTVOICEMATCHENABLEDDURINGOOBEPROTO._serialized_end=39281 - _ASSISTANTONBOARDINGMODEPROTO._serialized_start=39283 - _ASSISTANTONBOARDINGMODEPROTO._serialized_end=39408 - _ASSISTANTWEBENABLEDPROTO._serialized_start=39410 - _ASSISTANTWEBENABLEDPROTO._serialized_end=39527 - _ATTESTATIONEXTENSIONALLOWLISTPROTO._serialized_start=39530 - _ATTESTATIONEXTENSIONALLOWLISTPROTO._serialized_end=39702 - _ATTESTATIONENABLEDFORUSERPROTO._serialized_start=39705 - _ATTESTATIONENABLEDFORUSERPROTO._serialized_end=39834 - _CASTRECEIVERENABLEDPROTO._serialized_start=39836 - _CASTRECEIVERENABLEDPROTO._serialized_end=39953 - _RECOVERYFACTORBEHAVIORPROTO._serialized_start=39955 - _RECOVERYFACTORBEHAVIORPROTO._serialized_end=40078 - _SHOWCASTICONINTOOLBARPROTO._serialized_start=40080 - _SHOWCASTICONINTOOLBARPROTO._serialized_end=40201 - _SHOWCASTSESSIONSSTARTEDBYOTHERDEVICESPROTO._serialized_start=40204 - _SHOWCASTSESSIONSSTARTEDBYOTHERDEVICESPROTO._serialized_end=40357 - _MEDIAROUTERCASTALLOWALLIPSPROTO._serialized_start=40360 - _MEDIAROUTERCASTALLOWALLIPSPROTO._serialized_end=40491 - _ENABLEMEDIAROUTERPROTO._serialized_start=40493 - _ENABLEMEDIAROUTERPROTO._serialized_end=40606 - _AUTOCLICKENABLEDPROTO._serialized_start=40608 - _AUTOCLICKENABLEDPROTO._serialized_end=40719 - _VIRTUALKEYBOARDENABLEDPROTO._serialized_start=40721 - _VIRTUALKEYBOARDENABLEDPROTO._serialized_end=40844 - _STICKYKEYSENABLEDPROTO._serialized_start=40846 - _STICKYKEYSENABLEDPROTO._serialized_end=40959 - _VIRTUALKEYBOARDFEATURESPROTO._serialized_start=40961 - _VIRTUALKEYBOARDFEATURESPROTO._serialized_end=41086 - _HIGHCONTRASTENABLEDPROTO._serialized_start=41088 - _HIGHCONTRASTENABLEDPROTO._serialized_end=41205 - _KEYBOARDDEFAULTTOFUNCTIONKEYSPROTO._serialized_start=41208 - _KEYBOARDDEFAULTTOFUNCTIONKEYSPROTO._serialized_end=41345 - _ACCESSIBILITYSHORTCUTSENABLEDPROTO._serialized_start=41348 - _ACCESSIBILITYSHORTCUTSENABLEDPROTO._serialized_end=41485 - _SELECTTOSPEAKENABLEDPROTO._serialized_start=41487 - _SELECTTOSPEAKENABLEDPROTO._serialized_end=41606 - _FLOATINGACCESSIBILITYMENUENABLEDPROTO._serialized_start=41609 - _FLOATINGACCESSIBILITYMENUENABLEDPROTO._serialized_end=41752 - _SHOWACCESSIBILITYOPTIONSINSYSTEMTRAYMENUPROTO._serialized_start=41755 - _SHOWACCESSIBILITYOPTIONSINSYSTEMTRAYMENUPROTO._serialized_end=41914 - _CURSORHIGHLIGHTENABLEDPROTO._serialized_start=41916 - _CURSORHIGHLIGHTENABLEDPROTO._serialized_end=42039 - _CARETHIGHLIGHTENABLEDPROTO._serialized_start=42041 - _CARETHIGHLIGHTENABLEDPROTO._serialized_end=42162 - _KEYBOARDFOCUSHIGHLIGHTENABLEDPROTO._serialized_start=42165 - _KEYBOARDFOCUSHIGHLIGHTENABLEDPROTO._serialized_end=42302 - _SCREENMAGNIFIERTYPEPROTO._serialized_start=42304 - _SCREENMAGNIFIERTYPEPROTO._serialized_end=42421 - _MONOAUDIOENABLEDPROTO._serialized_start=42423 - _MONOAUDIOENABLEDPROTO._serialized_end=42534 - _ENHANCEDNETWORKVOICESINSELECTTOSPEAKALLOWEDPROTO._serialized_start=42537 - _ENHANCEDNETWORKVOICESINSELECTTOSPEAKALLOWEDPROTO._serialized_end=42702 - _SPOKENFEEDBACKENABLEDPROTO._serialized_start=42704 - _SPOKENFEEDBACKENABLEDPROTO._serialized_end=42825 - _DICTATIONENABLEDPROTO._serialized_start=42827 - _DICTATIONENABLEDPROTO._serialized_end=42938 - _LARGECURSORENABLEDPROTO._serialized_start=42940 - _LARGECURSORENABLEDPROTO._serialized_end=43055 - _PASSWORDMANAGERENABLEDPROTO._serialized_start=43057 - _PASSWORDMANAGERENABLEDPROTO._serialized_end=43180 - _PASSWORDDISMISSCOMPROMISEDALERTENABLEDPROTO._serialized_start=43183 - _PASSWORDDISMISSCOMPROMISEDALERTENABLEDPROTO._serialized_end=43338 - _PASSWORDLEAKDETECTIONENABLEDPROTO._serialized_start=43341 - _PASSWORDLEAKDETECTIONENABLEDPROTO._serialized_end=43476 - _PASSWORDMANAGERALLOWSHOWPASSWORDSPROTO._serialized_start=43479 - _PASSWORDMANAGERALLOWSHOWPASSWORDSPROTO._serialized_end=43624 - _PLUGINVMDATACOLLECTIONALLOWEDPROTO._serialized_start=43627 - _PLUGINVMDATACOLLECTIONALLOWEDPROTO._serialized_end=43764 - _PLUGINVMUSERIDPROTO._serialized_start=43766 - _PLUGINVMUSERIDPROTO._serialized_end=43873 - _USERPLUGINVMALLOWEDPROTO._serialized_start=43875 - _USERPLUGINVMALLOWEDPROTO._serialized_end=43992 - _PLUGINVMREQUIREDFREEDISKSPACEPROTO._serialized_start=43995 - _PLUGINVMREQUIREDFREEDISKSPACEPROTO._serialized_end=44132 - _PLUGINVMIMAGEPROTO._serialized_start=44134 - _PLUGINVMIMAGEPROTO._serialized_end=44239 - _USAGETIMELIMITPROTO._serialized_start=44241 - _USAGETIMELIMITPROTO._serialized_end=44348 - _PERAPPTIMELIMITSALLOWLISTPROTO._serialized_start=44351 - _PERAPPTIMELIMITSALLOWLISTPROTO._serialized_end=44480 - _PARENTACCESSCODECONFIGPROTO._serialized_start=44482 - _PARENTACCESSCODECONFIGPROTO._serialized_end=44605 - _PERAPPTIMELIMITSPROTO._serialized_start=44607 - _PERAPPTIMELIMITSPROTO._serialized_end=44718 - _EDUCOEXISTENCETOSVERSIONPROTO._serialized_start=44720 - _EDUCOEXISTENCETOSVERSIONPROTO._serialized_end=44847 - _REQUIREDCLIENTCERTIFICATEFORUSERPROTO._serialized_start=44850 - _REQUIREDCLIENTCERTIFICATEFORUSERPROTO._serialized_end=44993 - _SAFEBROWSINGEXTENDEDREPORTINGENABLEDPROTO._serialized_start=44996 - _SAFEBROWSINGEXTENDEDREPORTINGENABLEDPROTO._serialized_end=45147 - _SAFEBROWSINGPROTECTIONLEVELPROTO._serialized_start=45150 - _SAFEBROWSINGPROTECTIONLEVELPROTO._serialized_end=45283 - _SAFEBROWSINGENABLEDPROTO._serialized_start=45285 - _SAFEBROWSINGENABLEDPROTO._serialized_end=45402 - _PASSWORDPROTECTIONWARNINGTRIGGERPROTO._serialized_start=45405 - _PASSWORDPROTECTIONWARNINGTRIGGERPROTO._serialized_end=45548 - _PASSWORDPROTECTIONCHANGEPASSWORDURLPROTO._serialized_start=45551 - _PASSWORDPROTECTIONCHANGEPASSWORDURLPROTO._serialized_end=45700 - _SAFEBROWSINGALLOWLISTDOMAINSPROTO._serialized_start=45703 - _SAFEBROWSINGALLOWLISTDOMAINSPROTO._serialized_end=45873 - _PASSWORDPROTECTIONLOGINURLSPROTO._serialized_start=45876 - _PASSWORDPROTECTIONLOGINURLSPROTO._serialized_end=46044 - _PINUNLOCKAUTOSUBMITENABLEDPROTO._serialized_start=46047 - _PINUNLOCKAUTOSUBMITENABLEDPROTO._serialized_end=46178 - _PINUNLOCKWEAKPINSALLOWEDPROTO._serialized_start=46180 - _PINUNLOCKWEAKPINSALLOWEDPROTO._serialized_end=46307 - _QUICKUNLOCKMODEALLOWLISTPROTO._serialized_start=46310 - _QUICKUNLOCKMODEALLOWLISTPROTO._serialized_end=46472 - _PINUNLOCKMINIMUMLENGTHPROTO._serialized_start=46474 - _PINUNLOCKMINIMUMLENGTHPROTO._serialized_end=46597 - _PINUNLOCKMAXIMUMLENGTHPROTO._serialized_start=46599 - _PINUNLOCKMAXIMUMLENGTHPROTO._serialized_end=46722 - _QUICKUNLOCKTIMEOUTPROTO._serialized_start=46724 - _QUICKUNLOCKTIMEOUTPROTO._serialized_end=46839 - _CLOUDAPAUTHENABLEDPROTO._serialized_start=46841 - _CLOUDAPAUTHENABLEDPROTO._serialized_end=46956 - _CROSTINIEXPORTIMPORTUIALLOWEDPROTO._serialized_start=46959 - _CROSTINIEXPORTIMPORTUIALLOWEDPROTO._serialized_end=47096 - _CROSTINIROOTACCESSALLOWEDPROTO._serialized_start=47099 - _CROSTINIROOTACCESSALLOWEDPROTO._serialized_end=47228 - _CROSTINIALLOWEDPROTO._serialized_start=47230 - _CROSTINIALLOWEDPROTO._serialized_end=47339 - _CROSTINIPORTFORWARDINGALLOWEDPROTO._serialized_start=47342 - _CROSTINIPORTFORWARDINGALLOWEDPROTO._serialized_end=47479 - _SYSTEMTERMINALSSHALLOWEDPROTO._serialized_start=47481 - _SYSTEMTERMINALSSHALLOWEDPROTO._serialized_end=47608 - _CROSTINIANSIBLEPLAYBOOKPROTO._serialized_start=47610 - _CROSTINIANSIBLEPLAYBOOKPROTO._serialized_end=47735 - _CROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_start=47738 - _CROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_end=47881 - _DATACOMPRESSIONPROXYENABLEDPROTO._serialized_start=47884 - _DATACOMPRESSIONPROXYENABLEDPROTO._serialized_end=48017 - _HINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_start=48020 - _HINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_end=48151 - _ENABLEONLINEREVOCATIONCHECKSPROTO._serialized_start=48154 - _ENABLEONLINEREVOCATIONCHECKSPROTO._serialized_end=48289 - _UNSAFELYTREATINSECUREORIGINASSECUREPROTO._serialized_start=48292 - _UNSAFELYTREATINSECUREORIGINASSECUREPROTO._serialized_end=48476 - _FORCEYOUTUBESAFETYMODEPROTO._serialized_start=48478 - _FORCEYOUTUBESAFETYMODEPROTO._serialized_end=48601 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORLEGACYCASPROTO._serialized_start=48604 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORLEGACYCASPROTO._serialized_end=48826 - _HTTPSONLYMODEPROTO._serialized_start=48828 - _HTTPSONLYMODEPROTO._serialized_end=48933 - _SETTIMEOUTWITHOUT1MSCLAMPENABLEDPROTO._serialized_start=48936 - _SETTIMEOUTWITHOUT1MSCLAMPENABLEDPROTO._serialized_end=49079 - _DNSPREFETCHINGENABLEDPROTO._serialized_start=49081 - _DNSPREFETCHINGENABLEDPROTO._serialized_end=49202 - _SPELLCHECKLANGUAGEBLOCKLISTPROTO._serialized_start=49205 - _SPELLCHECKLANGUAGEBLOCKLISTPROTO._serialized_end=49373 - _DISABLEDPLUGINSPROTO._serialized_start=49376 - _DISABLEDPLUGINSPROTO._serialized_end=49520 - _SCHEDULERCONFIGURATIONPROTO._serialized_start=49522 - _SCHEDULERCONFIGURATIONPROTO._serialized_end=49645 - _POLICYATOMICGROUPSENABLEDPROTO._serialized_start=49648 - _POLICYATOMICGROUPSENABLEDPROTO._serialized_end=49777 - _ADDITIONALDNSQUERYTYPESENABLEDPROTO._serialized_start=49780 - _ADDITIONALDNSQUERYTYPESENABLEDPROTO._serialized_end=49919 - _ADVANCEDPROTECTIONDEEPSCANNINGENABLEDPROTO._serialized_start=49922 - _ADVANCEDPROTECTIONDEEPSCANNINGENABLEDPROTO._serialized_end=50075 - _SCROLLTOTEXTFRAGMENTENABLEDPROTO._serialized_start=50078 - _SCROLLTOTEXTFRAGMENTENABLEDPROTO._serialized_end=50211 - _AUTHNEGOTIATEDELEGATEWHITELISTPROTO._serialized_start=50214 - _AUTHNEGOTIATEDELEGATEWHITELISTPROTO._serialized_end=50353 - _RENDERERAPPCONTAINERENABLEDPROTO._serialized_start=50356 - _RENDERERAPPCONTAINERENABLEDPROTO._serialized_end=50489 - _ATTESTATIONEXTENSIONWHITELISTPROTO._serialized_start=50492 - _ATTESTATIONEXTENSIONWHITELISTPROTO._serialized_end=50664 - _MAXCONNECTIONSPERPROXYPROTO._serialized_start=50666 - _MAXCONNECTIONSPERPROXYPROTO._serialized_end=50789 - _DISABLESCREENSHOTSPROTO._serialized_start=50791 - _DISABLESCREENSHOTSPROTO._serialized_end=50906 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORURLSPROTO._serialized_start=50909 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORURLSPROTO._serialized_end=51121 - _SHOWLOGOUTBUTTONINTRAYPROTO._serialized_start=51123 - _SHOWLOGOUTBUTTONINTRAYPROTO._serialized_end=51246 - _VPNCONFIGALLOWEDPROTO._serialized_start=51248 - _VPNCONFIGALLOWEDPROTO._serialized_end=51359 - _ENABLEDPLUGINSPROTO._serialized_start=51362 - _ENABLEDPLUGINSPROTO._serialized_end=51504 - _ENABLEDEPRECATEDPRIVETPRINTINGPROTO._serialized_start=51507 - _ENABLEDEPRECATEDPRIVETPRINTINGPROTO._serialized_end=51646 - _ENTERPRISEREALTIMEURLCHECKMODEPROTO._serialized_start=51649 - _ENTERPRISEREALTIMEURLCHECKMODEPROTO._serialized_end=51788 - _ADVANCEDPROTECTIONALLOWEDPROTO._serialized_start=51791 - _ADVANCEDPROTECTIONALLOWEDPROTO._serialized_end=51920 - _APPLICATIONLOCALEVALUEPROTO._serialized_start=51922 - _APPLICATIONLOCALEVALUEPROTO._serialized_end=52045 - _APPCACHEFORCEENABLEDPROTO._serialized_start=52047 - _APPCACHEFORCEENABLEDPROTO._serialized_end=52166 - _ENTERPRISEAUTHENTICATIONAPPLINKPOLICYPROTO._serialized_start=52169 - _ENTERPRISEAUTHENTICATIONAPPLINKPOLICYPROTO._serialized_end=52322 - _TASKMANAGERENDPROCESSENABLEDPROTO._serialized_start=52325 - _TASKMANAGERENDPROCESSENABLEDPROTO._serialized_end=52460 - _SITEPERPROCESSANDROIDPROTO._serialized_start=52462 - _SITEPERPROCESSANDROIDPROTO._serialized_end=52583 - _INTRANETREDIRECTBEHAVIORPROTO._serialized_start=52585 - _INTRANETREDIRECTBEHAVIORPROTO._serialized_end=52712 - _DEFAULTHANDLERSFORFILEEXTENSIONSPROTO._serialized_start=52715 - _DEFAULTHANDLERSFORFILEEXTENSIONSPROTO._serialized_end=52858 - _BROWSERGUESTMODEENFORCEDPROTO._serialized_start=52860 - _BROWSERGUESTMODEENFORCEDPROTO._serialized_end=52987 - _SSLVERSIONMAXPROTO._serialized_start=52989 - _SSLVERSIONMAXPROTO._serialized_end=53094 - _PERAPPTIMELIMITSWHITELISTPROTO._serialized_start=53097 - _PERAPPTIMELIMITSWHITELISTPROTO._serialized_end=53226 - _INCOGNITOENABLEDPROTO._serialized_start=53228 - _INCOGNITOENABLEDPROTO._serialized_end=53339 - _BRUSCHETTAVMCONFIGURATIONPROTO._serialized_start=53342 - _BRUSCHETTAVMCONFIGURATIONPROTO._serialized_end=53471 - _PACHTTPSURLSTRIPPINGENABLEDPROTO._serialized_start=53474 - _PACHTTPSURLSTRIPPINGENABLEDPROTO._serialized_end=53607 - _OFFSETPARENTNEWSPECBEHAVIORENABLEDPROTO._serialized_start=53610 - _OFFSETPARENTNEWSPECBEHAVIORENABLEDPROTO._serialized_end=53757 - _CLOUDPOLICYOVERRIDESPLATFORMPOLICYPROTO._serialized_start=53760 - _CLOUDPOLICYOVERRIDESPLATFORMPOLICYPROTO._serialized_end=53907 - _SECONDARYGOOGLEACCOUNTSIGNINALLOWEDPROTO._serialized_start=53910 - _SECONDARYGOOGLEACCOUNTSIGNINALLOWEDPROTO._serialized_end=54059 - _DOWNLOADRESTRICTIONSPROTO._serialized_start=54061 - _DOWNLOADRESTRICTIONSPROTO._serialized_end=54180 - _ALTERNATEERRORPAGESENABLEDPROTO._serialized_start=54183 - _ALTERNATEERRORPAGESENABLEDPROTO._serialized_end=54314 - _AUTOLAUNCHPROTOCOLSFROMORIGINSPROTO._serialized_start=54317 - _AUTOLAUNCHPROTOCOLSFROMORIGINSPROTO._serialized_end=54456 - _WALLPAPERIMAGEPROTO._serialized_start=54458 - _WALLPAPERIMAGEPROTO._serialized_end=54565 - _ABUSIVEEXPERIENCEINTERVENTIONENFORCEPROTO._serialized_start=54568 - _ABUSIVEEXPERIENCEINTERVENTIONENFORCEPROTO._serialized_end=54719 - _CHROMEOSMULTIPROFILEUSERBEHAVIORPROTO._serialized_start=54722 - _CHROMEOSMULTIPROFILEUSERBEHAVIORPROTO._serialized_end=54865 - _RELAUNCHNOTIFICATIONPROTO._serialized_start=54867 - _RELAUNCHNOTIFICATIONPROTO._serialized_end=54986 - _IMPORTHOMEPAGEPROTO._serialized_start=54988 - _IMPORTHOMEPAGEPROTO._serialized_end=55095 - _RELAUNCHWINDOWPROTO._serialized_start=55097 - _RELAUNCHWINDOWPROTO._serialized_end=55204 - _SHELFALIGNMENTPROTO._serialized_start=55206 - _SHELFALIGNMENTPROTO._serialized_end=55313 - _BOOKMARKBARENABLEDPROTO._serialized_start=55315 - _BOOKMARKBARENABLEDPROTO._serialized_end=55430 - _MANAGEDACCOUNTSSIGNINRESTRICTIONPROTO._serialized_start=55433 - _MANAGEDACCOUNTSSIGNINRESTRICTIONPROTO._serialized_end=55576 - _PHONEHUBNOTIFICATIONSALLOWEDPROTO._serialized_start=55579 - _PHONEHUBNOTIFICATIONSALLOWEDPROTO._serialized_end=55714 - _CORSNONWILDCARDREQUESTHEADERSSUPPORTPROTO._serialized_start=55717 - _CORSNONWILDCARDREQUESTHEADERSSUPPORTPROTO._serialized_end=55868 - _HARDWAREACCELERATIONMODEENABLEDPROTO._serialized_start=55871 - _HARDWAREACCELERATIONMODEENABLEDPROTO._serialized_end=56012 - _CONTEXTUALSEARCHENABLEDPROTO._serialized_start=56014 - _CONTEXTUALSEARCHENABLEDPROTO._serialized_end=56139 - _EASYUNLOCKALLOWEDPROTO._serialized_start=56141 - _EASYUNLOCKALLOWEDPROTO._serialized_end=56254 - _EXTERNALSTORAGEREADONLYPROTO._serialized_start=56256 - _EXTERNALSTORAGEREADONLYPROTO._serialized_end=56381 - _SECURITYTOKENSESSIONBEHAVIORPROTO._serialized_start=56384 - _SECURITYTOKENSESSIONBEHAVIORPROTO._serialized_end=56519 - _USERFEEDBACKALLOWEDPROTO._serialized_start=56521 - _USERFEEDBACKALLOWEDPROTO._serialized_end=56638 - _LOCKICONINADDRESSBARENABLEDPROTO._serialized_start=56641 - _LOCKICONINADDRESSBARENABLEDPROTO._serialized_end=56774 - _LOOKALIKEWARNINGALLOWLISTDOMAINSPROTO._serialized_start=56777 - _LOOKALIKEWARNINGALLOWLISTDOMAINSPROTO._serialized_end=56955 - _RESTRICTEDMANAGEDGUESTSESSIONEXTENSIONCLEANUPEXEMPTLISTPROTO._serialized_start=56958 - _RESTRICTEDMANAGEDGUESTSESSIONEXTENSIONCLEANUPEXEMPTLISTPROTO._serialized_end=57182 - _ISOLATEDAPPSDEVELOPERMODEALLOWEDPROTO._serialized_start=57185 - _ISOLATEDAPPSDEVELOPERMODEALLOWEDPROTO._serialized_end=57328 - _SEARCHSUGGESTENABLEDPROTO._serialized_start=57330 - _SEARCHSUGGESTENABLEDPROTO._serialized_end=57449 - _TRASHENABLEDPROTO._serialized_start=57451 - _TRASHENABLEDPROTO._serialized_end=57554 - _VIDEOCAPTUREALLOWEDURLSPROTO._serialized_start=57557 - _VIDEOCAPTUREALLOWEDURLSPROTO._serialized_end=57717 - _BROWSERLABSENABLEDPROTO._serialized_start=57719 - _BROWSERLABSENABLEDPROTO._serialized_end=57834 - _SAMLLOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=57837 - _SAMLLOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=57996 - _ISOLATEDWEBAPPINSTALLFORCELISTPROTO._serialized_start=57999 - _ISOLATEDWEBAPPINSTALLFORCELISTPROTO._serialized_end=58138 - _GETDISPLAYMEDIASETSELECTALLSCREENSALLOWEDFORURLSPROTO._serialized_start=58141 - _GETDISPLAYMEDIASETSELECTALLSCREENSALLOWEDFORURLSPROTO._serialized_end=58351 - _SESSIONLENGTHLIMITPROTO._serialized_start=58353 - _SESSIONLENGTHLIMITPROTO._serialized_end=58468 - _BROWSERTHEMECOLORPROTO._serialized_start=58470 - _BROWSERTHEMECOLORPROTO._serialized_end=58583 - _WEBAUTHENTICATIONREMOTEPROXIEDREQUESTSALLOWEDPROTO._serialized_start=58586 - _WEBAUTHENTICATIONREMOTEPROXIEDREQUESTSALLOWEDPROTO._serialized_end=58755 - _PROMPTONMULTIPLEMATCHINGCERTIFICATESPROTO._serialized_start=58758 - _PROMPTONMULTIPLEMATCHINGCERTIFICATESPROTO._serialized_end=58909 - _INSECUREFORMSWARNINGSENABLEDPROTO._serialized_start=58912 - _INSECUREFORMSWARNINGSENABLEDPROTO._serialized_end=59047 - _GCFUSERDATADIRPROTO._serialized_start=59049 - _GCFUSERDATADIRPROTO._serialized_end=59156 - _SECONDARYGOOGLEACCOUNTUSAGEPROTO._serialized_start=59159 - _SECONDARYGOOGLEACCOUNTUSAGEPROTO._serialized_end=59292 - _POLICYSCOPEDETECTIONPROTO._serialized_start=59294 - _POLICYSCOPEDETECTIONPROTO._serialized_end=59413 - _DISABLE3DAPISPROTO._serialized_start=59415 - _DISABLE3DAPISPROTO._serialized_end=59520 - _UNIFIEDDESKTOPENABLEDBYDEFAULTPROTO._serialized_start=59523 - _UNIFIEDDESKTOPENABLEDBYDEFAULTPROTO._serialized_end=59662 - _PAYMENTMETHODQUERYENABLEDPROTO._serialized_start=59665 - _PAYMENTMETHODQUERYENABLEDPROTO._serialized_end=59794 - _VIDEOCAPTUREALLOWEDPROTO._serialized_start=59796 - _VIDEOCAPTUREALLOWEDPROTO._serialized_end=59913 - _LACROSDATABACKWARDMIGRATIONMODEPROTO._serialized_start=59916 - _LACROSDATABACKWARDMIGRATIONMODEPROTO._serialized_end=60057 - _INTENSIVEWAKEUPTHROTTLINGENABLEDPROTO._serialized_start=60060 - _INTENSIVEWAKEUPTHROTTLINGENABLEDPROTO._serialized_end=60203 - _SHELFAUTOHIDEBEHAVIORPROTO._serialized_start=60205 - _SHELFAUTOHIDEBEHAVIORPROTO._serialized_end=60326 - _SYNCDISABLEDPROTO._serialized_start=60328 - _SYNCDISABLEDPROTO._serialized_end=60431 - _DISKCACHEDIRPROTO._serialized_start=60433 - _DISKCACHEDIRPROTO._serialized_end=60536 - _DATALEAKPREVENTIONCLIPBOARDCHECKSIZELIMITPROTO._serialized_start=60539 - _DATALEAKPREVENTIONCLIPBOARDCHECKSIZELIMITPROTO._serialized_end=60700 - _ACCESSCODECASTDEVICEDURATIONPROTO._serialized_start=60703 - _ACCESSCODECASTDEVICEDURATIONPROTO._serialized_end=60838 - _DATALEAKPREVENTIONRULESLISTPROTO._serialized_start=60841 - _DATALEAKPREVENTIONRULESLISTPROTO._serialized_end=60974 - _URLWHITELISTPROTO._serialized_start=60977 - _URLWHITELISTPROTO._serialized_end=61115 - _SUPPRESSDIFFERENTORIGINSUBFRAMEDIALOGSPROTO._serialized_start=61118 - _SUPPRESSDIFFERENTORIGINSUBFRAMEDIALOGSPROTO._serialized_end=61273 - _COMPONENTUPDATESENABLEDPROTO._serialized_start=61275 - _COMPONENTUPDATESENABLEDPROTO._serialized_end=61400 - _WEBRTCEVENTLOGCOLLECTIONALLOWEDPROTO._serialized_start=61403 - _WEBRTCEVENTLOGCOLLECTIONALLOWEDPROTO._serialized_end=61544 - _ENCRYPTEDCLIENTHELLOENABLEDPROTO._serialized_start=61547 - _ENCRYPTEDCLIENTHELLOENABLEDPROTO._serialized_end=61680 - _SYNCTYPESLISTDISABLEDPROTO._serialized_start=61683 - _SYNCTYPESLISTDISABLEDPROTO._serialized_end=61839 - _WEBXRIMMERSIVEARENABLEDPROTO._serialized_start=61841 - _WEBXRIMMERSIVEARENABLEDPROTO._serialized_end=61966 - _OPTIMIZATIONGUIDEFETCHINGENABLEDPROTO._serialized_start=61969 - _OPTIMIZATIONGUIDEFETCHINGENABLEDPROTO._serialized_end=62112 - _EXPLICITLYALLOWEDNETWORKPORTSPROTO._serialized_start=62115 - _EXPLICITLYALLOWEDNETWORKPORTSPROTO._serialized_end=62287 - _PINNEDLAUNCHERAPPSPROTO._serialized_start=62290 - _PINNEDLAUNCHERAPPSPROTO._serialized_end=62440 - _CCTTOSDIALOGENABLEDPROTO._serialized_start=62442 - _CCTTOSDIALOGENABLEDPROTO._serialized_end=62559 - _AUDIOCAPTUREALLOWEDURLSPROTO._serialized_start=62562 - _AUDIOCAPTUREALLOWEDURLSPROTO._serialized_end=62722 - _NOTETAKINGAPPSLOCKSCREENALLOWLISTPROTO._serialized_start=62725 - _NOTETAKINGAPPSLOCKSCREENALLOWLISTPROTO._serialized_end=62905 - _ROAMINGPROFILESUPPORTENABLEDPROTO._serialized_start=62908 - _ROAMINGPROFILESUPPORTENABLEDPROTO._serialized_end=63043 - _ALWAYSAUTHORIZEPLUGINSPROTO._serialized_start=63045 - _ALWAYSAUTHORIZEPLUGINSPROTO._serialized_end=63168 - _PERSISTENTQUOTAENABLEDPROTO._serialized_start=63170 - _PERSISTENTQUOTAENABLEDPROTO._serialized_end=63293 - _WEBAPPSETTINGSPROTO._serialized_start=63295 - _WEBAPPSETTINGSPROTO._serialized_end=63402 - _CLICKTOCALLENABLEDPROTO._serialized_start=63404 - _CLICKTOCALLENABLEDPROTO._serialized_end=63519 - _NEARBYSHAREALLOWEDPROTO._serialized_start=63521 - _NEARBYSHAREALLOWEDPROTO._serialized_end=63636 - _ACCESSCODECASTENABLEDPROTO._serialized_start=63638 - _ACCESSCODECASTENABLEDPROTO._serialized_end=63759 - _EDITBOOKMARKSENABLEDPROTO._serialized_start=63761 - _EDITBOOKMARKSENABLEDPROTO._serialized_end=63880 - _WELCOMEPAGEONOSUPGRADEENABLEDPROTO._serialized_start=63883 - _WELCOMEPAGEONOSUPGRADEENABLEDPROTO._serialized_end=64020 - _UNMANAGEDDEVICESIGNALSCONSENTFLOWENABLEDPROTO._serialized_start=64023 - _UNMANAGEDDEVICESIGNALSCONSENTFLOWENABLEDPROTO._serialized_end=64182 - _EXEMPTDOMAINFILETYPEPAIRSFROMFILETYPEDOWNLOADWARNINGSPROTO._serialized_start=64185 - _EXEMPTDOMAINFILETYPEPAIRSFROMFILETYPEDOWNLOADWARNINGSPROTO._serialized_end=64370 - _USERAGENTCLIENTHINTSENABLEDPROTO._serialized_start=64373 - _USERAGENTCLIENTHINTSENABLEDPROTO._serialized_end=64506 - _CLOUDPROFILEREPORTINGENABLEDPROTO._serialized_start=64509 - _CLOUDPROFILEREPORTINGENABLEDPROTO._serialized_end=64644 - _AUDIOSANDBOXENABLEDPROTO._serialized_start=64646 - _AUDIOSANDBOXENABLEDPROTO._serialized_end=64763 - _SPELLCHECKLANGUAGEPROTO._serialized_start=64766 - _SPELLCHECKLANGUAGEPROTO._serialized_end=64916 - _BLOCKTHIRDPARTYCOOKIESPROTO._serialized_start=64918 - _BLOCKTHIRDPARTYCOOKIESPROTO._serialized_end=65041 - _DISKCACHESIZEPROTO._serialized_start=65043 - _DISKCACHESIZEPROTO._serialized_end=65148 - _NATIVEWINDOWOCCLUSIONENABLEDPROTO._serialized_start=65151 - _NATIVEWINDOWOCCLUSIONENABLEDPROTO._serialized_end=65286 - _USERDATADIRPROTO._serialized_start=65288 - _USERDATADIRPROTO._serialized_end=65389 - _SAVINGBROWSERHISTORYDISABLEDPROTO._serialized_start=65392 - _SAVINGBROWSERHISTORYDISABLEDPROTO._serialized_end=65527 - _ALLOWFILESELECTIONDIALOGSPROTO._serialized_start=65530 - _ALLOWFILESELECTIONDIALOGSPROTO._serialized_end=65659 - _BACKFORWARDCACHEENABLEDPROTO._serialized_start=65661 - _BACKFORWARDCACHEENABLEDPROTO._serialized_end=65786 - _CHROMEVARIATIONSPROTO._serialized_start=65788 - _CHROMEVARIATIONSPROTO._serialized_end=65899 - _SIDESEARCHENABLEDPROTO._serialized_start=65901 - _SIDESEARCHENABLEDPROTO._serialized_end=66014 - _DEVELOPERTOOLSAVAILABILITYPROTO._serialized_start=66017 - _DEVELOPERTOOLSAVAILABILITYPROTO._serialized_end=66148 - _CORSLEGACYMODEENABLEDPROTO._serialized_start=66150 - _CORSLEGACYMODEENABLEDPROTO._serialized_end=66271 - _SPELLCHECKSERVICEENABLEDPROTO._serialized_start=66273 - _SPELLCHECKSERVICEENABLEDPROTO._serialized_end=66400 - _CONTEXTAWAREACCESSSIGNALSALLOWLISTPROTO._serialized_start=66403 - _CONTEXTAWAREACCESSSIGNALSALLOWLISTPROTO._serialized_end=66585 - _SSLERROROVERRIDEALLOWEDPROTO._serialized_start=66587 - _SSLERROROVERRIDEALLOWEDPROTO._serialized_end=66712 - _DISABLESPDYPROTO._serialized_start=66714 - _DISABLESPDYPROTO._serialized_end=66815 - _LACROSALLOWEDPROTO._serialized_start=66817 - _LACROSALLOWEDPROTO._serialized_end=66922 - _NTPCARDSVISIBLEPROTO._serialized_start=66924 - _NTPCARDSVISIBLEPROTO._serialized_end=67033 - _WEBCOMPONENTSV0ENABLEDPROTO._serialized_start=67035 - _WEBCOMPONENTSV0ENABLEDPROTO._serialized_end=67158 - _DOWNLOADDIRECTORYPROTO._serialized_start=67160 - _DOWNLOADDIRECTORYPROTO._serialized_end=67273 - _FORCEEPHEMERALPROFILESPROTO._serialized_start=67275 - _FORCEEPHEMERALPROFILESPROTO._serialized_end=67398 - _BROWSERADDPERSONENABLEDPROTO._serialized_start=67400 - _BROWSERADDPERSONENABLEDPROTO._serialized_end=67525 - _RC4ENABLEDPROTO._serialized_start=67527 - _RC4ENABLEDPROTO._serialized_end=67626 - _INSTANTENABLEDPROTO._serialized_start=67628 - _INSTANTENABLEDPROTO._serialized_end=67735 - _OSCOLORMODEPROTO._serialized_start=67737 - _OSCOLORMODEPROTO._serialized_end=67838 - _NOTETAKINGAPPSLOCKSCREENWHITELISTPROTO._serialized_start=67841 - _NOTETAKINGAPPSLOCKSCREENWHITELISTPROTO._serialized_end=68021 - _CHROMEAPPSENABLEDPROTO._serialized_start=68023 - _CHROMEAPPSENABLEDPROTO._serialized_end=68136 - _ENTERPRISEPROFILECREATIONKEEPBROWSINGDATAPROTO._serialized_start=68139 - _ENTERPRISEPROFILECREATIONKEEPBROWSINGDATAPROTO._serialized_end=68300 - _DESKTOPSHARINGHUBENABLEDPROTO._serialized_start=68302 - _DESKTOPSHARINGHUBENABLEDPROTO._serialized_end=68429 - _QUICKUNLOCKMODEWHITELISTPROTO._serialized_start=68432 - _QUICKUNLOCKMODEWHITELISTPROTO._serialized_end=68594 - _TABUNDERALLOWEDPROTO._serialized_start=68596 - _TABUNDERALLOWEDPROTO._serialized_end=68705 - _CHROMECLEANUPREPORTINGENABLEDPROTO._serialized_start=68708 - _CHROMECLEANUPREPORTINGENABLEDPROTO._serialized_end=68845 - _CLEARSITEDATAONEXITPROTO._serialized_start=68847 - _CLEARSITEDATAONEXITPROTO._serialized_end=68964 - _DNSINTERCEPTIONCHECKSENABLEDPROTO._serialized_start=68967 - _DNSINTERCEPTIONCHECKSENABLEDPROTO._serialized_end=69102 - _DISABLEDSCHEMESPROTO._serialized_start=69105 - _DISABLEDSCHEMESPROTO._serialized_end=69249 - _FLOATINGWORKSPACEV2ENABLEDPROTO._serialized_start=69252 - _FLOATINGWORKSPACEV2ENABLEDPROTO._serialized_end=69383 - _SUPPRESSCHROMEFRAMETURNDOWNPROMPTPROTO._serialized_start=69386 - _SUPPRESSCHROMEFRAMETURNDOWNPROMPTPROTO._serialized_end=69531 - _EXTERNALSTORAGEDISABLEDPROTO._serialized_start=69533 - _EXTERNALSTORAGEDISABLEDPROTO._serialized_end=69658 - _BROWSERLEGACYEXTENSIONPOINTSBLOCKEDPROTO._serialized_start=69661 - _BROWSERLEGACYEXTENSIONPOINTSBLOCKEDPROTO._serialized_end=69810 - _SIGNEDHTTPEXCHANGEENABLEDPROTO._serialized_start=69813 - _SIGNEDHTTPEXCHANGEENABLEDPROTO._serialized_end=69942 - _SECURITYTOKENSESSIONNOTIFICATIONSECONDSPROTO._serialized_start=69945 - _SECURITYTOKENSESSIONNOTIFICATIONSECONDSPROTO._serialized_end=70102 - _SUGGESTEDCONTENTENABLEDPROTO._serialized_start=70104 - _SUGGESTEDCONTENTENABLEDPROTO._serialized_end=70229 - _WEBDRIVEROVERRIDESINCOMPATIBLEPOLICIESPROTO._serialized_start=70232 - _WEBDRIVEROVERRIDESINCOMPATIBLEPOLICIESPROTO._serialized_end=70387 - _ALLOWNATIVENOTIFICATIONSPROTO._serialized_start=70389 - _ALLOWNATIVENOTIFICATIONSPROTO._serialized_end=70516 - _BROWSERNETWORKTIMEQUERIESENABLEDPROTO._serialized_start=70519 - _BROWSERNETWORKTIMEQUERIESENABLEDPROTO._serialized_end=70662 - _HSTSPOLICYBYPASSLISTPROTO._serialized_start=70665 - _HSTSPOLICYBYPASSLISTPROTO._serialized_end=70819 - _PREFIXEDSTORAGEINFOENABLEDPROTO._serialized_start=70822 - _PREFIXEDSTORAGEINFOENABLEDPROTO._serialized_end=70953 - _ALLOWDINOSAUREASTEREGGPROTO._serialized_start=70955 - _ALLOWDINOSAUREASTEREGGPROTO._serialized_end=71078 - _EXTENSIONINSTALLBLACKLISTPROTO._serialized_start=71081 - _EXTENSIONINSTALLBLACKLISTPROTO._serialized_end=71245 - _WEBAUTHNFACTORSPROTO._serialized_start=71248 - _WEBAUTHNFACTORSPROTO._serialized_end=71392 - _ACCESSIBILITYIMAGELABELSENABLEDPROTO._serialized_start=71395 - _ACCESSIBILITYIMAGELABELSENABLEDPROTO._serialized_end=71536 - _DOWNLOADBUBBLEENABLEDPROTO._serialized_start=71538 - _DOWNLOADBUBBLEENABLEDPROTO._serialized_end=71659 - _EXTERNALPROTOCOLDIALOGSHOWALWAYSOPENCHECKBOXPROTO._serialized_start=71662 - _EXTERNALPROTOCOLDIALOGSHOWALWAYSOPENCHECKBOXPROTO._serialized_end=71829 - _INSECUREPRIVATENETWORKREQUESTSALLOWEDPROTO._serialized_start=71832 - _INSECUREPRIVATENETWORKREQUESTSALLOWEDPROTO._serialized_end=71985 - _HIGHEFFICIENCYMODEENABLEDPROTO._serialized_start=71988 - _HIGHEFFICIENCYMODEENABLEDPROTO._serialized_end=72117 - _KEEPFULLSCREENWITHOUTNOTIFICATIONURLALLOWLISTPROTO._serialized_start=72120 - _KEEPFULLSCREENWITHOUTNOTIFICATIONURLALLOWLISTPROTO._serialized_end=72324 - _ALLOWSCREENLOCKPROTO._serialized_start=72326 - _ALLOWSCREENLOCKPROTO._serialized_end=72435 - _IMPORTSEARCHENGINEPROTO._serialized_start=72437 - _IMPORTSEARCHENGINEPROTO._serialized_end=72552 - _CORSMITIGATIONLISTPROTO._serialized_start=72555 - _CORSMITIGATIONLISTPROTO._serialized_end=72705 - _THIRDPARTYBLOCKINGENABLEDPROTO._serialized_start=72708 - _THIRDPARTYBLOCKINGENABLEDPROTO._serialized_end=72837 - _DISPLAYCAPTUREPERMISSIONSPOLICYENABLEDPROTO._serialized_start=72840 - _DISPLAYCAPTUREPERMISSIONSPOLICYENABLEDPROTO._serialized_end=72995 - _WEBSQLNONSECURECONTEXTENABLEDPROTO._serialized_start=72998 - _WEBSQLNONSECURECONTEXTENABLEDPROTO._serialized_end=73135 - _ENABLESYMANTECLEGACYINFRASTRUCTUREPROTO._serialized_start=73138 - _ENABLESYMANTECLEGACYINFRASTRUCTUREPROTO._serialized_end=73285 - _REQUIREONLINEREVOCATIONCHECKSFORLOCALANCHORSPROTO._serialized_start=73288 - _REQUIREONLINEREVOCATIONCHECKSFORLOCALANCHORSPROTO._serialized_end=73455 - _WEBRTCALLOWLEGACYTLSPROTOCOLSPROTO._serialized_start=73458 - _WEBRTCALLOWLEGACYTLSPROTOCOLSPROTO._serialized_end=73595 - _LENSREGIONSEARCHENABLEDPROTO._serialized_start=73597 - _LENSREGIONSEARCHENABLEDPROTO._serialized_end=73722 - _FORCEMAJORVERSIONTOMINORPOSITIONINUSERAGENTPROTO._serialized_start=73725 - _FORCEMAJORVERSIONTOMINORPOSITIONINUSERAGENTPROTO._serialized_end=73890 - _ROAMINGPROFILELOCATIONPROTO._serialized_start=73892 - _ROAMINGPROFILELOCATIONPROTO._serialized_end=74015 - _CECPQ2ENABLEDPROTO._serialized_start=74017 - _CECPQ2ENABLEDPROTO._serialized_end=74122 - _LENSCAMERAASSISTEDSEARCHENABLEDPROTO._serialized_start=74125 - _LENSCAMERAASSISTEDSEARCHENABLEDPROTO._serialized_end=74266 - _EXTENSIONINSTALLWHITELISTPROTO._serialized_start=74269 - _EXTENSIONINSTALLWHITELISTPROTO._serialized_end=74433 - _HTTP09ONNONDEFAULTPORTSENABLEDPROTO._serialized_start=74436 - _HTTP09ONNONDEFAULTPORTSENABLEDPROTO._serialized_end=74575 - _SANDBOXEXTERNALPROTOCOLBLOCKEDPROTO._serialized_start=74578 - _SANDBOXEXTERNALPROTOCOLBLOCKEDPROTO._serialized_end=74717 - _SHAREDCLIPBOARDENABLEDPROTO._serialized_start=74719 - _SHAREDCLIPBOARDENABLEDPROTO._serialized_end=74842 - _CLOUDMANAGEMENTENROLLMENTMANDATORYPROTO._serialized_start=74845 - _CLOUDMANAGEMENTENROLLMENTMANDATORYPROTO._serialized_end=74992 - _ENABLECOMMONNAMEFALLBACKFORLOCALANCHORSPROTO._serialized_start=74995 - _ENABLECOMMONNAMEFALLBACKFORLOCALANCHORSPROTO._serialized_end=75152 - _FORCELEGACYDEFAULTREFERRERPOLICYPROTO._serialized_start=75155 - _FORCELEGACYDEFAULTREFERRERPOLICYPROTO._serialized_end=75298 - _NEWBASEURLINHERITANCEBEHAVIORALLOWEDPROTO._serialized_start=75301 - _NEWBASEURLINHERITANCEBEHAVIORALLOWEDPROTO._serialized_end=75452 - _USERAVATARIMAGEPROTO._serialized_start=75454 - _USERAVATARIMAGEPROTO._serialized_end=75563 - _URLKEYEDANONYMIZEDDATACOLLECTIONENABLEDPROTO._serialized_start=75566 - _URLKEYEDANONYMIZEDDATACOLLECTIONENABLEDPROTO._serialized_end=75723 - _SUGGESTLOGOUTAFTERCLOSINGLASTWINDOWPROTO._serialized_start=75726 - _SUGGESTLOGOUTAFTERCLOSINGLASTWINDOWPROTO._serialized_end=75875 - _ALLOWEDDOMAINSFORAPPSPROTO._serialized_start=75877 - _ALLOWEDDOMAINSFORAPPSPROTO._serialized_end=75998 - _URLBLACKLISTPROTO._serialized_start=76001 - _URLBLACKLISTPROTO._serialized_end=76139 - _AUTOFILLCREDITCARDENABLEDPROTO._serialized_start=76142 - _AUTOFILLCREDITCARDENABLEDPROTO._serialized_end=76271 - _PROXYSETTINGSPROTO._serialized_start=76273 - _PROXYSETTINGSPROTO._serialized_end=76378 - _ISOLATEORIGINSPROTO._serialized_start=76380 - _ISOLATEORIGINSPROTO._serialized_end=76487 - _STRICTMIMETYPECHECKFORWORKERSCRIPTSENABLEDPROTO._serialized_start=76490 - _STRICTMIMETYPECHECKFORWORKERSCRIPTSENABLEDPROTO._serialized_end=76653 - _RESTRICTSIGNINTOPATTERNPROTO._serialized_start=76655 - _RESTRICTSIGNINTOPATTERNPROTO._serialized_end=76780 - _SHAREDARRAYBUFFERUNRESTRICTEDACCESSALLOWEDPROTO._serialized_start=76783 - _SHAREDARRAYBUFFERUNRESTRICTEDACCESSALLOWEDPROTO._serialized_end=76946 - _FULLRESTOREENABLEDPROTO._serialized_start=76948 - _FULLRESTOREENABLEDPROTO._serialized_end=77063 - _DESKTEMPLATESENABLEDPROTO._serialized_start=77065 - _DESKTEMPLATESENABLEDPROTO._serialized_end=77184 - _PROMPTFORDOWNLOADLOCATIONPROTO._serialized_start=77187 - _PROMPTFORDOWNLOADLOCATIONPROTO._serialized_end=77316 - _ONPRINTENTERPRISECONNECTORPROTO._serialized_start=77319 - _ONPRINTENTERPRISECONNECTORPROTO._serialized_end=77450 - _AUDIOCAPTUREALLOWEDPROTO._serialized_start=77452 - _AUDIOCAPTUREALLOWEDPROTO._serialized_end=77569 - _INCOGNITOMODEAVAILABILITYPROTO._serialized_start=77572 - _INCOGNITOMODEAVAILABILITYPROTO._serialized_end=77701 - _DESKAPITHIRDPARTYACCESSENABLEDPROTO._serialized_start=77704 - _DESKAPITHIRDPARTYACCESSENABLEDPROTO._serialized_end=77843 - _SSLERROROVERRIDEALLOWEDFORORIGINSPROTO._serialized_start=77846 - _SSLERROROVERRIDEALLOWEDFORORIGINSPROTO._serialized_end=78026 - _SITEPERPROCESSPROTO._serialized_start=78028 - _SITEPERPROCESSPROTO._serialized_end=78135 - _GAIALOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=78138 - _GAIALOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=78297 - _FLOATINGWORKSPACEENABLEDPROTO._serialized_start=78299 - _FLOATINGWORKSPACEENABLEDPROTO._serialized_end=78426 - _WEBRTCUDPPORTRANGEPROTO._serialized_start=78428 - _WEBRTCUDPPORTRANGEPROTO._serialized_end=78543 - _REMOTEDEBUGGINGALLOWEDPROTO._serialized_start=78545 - _REMOTEDEBUGGINGALLOWEDPROTO._serialized_end=78668 - _PRINTINGAPIEXTENSIONSWHITELISTPROTO._serialized_start=78671 - _PRINTINGAPIEXTENSIONSWHITELISTPROTO._serialized_end=78845 - _USERDISPLAYNAMEPROTO._serialized_start=78847 - _USERDISPLAYNAMEPROTO._serialized_end=78956 - _REPORTCROSTINIUSAGEENABLEDPROTO._serialized_start=78959 - _REPORTCROSTINIUSAGEENABLEDPROTO._serialized_end=79090 - _ONFILEATTACHEDENTERPRISECONNECTORPROTO._serialized_start=79093 - _ONFILEATTACHEDENTERPRISECONNECTORPROTO._serialized_end=79238 - _CACERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_start=79241 - _CACERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_end=79380 - _EXTERNALPRINTSERVERSWHITELISTPROTO._serialized_start=79383 - _EXTERNALPRINTSERVERSWHITELISTPROTO._serialized_end=79555 - _AMBIENTAUTHENTICATIONINPRIVATEMODESENABLEDPROTO._serialized_start=79558 - _AMBIENTAUTHENTICATIONINPRIVATEMODESENABLEDPROTO._serialized_end=79721 - _FORCEYOUTUBERESTRICTPROTO._serialized_start=79723 - _FORCEYOUTUBERESTRICTPROTO._serialized_end=79842 - _COPYPREVENTIONSETTINGSPROTO._serialized_start=79844 - _COPYPREVENTIONSETTINGSPROTO._serialized_end=79967 - _QUICALLOWEDPROTO._serialized_start=79969 - _QUICALLOWEDPROTO._serialized_end=80070 - _EMOJISUGGESTIONENABLEDPROTO._serialized_start=80072 - _EMOJISUGGESTIONENABLEDPROTO._serialized_end=80195 - _DEVICELOCALACCOUNTMANAGEDSESSIONENABLEDPROTO._serialized_start=80198 - _DEVICELOCALACCOUNTMANAGEDSESSIONENABLEDPROTO._serialized_end=80355 - _NTPMIDDLESLOTANNOUNCEMENTVISIBLEPROTO._serialized_start=80358 - _NTPMIDDLESLOTANNOUNCEMENTVISIBLEPROTO._serialized_end=80501 - _ALLOWOUTDATEDPLUGINSPROTO._serialized_start=80503 - _ALLOWOUTDATEDPLUGINSPROTO._serialized_end=80622 - _SPELLCHECKENABLEDPROTO._serialized_start=80624 - _SPELLCHECKENABLEDPROTO._serialized_end=80737 - _EXTENSIONINSTALLEVENTLOGGINGENABLEDPROTO._serialized_start=80740 - _EXTENSIONINSTALLEVENTLOGGINGENABLEDPROTO._serialized_end=80889 - _BROWSINGDATALIFETIMEPROTO._serialized_start=80891 - _BROWSINGDATALIFETIMEPROTO._serialized_end=81010 - _CAPTIVEPORTALAUTHENTICATIONIGNORESPROXYPROTO._serialized_start=81013 - _CAPTIVEPORTALAUTHENTICATIONIGNORESPROXYPROTO._serialized_end=81170 - _NTPCUSTOMBACKGROUNDENABLEDPROTO._serialized_start=81173 - _NTPCUSTOMBACKGROUNDENABLEDPROTO._serialized_end=81304 - _SMARTLOCKSIGNINALLOWEDPROTO._serialized_start=81306 - _SMARTLOCKSIGNINALLOWEDPROTO._serialized_end=81429 - _DEVELOPERTOOLSDISABLEDPROTO._serialized_start=81431 - _DEVELOPERTOOLSDISABLEDPROTO._serialized_end=81554 - _WPADQUICKCHECKENABLEDPROTO._serialized_start=81556 - _WPADQUICKCHECKENABLEDPROTO._serialized_end=81677 - _BATTERYSAVERMODEAVAILABILITYPROTO._serialized_start=81680 - _BATTERYSAVERMODEAVAILABILITYPROTO._serialized_end=81815 - _USERAGENTREDUCTIONPROTO._serialized_start=81817 - _USERAGENTREDUCTIONPROTO._serialized_end=81932 - _HIDEWEBSTOREICONPROTO._serialized_start=81934 - _HIDEWEBSTOREICONPROTO._serialized_end=82045 - _INSIGHTSEXTENSIONENABLEDPROTO._serialized_start=82047 - _INSIGHTSEXTENSIONENABLEDPROTO._serialized_end=82174 - _AUTOPLAYWHITELISTPROTO._serialized_start=82177 - _AUTOPLAYWHITELISTPROTO._serialized_end=82325 - _SSLVERSIONMINPROTO._serialized_start=82327 - _SSLVERSIONMINPROTO._serialized_end=82432 - _SESSIONLOCALESPROTO._serialized_start=82435 - _SESSIONLOCALESPROTO._serialized_end=82577 - _RESTRICTACCOUNTSTOPATTERNSPROTO._serialized_start=82580 - _RESTRICTACCOUNTSTOPATTERNSPROTO._serialized_end=82746 - _MAXINVALIDATIONFETCHDELAYPROTO._serialized_start=82749 - _MAXINVALIDATIONFETCHDELAYPROTO._serialized_end=82878 - _DESKAPITHIRDPARTYALLOWLISTPROTO._serialized_start=82881 - _DESKAPITHIRDPARTYALLOWLISTPROTO._serialized_end=83047 - _VIRTUALKEYBOARDRESIZESLAYOUTBYDEFAULTPROTO._serialized_start=83050 - _VIRTUALKEYBOARDRESIZESLAYOUTBYDEFAULTPROTO._serialized_end=83203 - _WEBSQLACCESSPROTO._serialized_start=83205 - _WEBSQLACCESSPROTO._serialized_end=83308 - _OVERRIDESECURITYRESTRICTIONSONINSECUREORIGINPROTO._serialized_start=83311 - _OVERRIDESECURITYRESTRICTIONSONINSECUREORIGINPROTO._serialized_end=83513 - _ADSSETTINGFORINTRUSIVEADSSITESPROTO._serialized_start=83516 - _ADSSETTINGFORINTRUSIVEADSSITESPROTO._serialized_end=83655 - _OPENNETWORKCONFIGURATIONPROTO._serialized_start=83657 - _OPENNETWORKCONFIGURATIONPROTO._serialized_end=83784 - _DNSOVERHTTPSTEMPLATESPROTO._serialized_start=83786 - _DNSOVERHTTPSTEMPLATESPROTO._serialized_end=83907 - _DISABLEDPLUGINSEXCEPTIONSPROTO._serialized_start=83910 - _DISABLEDPLUGINSEXCEPTIONSPROTO._serialized_end=84074 - _USELEGACYFORMCONTROLSPROTO._serialized_start=84076 - _USELEGACYFORMCONTROLSPROTO._serialized_end=84197 - _DISABLESAFEBROWSINGPROCEEDANYWAYPROTO._serialized_start=84200 - _DISABLESAFEBROWSINGPROCEEDANYWAYPROTO._serialized_end=84343 - _FORCEDLANGUAGESPROTO._serialized_start=84346 - _FORCEDLANGUAGESPROTO._serialized_end=84490 - _DEFAULTBROWSERSETTINGENABLEDPROTO._serialized_start=84493 - _DEFAULTBROWSERSETTINGENABLEDPROTO._serialized_end=84628 - _LOGINDISPLAYPASSWORDBUTTONENABLEDPROTO._serialized_start=84631 - _LOGINDISPLAYPASSWORDBUTTONENABLEDPROTO._serialized_end=84776 - _ALLOWDELETINGBROWSERHISTORYPROTO._serialized_start=84779 - _ALLOWDELETINGBROWSERHISTORYPROTO._serialized_end=84912 - _SPELLCHECKLANGUAGEBLACKLISTPROTO._serialized_start=84915 - _SPELLCHECKLANGUAGEBLACKLISTPROTO._serialized_end=85083 - _TOUCHVIRTUALKEYBOARDENABLEDPROTO._serialized_start=85086 - _TOUCHVIRTUALKEYBOARDENABLEDPROTO._serialized_end=85219 - _INSECUREPRIVATENETWORKREQUESTSALLOWEDFORURLSPROTO._serialized_start=85222 - _INSECUREPRIVATENETWORKREQUESTSALLOWEDFORURLSPROTO._serialized_end=85424 - _AUTHSERVERWHITELISTPROTO._serialized_start=85426 - _AUTHSERVERWHITELISTPROTO._serialized_end=85543 - _AUTOOPENALLOWEDFORURLSPROTO._serialized_start=85546 - _AUTOOPENALLOWEDFORURLSPROTO._serialized_end=85704 - _AUTOOPENFILETYPESPROTO._serialized_start=85707 - _AUTOOPENFILETYPESPROTO._serialized_end=85855 - _ENABLEDEPRECATEDWEBPLATFORMFEATURESPROTO._serialized_start=85858 - _ENABLEDEPRECATEDWEBPLATFORMFEATURESPROTO._serialized_end=86042 - _VMMANAGEMENTCLIALLOWEDPROTO._serialized_start=86044 - _VMMANAGEMENTCLIALLOWEDPROTO._serialized_end=86167 - _STARTUPBROWSERWINDOWLAUNCHSUPPRESSEDPROTO._serialized_start=86170 - _STARTUPBROWSERWINDOWLAUNCHSUPPRESSEDPROTO._serialized_end=86321 - _PHONEHUBCAMERAROLLALLOWEDPROTO._serialized_start=86324 - _PHONEHUBCAMERAROLLALLOWEDPROTO._serialized_end=86453 - _SIGNININTERCEPTIONENABLEDPROTO._serialized_start=86456 - _SIGNININTERCEPTIONENABLEDPROTO._serialized_end=86585 - _MEDIARECOMMENDATIONSENABLEDPROTO._serialized_start=86588 - _MEDIARECOMMENDATIONSENABLEDPROTO._serialized_end=86721 - _LOCKSCREENMEDIAPLAYBACKENABLEDPROTO._serialized_start=86724 - _LOCKSCREENMEDIAPLAYBACKENABLEDPROTO._serialized_end=86863 - _LACROSAVAILABILITYPROTO._serialized_start=86865 - _LACROSAVAILABILITYPROTO._serialized_end=86980 - _NETWORKSERVICESANDBOXENABLEDPROTO._serialized_start=86983 - _NETWORKSERVICESANDBOXENABLEDPROTO._serialized_end=87118 - _PHONEHUBALLOWEDPROTO._serialized_start=87120 - _PHONEHUBALLOWEDPROTO._serialized_end=87229 - _GHOSTWINDOWENABLEDPROTO._serialized_start=87231 - _GHOSTWINDOWENABLEDPROTO._serialized_end=87346 - _SAFEBROWSINGWHITELISTDOMAINSPROTO._serialized_start=87349 - _SAFEBROWSINGWHITELISTDOMAINSPROTO._serialized_end=87519 - _MEDIACACHESIZEPROTO._serialized_start=87521 - _MEDIACACHESIZEPROTO._serialized_end=87628 - _AUTOFILLENABLEDPROTO._serialized_start=87630 - _AUTOFILLENABLEDPROTO._serialized_end=87739 - _WEBRTCLOCALIPSALLOWEDURLSPROTO._serialized_start=87742 - _WEBRTCLOCALIPSALLOWEDURLSPROTO._serialized_end=87906 - _HIDEWEBSTOREPROMOPROTO._serialized_start=87908 - _HIDEWEBSTOREPROMOPROTO._serialized_end=88021 - _ONSECURITYEVENTENTERPRISECONNECTORPROTO._serialized_start=88024 - _ONSECURITYEVENTENTERPRISECONNECTORPROTO._serialized_end=88171 - _BUILTINDNSCLIENTENABLEDPROTO._serialized_start=88173 - _BUILTINDNSCLIENTENABLEDPROTO._serialized_end=88298 - _AUDIOPROCESSHIGHPRIORITYENABLEDPROTO._serialized_start=88301 - _AUDIOPROCESSHIGHPRIORITYENABLEDPROTO._serialized_end=88442 - _DISABLEPLUGINFINDERPROTO._serialized_start=88444 - _DISABLEPLUGINFINDERPROTO._serialized_end=88561 - _HISTORYCLUSTERSVISIBLEPROTO._serialized_start=88563 - _HISTORYCLUSTERSVISIBLEPROTO._serialized_end=88686 - _SMSMESSAGESALLOWEDPROTO._serialized_start=88688 - _SMSMESSAGESALLOWEDPROTO._serialized_end=88803 - _URLBLOCKLISTPROTO._serialized_start=88806 - _URLBLOCKLISTPROTO._serialized_end=88944 - _CONTEXTUALSUGGESTIONSENABLEDPROTO._serialized_start=88947 - _CONTEXTUALSUGGESTIONSENABLEDPROTO._serialized_end=89082 - _CHROMEOSLOCKONIDLESUSPENDPROTO._serialized_start=89085 - _CHROMEOSLOCKONIDLESUSPENDPROTO._serialized_end=89214 - _SYSTEMFEATURESDISABLEMODEPROTO._serialized_start=89217 - _SYSTEMFEATURESDISABLEMODEPROTO._serialized_end=89346 - _TERMSOFSERVICEURLPROTO._serialized_start=89348 - _TERMSOFSERVICEURLPROTO._serialized_end=89461 - _DNSOVERHTTPSMODEPROTO._serialized_start=89463 - _DNSOVERHTTPSMODEPROTO._serialized_end=89574 - _FORCEBROWSERSIGNINPROTO._serialized_start=89576 - _FORCEBROWSERSIGNINPROTO._serialized_end=89691 - _BROWSERSIGNINPROTO._serialized_start=89693 - _BROWSERSIGNINPROTO._serialized_end=89798 - _ENABLESHA1FORLOCALANCHORSPROTO._serialized_start=89801 - _ENABLESHA1FORLOCALANCHORSPROTO._serialized_end=89930 - _TOTALMEMORYLIMITMBPROTO._serialized_start=89932 - _TOTALMEMORYLIMITMBPROTO._serialized_end=90047 - _IMPORTAUTOFILLFORMDATAPROTO._serialized_start=90049 - _IMPORTAUTOFILLFORMDATAPROTO._serialized_end=90172 - _AUTOFILLADDRESSENABLEDPROTO._serialized_start=90174 - _AUTOFILLADDRESSENABLEDPROTO._serialized_end=90297 - _POLICYLISTMULTIPLESOURCEMERGELISTPROTO._serialized_start=90300 - _POLICYLISTMULTIPLESOURCEMERGELISTPROTO._serialized_end=90480 - _DEFAULTSEARCHPROVIDERCONTEXTMENUACCESSALLOWEDPROTO._serialized_start=90483 - _DEFAULTSEARCHPROVIDERCONTEXTMENUACCESSALLOWEDPROTO._serialized_end=90652 - _ENTERPRISEWEBSTOREURLPROTO._serialized_start=90654 - _ENTERPRISEWEBSTOREURLPROTO._serialized_end=90775 - _URLALLOWLISTPROTO._serialized_start=90778 - _URLALLOWLISTPROTO._serialized_end=90916 - _NATIVEPRINTERSBULKBLACKLISTPROTO._serialized_start=90919 - _NATIVEPRINTERSBULKBLACKLISTPROTO._serialized_end=91087 - _SCREENTIMEENABLEDPROTO._serialized_start=91089 - _SCREENTIMEENABLEDPROTO._serialized_end=91202 - _RENDERERCODEINTEGRITYENABLEDPROTO._serialized_start=91205 - _RENDERERCODEINTEGRITYENABLEDPROTO._serialized_end=91340 - _WARNBEFOREQUITTINGENABLEDPROTO._serialized_start=91343 - _WARNBEFOREQUITTINGENABLEDPROTO._serialized_end=91472 - _TARGETBLANKIMPLIESNOOPENERPROTO._serialized_start=91475 - _TARGETBLANKIMPLIESNOOPENERPROTO._serialized_end=91606 - _AUTOPLAYALLOWEDPROTO._serialized_start=91608 - _AUTOPLAYALLOWEDPROTO._serialized_end=91717 - _COMMANDLINEFLAGSECURITYWARNINGSENABLEDPROTO._serialized_start=91720 - _COMMANDLINEFLAGSECURITYWARNINGSENABLEDPROTO._serialized_end=91875 - _CHROMEROOTSTOREENABLEDPROTO._serialized_start=91877 - _CHROMEROOTSTOREENABLEDPROTO._serialized_end=92000 - _POLICYREFRESHRATEPROTO._serialized_start=92002 - _POLICYREFRESHRATEPROTO._serialized_end=92115 - _WEBSQLINTHIRDPARTYCONTEXTENABLEDPROTO._serialized_start=92118 - _WEBSQLINTHIRDPARTYCONTEXTENABLEDPROTO._serialized_end=92261 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORCASPROTO._serialized_start=92264 - _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORCASPROTO._serialized_end=92474 - _NATIVEMESSAGINGBLACKLISTPROTO._serialized_start=92477 - _NATIVEMESSAGINGBLACKLISTPROTO._serialized_end=92639 - _FULLSCREENALERTENABLEDPROTO._serialized_start=92641 - _FULLSCREENALERTENABLEDPROTO._serialized_end=92764 - _LACROSSECONDARYPROFILESALLOWEDPROTO._serialized_start=92767 - _LACROSSECONDARYPROFILESALLOWEDPROTO._serialized_end=92906 - _CLOUDUSERPOLICYMERGEPROTO._serialized_start=92908 - _CLOUDUSERPOLICYMERGEPROTO._serialized_end=93027 - _JAVASCRIPTENABLEDPROTO._serialized_start=93029 - _JAVASCRIPTENABLEDPROTO._serialized_end=93142 - _ALLOWSYSTEMNOTIFICATIONSPROTO._serialized_start=93144 - _ALLOWSYSTEMNOTIFICATIONSPROTO._serialized_end=93271 - _POLICYDICTIONARYMULTIPLESOURCEMERGELISTPROTO._serialized_start=93274 - _POLICYDICTIONARYMULTIPLESOURCEMERGELISTPROTO._serialized_end=93466 - _ALLOWWEBAUTHNWITHBROKENTLSCERTSPROTO._serialized_start=93469 - _ALLOWWEBAUTHNWITHBROKENTLSCERTSPROTO._serialized_end=93610 - _FORCESAFESEARCHPROTO._serialized_start=93612 - _FORCESAFESEARCHPROTO._serialized_end=93721 - _ENTERPRISEHARDWAREPLATFORMAPIENABLEDPROTO._serialized_start=93724 - _ENTERPRISEHARDWAREPLATFORMAPIENABLEDPROTO._serialized_end=93875 - _SHOWAPPSSHORTCUTINBOOKMARKBARPROTO._serialized_start=93878 - _SHOWAPPSSHORTCUTINBOOKMARKBARPROTO._serialized_end=94015 - _MANAGEDCONFIGURATIONPERORIGINPROTO._serialized_start=94018 - _MANAGEDCONFIGURATIONPERORIGINPROTO._serialized_end=94155 - _SIGNINALLOWEDPROTO._serialized_start=94157 - _SIGNINALLOWEDPROTO._serialized_end=94262 - _TOSDIALOGBEHAVIORPROTO._serialized_start=94264 - _TOSDIALOGBEHAVIORPROTO._serialized_end=94377 - _STRICTERMIXEDCONTENTTREATMENTENABLEDPROTO._serialized_start=94380 - _STRICTERMIXEDCONTENTTREATMENTENABLEDPROTO._serialized_end=94531 - _DEVICEATTRIBUTESALLOWEDFORORIGINSPROTO._serialized_start=94534 - _DEVICEATTRIBUTESALLOWEDFORORIGINSPROTO._serialized_end=94714 - _FORCENETWORKINPROCESSPROTO._serialized_start=94716 - _FORCENETWORKINPROCESSPROTO._serialized_end=94837 - _TLS13HARDENINGFORLOCALANCHORSENABLEDPROTO._serialized_start=94840 - _TLS13HARDENINGFORLOCALANCHORSENABLEDPROTO._serialized_end=94991 - _SAFEBROWSINGFORTRUSTEDSOURCESENABLEDPROTO._serialized_start=94994 - _SAFEBROWSINGFORTRUSTEDSOURCESENABLEDPROTO._serialized_end=95145 - _SECURITYKEYPERMITATTESTATIONPROTO._serialized_start=95148 - _SECURITYKEYPERMITATTESTATIONPROTO._serialized_end=95318 - _TABFREEZINGENABLEDPROTO._serialized_start=95320 - _TABFREEZINGENABLEDPROTO._serialized_end=95435 - _IMPORTBOOKMARKSPROTO._serialized_start=95437 - _IMPORTBOOKMARKSPROTO._serialized_end=95546 - _ONFILETRANSFERENTERPRISECONNECTORPROTO._serialized_start=95549 - _ONFILETRANSFERENTERPRISECONNECTORPROTO._serialized_end=95694 - _GLOBALLYSCOPEHTTPAUTHCACHEENABLEDPROTO._serialized_start=95697 - _GLOBALLYSCOPEHTTPAUTHCACHEENABLEDPROTO._serialized_end=95842 - _FASTPAIRENABLEDPROTO._serialized_start=95844 - _FASTPAIRENABLEDPROTO._serialized_end=95953 - _ALLOWCHROMEDATAINBACKUPSPROTO._serialized_start=95955 - _ALLOWCHROMEDATAINBACKUPSPROTO._serialized_end=96082 - _ORIGINAGENTCLUSTERDEFAULTENABLEDPROTO._serialized_start=96085 - _ORIGINAGENTCLUSTERDEFAULTENABLEDPROTO._serialized_end=96228 - _DEFAULTDOWNLOADDIRECTORYPROTO._serialized_start=96230 - _DEFAULTDOWNLOADDIRECTORYPROTO._serialized_end=96357 - _SYSTEMFEATURESDISABLELISTPROTO._serialized_start=96360 - _SYSTEMFEATURESDISABLELISTPROTO._serialized_end=96524 - _MANAGEDGUESTSESSIONAUTOLAUNCHNOTIFICATIONREDUCEDPROTO._serialized_start=96527 - _MANAGEDGUESTSESSIONAUTOLAUNCHNOTIFICATIONREDUCEDPROTO._serialized_end=96702 - _LENSDESKTOPNTPSEARCHENABLEDPROTO._serialized_start=96705 - _LENSDESKTOPNTPSEARCHENABLEDPROTO._serialized_end=96838 - _USERAGENTCLIENTHINTSGREASEUPDATEENABLEDPROTO._serialized_start=96841 - _USERAGENTCLIENTHINTSGREASEUPDATEENABLEDPROTO._serialized_end=96998 - _ONFILEDOWNLOADEDENTERPRISECONNECTORPROTO._serialized_start=97001 - _ONFILEDOWNLOADEDENTERPRISECONNECTORPROTO._serialized_end=97150 - _SSLVERSIONFALLBACKMINPROTO._serialized_start=97152 - _SSLVERSIONFALLBACKMINPROTO._serialized_end=97273 - _ENABLEDEPRECATEDWEBBASEDSIGNINPROTO._serialized_start=97276 - _ENABLEDEPRECATEDWEBBASEDSIGNINPROTO._serialized_end=97415 - _VARIATIONSRESTRICTPARAMETERPROTO._serialized_start=97418 - _VARIATIONSRESTRICTPARAMETERPROTO._serialized_end=97551 - _USBDETECTORNOTIFICATIONENABLEDPROTO._serialized_start=97554 - _USBDETECTORNOTIFICATIONENABLEDPROTO._serialized_end=97693 - _CROSSORIGINWEBASSEMBLYMODULESHARINGENABLEDPROTO._serialized_start=97696 - _CROSSORIGINWEBASSEMBLYMODULESHARINGENABLEDPROTO._serialized_end=97859 - _CLOUDMANAGEMENTENROLLMENTTOKENPROTO._serialized_start=97862 - _CLOUDMANAGEMENTENROLLMENTTOKENPROTO._serialized_end=98001 - _METRICSREPORTINGENABLEDPROTO._serialized_start=98003 - _METRICSREPORTINGENABLEDPROTO._serialized_end=98128 - _SHOPPINGLISTENABLEDPROTO._serialized_start=98130 - _SHOPPINGLISTENABLEDPROTO._serialized_end=98247 - _URLPARAMFILTERENABLEDPROTO._serialized_start=98249 - _URLPARAMFILTERENABLEDPROTO._serialized_end=98370 - _ONBULKDATAENTRYENTERPRISECONNECTORPROTO._serialized_start=98373 - _ONBULKDATAENTRYENTERPRISECONNECTORPROTO._serialized_end=98520 - _PHONEHUBTASKCONTINUATIONALLOWEDPROTO._serialized_start=98523 - _PHONEHUBTASKCONTINUATIONALLOWEDPROTO._serialized_end=98664 - _ENTERPRISEWEBSTORENAMEPROTO._serialized_start=98666 - _ENTERPRISEWEBSTORENAMEPROTO._serialized_end=98789 - _COALESCEH2CONNECTIONSWITHCLIENTCERTIFICATESFORHOSTSPROTO._serialized_start=98792 - _COALESCEH2CONNECTIONSWITHCLIENTCERTIFICATESFORHOSTSPROTO._serialized_end=99008 - _PRECONFIGUREDDESKTEMPLATESPROTO._serialized_start=99011 - _PRECONFIGUREDDESKTEMPLATESPROTO._serialized_end=99142 - _TRIPLEDESENABLEDPROTO._serialized_start=99144 - _TRIPLEDESENABLEDPROTO._serialized_end=99255 - _SUPPRESSUNSUPPORTEDOSWARNINGPROTO._serialized_start=99258 - _SUPPRESSUNSUPPORTEDOSWARNINGPROTO._serialized_end=99393 - _MANAGEDBOOKMARKSPROTO._serialized_start=99395 - _MANAGEDBOOKMARKSPROTO._serialized_end=99506 - _BUILTINCERTIFICATEVERIFIERENABLEDPROTO._serialized_start=99509 - _BUILTINCERTIFICATEVERIFIERENABLEDPROTO._serialized_end=99654 - _FULLSCREENALLOWEDPROTO._serialized_start=99656 - _FULLSCREENALLOWEDPROTO._serialized_end=99769 - _LOCALDISCOVERYENABLEDPROTO._serialized_start=99771 - _LOCALDISCOVERYENABLEDPROTO._serialized_end=99892 - _MACHINELEVELUSERCLOUDPOLICYENROLLMENTTOKENPROTO._serialized_start=99895 - _MACHINELEVELUSERCLOUDPOLICYENROLLMENTTOKENPROTO._serialized_end=100058 - _TRANSLATEENABLEDPROTO._serialized_start=100060 - _TRANSLATEENABLEDPROTO._serialized_end=100171 - _WIFISYNCANDROIDALLOWEDPROTO._serialized_start=100173 - _WIFISYNCANDROIDALLOWEDPROTO._serialized_end=100296 - _NTPCONTENTSUGGESTIONSENABLEDPROTO._serialized_start=100299 - _NTPCONTENTSUGGESTIONSENABLEDPROTO._serialized_end=100434 - _INSTANTTETHERINGALLOWEDPROTO._serialized_start=100436 - _INSTANTTETHERINGALLOWEDPROTO._serialized_end=100561 - _ALLOWSYNCXHRINPAGEDISMISSALPROTO._serialized_start=100564 - _ALLOWSYNCXHRINPAGEDISMISSALPROTO._serialized_end=100697 - _PRIMARYMOUSEBUTTONSWITCHPROTO._serialized_start=100699 - _PRIMARYMOUSEBUTTONSWITCHPROTO._serialized_end=100826 - _RELAUNCHHEADSUPPERIODPROTO._serialized_start=100828 - _RELAUNCHHEADSUPPERIODPROTO._serialized_end=100949 - _BACKGROUNDMODEENABLEDPROTO._serialized_start=100951 - _BACKGROUNDMODEENABLEDPROTO._serialized_end=101072 - _SHOWFULLURLSINADDRESSBARPROTO._serialized_start=101074 - _SHOWFULLURLSINADDRESSBARPROTO._serialized_end=101201 - _FORCEGOOGLESAFESEARCHPROTO._serialized_start=101203 - _FORCEGOOGLESAFESEARCHPROTO._serialized_end=101324 - _NATIVEMESSAGINGWHITELISTPROTO._serialized_start=101327 - _NATIVEMESSAGINGWHITELISTPROTO._serialized_end=101489 - _ENABLEEXPERIMENTALPOLICIESPROTO._serialized_start=101492 - _ENABLEEXPERIMENTALPOLICIESPROTO._serialized_end=101658 - _KEYPERMISSIONSPROTO._serialized_start=101660 - _KEYPERMISSIONSPROTO._serialized_end=101767 - _UNTHROTTLEDNESTEDTIMEOUTENABLEDPROTO._serialized_start=101770 - _UNTHROTTLEDNESTEDTIMEOUTENABLEDPROTO._serialized_end=101911 - _WEBAPPINSTALLFORCELISTPROTO._serialized_start=101913 - _WEBAPPINSTALLFORCELISTPROTO._serialized_end=102036 - _ALWAYSOPENPDFEXTERNALLYPROTO._serialized_start=102038 - _ALWAYSOPENPDFEXTERNALLYPROTO._serialized_end=102163 - _ALLOWEDLANGUAGESPROTO._serialized_start=102166 - _ALLOWEDLANGUAGESPROTO._serialized_end=102312 - _AUTOPLAYALLOWLISTPROTO._serialized_start=102315 - _AUTOPLAYALLOWLISTPROTO._serialized_end=102463 - _SENDMOUSEEVENTSDISABLEDFORMCONTROLSENABLEDPROTO._serialized_start=102466 - _SENDMOUSEEVENTSDISABLEDFORMCONTROLSENABLEDPROTO._serialized_end=102629 - _TABDISCARDINGEXCEPTIONSPROTO._serialized_start=102632 - _TABDISCARDINGEXCEPTIONSPROTO._serialized_end=102792 - _THROTTLENONVISIBLECROSSORIGINIFRAMESALLOWEDPROTO._serialized_start=102795 - _THROTTLENONVISIBLECROSSORIGINIFRAMESALLOWEDPROTO._serialized_end=102960 - _WINDOWOCCLUSIONENABLEDPROTO._serialized_start=102962 - _WINDOWOCCLUSIONENABLEDPROTO._serialized_end=103085 - _RUNALLFLASHINALLOWMODEPROTO._serialized_start=103087 - _RUNALLFLASHINALLOWMODEPROTO._serialized_end=103210 - _EVENTPATHENABLEDPROTO._serialized_start=103212 - _EVENTPATHENABLEDPROTO._serialized_end=103323 - _DHEENABLEDPROTO._serialized_start=103325 - _DHEENABLEDPROTO._serialized_end=103424 - _PDFANNOTATIONSENABLEDPROTO._serialized_start=103426 - _PDFANNOTATIONSENABLEDPROTO._serialized_end=103547 - _HEADLESSMODEPROTO._serialized_start=103549 - _HEADLESSMODEPROTO._serialized_end=103652 - _LOADCRYPTOTOKENEXTENSIONPROTO._serialized_start=103654 - _LOADCRYPTOTOKENEXTENSIONPROTO._serialized_end=103781 - _ENABLESYNCCONSENTPROTO._serialized_start=103783 - _ENABLESYNCCONSENTPROTO._serialized_end=103896 - _BROWSERGUESTMODEENABLEDPROTO._serialized_start=103898 - _BROWSERGUESTMODEENABLEDPROTO._serialized_end=104023 - _DISABLESSLRECORDSPLITTINGPROTO._serialized_start=104026 - _DISABLESSLRECORDSPLITTINGPROTO._serialized_end=104155 - _CLOUDUSERPOLICYOVERRIDESCLOUDMACHINEPOLICYPROTO._serialized_start=104158 - _CLOUDUSERPOLICYOVERRIDESCLOUDMACHINEPOLICYPROTO._serialized_end=104321 - _SAFESITESFILTERBEHAVIORPROTO._serialized_start=104323 - _SAFESITESFILTERBEHAVIORPROTO._serialized_end=104448 - _USERDATASNAPSHOTRETENTIONLIMITPROTO._serialized_start=104451 - _USERDATASNAPSHOTRETENTIONLIMITPROTO._serialized_end=104590 - _U2FSECURITYKEYAPIENABLEDPROTO._serialized_start=104592 - _U2FSECURITYKEYAPIENABLEDPROTO._serialized_end=104719 - _CLIENTCERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_start=104722 - _CLIENTCERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_end=104869 - _AUDIOOUTPUTALLOWEDPROTO._serialized_start=104871 - _AUDIOOUTPUTALLOWEDPROTO._serialized_end=104986 - _ALLOWEDINPUTMETHODSPROTO._serialized_start=104989 - _ALLOWEDINPUTMETHODSPROTO._serialized_end=105141 - _FETCHKEEPALIVEDURATIONSECONDSONSHUTDOWNPROTO._serialized_start=105144 - _FETCHKEEPALIVEDURATIONSECONDSONSHUTDOWNPROTO._serialized_end=105301 - _RELAUNCHNOTIFICATIONPERIODPROTO._serialized_start=105304 - _RELAUNCHNOTIFICATIONPERIODPROTO._serialized_end=105435 - _CHROMECLEANUPENABLEDPROTO._serialized_start=105437 - _CHROMECLEANUPENABLEDPROTO._serialized_end=105556 - _WEBRTCIPHANDLINGPROTO._serialized_start=105558 - _WEBRTCIPHANDLINGPROTO._serialized_end=105669 - _NETWORKPREDICTIONOPTIONSPROTO._serialized_start=105671 - _NETWORKPREDICTIONOPTIONSPROTO._serialized_end=105798 - _IMPORTSAVEDPASSWORDSPROTO._serialized_start=105800 - _IMPORTSAVEDPASSWORDSPROTO._serialized_end=105919 - _FORCELOGOUTUNAUTHENTICATEDUSERENABLEDPROTO._serialized_start=105922 - _FORCELOGOUTUNAUTHENTICATEDUSERENABLEDPROTO._serialized_end=106075 - _PROMOTIONALTABSENABLEDPROTO._serialized_start=106077 - _PROMOTIONALTABSENABLEDPROTO._serialized_end=106200 - _PROFILEPICKERONSTARTUPAVAILABILITYPROTO._serialized_start=106203 - _PROFILEPICKERONSTARTUPAVAILABILITYPROTO._serialized_end=106350 - _FORCEMAXIMIZEONFIRSTRUNPROTO._serialized_start=106352 - _FORCEMAXIMIZEONFIRSTRUNPROTO._serialized_end=106477 - _NATIVEPRINTERSBULKWHITELISTPROTO._serialized_start=106480 - _NATIVEPRINTERSBULKWHITELISTPROTO._serialized_end=106648 - _ECHEALLOWEDPROTO._serialized_start=106650 - _ECHEALLOWEDPROTO._serialized_end=106751 - _DATALEAKPREVENTIONREPORTINGENABLEDPROTO._serialized_start=106754 - _DATALEAKPREVENTIONREPORTINGENABLEDPROTO._serialized_end=106901 - _ALLOWPOPUPSDURINGPAGEUNLOADPROTO._serialized_start=106904 - _ALLOWPOPUPSDURINGPAGEUNLOADPROTO._serialized_end=107037 - _IMPORTHISTORYPROTO._serialized_start=107039 - _IMPORTHISTORYPROTO._serialized_end=107144 - _SAFEBROWSINGEXTENDEDREPORTINGOPTINALLOWEDPROTO._serialized_start=107147 - _SAFEBROWSINGEXTENDEDREPORTINGOPTINALLOWEDPROTO._serialized_end=107308 - _ISOLATEORIGINSANDROIDPROTO._serialized_start=107310 - _ISOLATEORIGINSANDROIDPROTO._serialized_end=107431 - _CLEARBROWSINGDATAONEXITLISTPROTO._serialized_start=107434 - _CLEARBROWSINGDATAONEXITLISTPROTO._serialized_end=107602 - _ECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_start=107605 - _ECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_end=107734 - _PRIVACYSCREENENABLEDPROTO._serialized_start=107736 - _PRIVACYSCREENENABLEDPROTO._serialized_end=107855 - _ADDITIONALLAUNCHPARAMETERSPROTO._serialized_start=107858 - _ADDITIONALLAUNCHPARAMETERSPROTO._serialized_end=107989 - _SKIPMETADATACHECKPROTO._serialized_start=107991 - _SKIPMETADATACHECKPROTO._serialized_end=108104 - _RENDERINCHROMEFRAMELISTPROTO._serialized_start=108107 - _RENDERINCHROMEFRAMELISTPROTO._serialized_end=108267 - _RENDERINHOSTLISTPROTO._serialized_start=108270 - _RENDERINHOSTLISTPROTO._serialized_end=108416 - _CHROMEFRAMERENDERERSETTINGSPROTO._serialized_start=108419 - _CHROMEFRAMERENDERERSETTINGSPROTO._serialized_end=108552 - _NETBIOSSHAREDISCOVERYENABLEDPROTO._serialized_start=108555 - _NETBIOSSHAREDISCOVERYENABLEDPROTO._serialized_end=108690 - _NETWORKFILESHARESALLOWEDPROTO._serialized_start=108692 - _NETWORKFILESHARESALLOWEDPROTO._serialized_end=108819 - _NETWORKFILESHARESPRECONFIGUREDSHARESPROTO._serialized_start=108822 - _NETWORKFILESHARESPRECONFIGUREDSHARESPROTO._serialized_end=108973 - _NTLMSHAREAUTHENTICATIONENABLEDPROTO._serialized_start=108976 - _NTLMSHAREAUTHENTICATIONENABLEDPROTO._serialized_end=109115 - _SCREENCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=109118 - _SCREENCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=109290 - _TABCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=109293 - _TABCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=109459 - _SCREENCAPTUREALLOWEDPROTO._serialized_start=109461 - _SCREENCAPTUREALLOWEDPROTO._serialized_end=109580 - _WINDOWCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=109583 - _WINDOWCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=109755 - _SAMEORIGINTABCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=109758 - _SAMEORIGINTABCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=109944 - _ARCBACKUPRESTORESERVICEENABLEDPROTO._serialized_start=109947 - _ARCBACKUPRESTORESERVICEENABLEDPROTO._serialized_end=110086 - _ARCENABLEDPROTO._serialized_start=110088 - _ARCENABLEDPROTO._serialized_end=110187 - _ARCCERTIFICATESSYNCMODEPROTO._serialized_start=110189 - _ARCCERTIFICATESSYNCMODEPROTO._serialized_end=110314 - _ARCAPPTOWEBAPPSHARINGENABLEDPROTO._serialized_start=110317 - _ARCAPPTOWEBAPPSHARINGENABLEDPROTO._serialized_end=110452 - _APPRECOMMENDATIONZEROSTATEENABLEDPROTO._serialized_start=110455 - _APPRECOMMENDATIONZEROSTATEENABLEDPROTO._serialized_end=110600 - _ARCLOCATIONSERVICEENABLEDPROTO._serialized_start=110603 - _ARCLOCATIONSERVICEENABLEDPROTO._serialized_end=110732 - _ARCGOOGLELOCATIONSERVICESENABLEDPROTO._serialized_start=110735 - _ARCGOOGLELOCATIONSERVICESENABLEDPROTO._serialized_end=110878 - _ARCAPPINSTALLEVENTLOGGINGENABLEDPROTO._serialized_start=110881 - _ARCAPPINSTALLEVENTLOGGINGENABLEDPROTO._serialized_end=111024 - _ARCBACKUPRESTOREENABLEDPROTO._serialized_start=111026 - _ARCBACKUPRESTOREENABLEDPROTO._serialized_end=111151 - _ARCPOLICYPROTO._serialized_start=111153 - _ARCPOLICYPROTO._serialized_end=111250 - _CHROMESETTINGSSUBPROTO1._serialized_start=111253 - _CHROMESETTINGSSUBPROTO1._serialized_end=111680 - _CHROMESETTINGSPROTO._serialized_start=111684 - _CHROMESETTINGSPROTO._serialized_end=184826 -# @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_pb2.py new file mode 100644 index 0000000..04456370 --- /dev/null +++ b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/chrome_settings_pb2.py
@@ -0,0 +1,1653 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: chrome_settings.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import policy_common_definitions_pb2 as policy__common__definitions__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x63hrome_settings.proto\x12\x15\x65nterprise_management\x1a\x1fpolicy_common_definitions.proto\"q\n\x16GSSAPILibraryNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11GSSAPILibraryName\x18\x02 \x01(\t\"i\n\x12NtlmV2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rNtlmV2Enabled\x18\x02 \x01(\x08\"\x8d\x01\n$DisableAuthNegotiateCnameLookupProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44isableAuthNegotiateCnameLookup\x18\x02 \x01(\x08\"u\n\x18\x41uthServerAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41uthServerAllowlist\x18\x02 \x01(\t\"e\n\x10\x41uthSchemesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x41uthSchemes\x18\x02 \x01(\t\"}\n\x1c\x45nableAuthNegotiatePortProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45nableAuthNegotiatePort\x18\x02 \x01(\x08\"\x8d\x01\n$AuthAndroidNegotiateAccountTypeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41uthAndroidNegotiateAccountType\x18\x02 \x01(\t\"\x8f\x01\n%AuthNegotiateDelegateByKdcPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n AuthNegotiateDelegateByKdcPolicy\x18\x02 \x01(\x08\"\x93\x01\n\'IntegratedWebAuthenticationAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"IntegratedWebAuthenticationAllowed\x18\x02 \x01(\x08\"\x7f\n\x1d\x42\x61sicAuthOverHttpEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x42\x61sicAuthOverHttpEnabled\x18\x02 \x01(\x08\"\xb8\x01\n(AllHttpAuthSchemesAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#AllHttpAuthSchemesAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x41llowCrossOriginAuthPromptProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41llowCrossOriginAuthPrompt\x18\x02 \x01(\x08\"\x8b\x01\n#AuthNegotiateDelegateAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41uthNegotiateDelegateAllowlist\x18\x02 \x01(\t\"y\n\x1a\x46irstPartySetsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46irstPartySetsEnabled\x18\x02 \x01(\x08\"}\n\x1c\x46irstPartySetsOverridesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x46irstPartySetsOverrides\x18\x02 \x01(\t\"\x8b\x01\n#VoiceInteractionContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eVoiceInteractionContextEnabled\x18\x02 \x01(\x08\"}\n\x1c\x41ssistantOnboardingModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41ssistantOnboardingMode\x18\x02 \x01(\t\"\x95\x01\n(VoiceInteractionQuickAnswersEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#VoiceInteractionQuickAnswersEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#VoiceInteractionHotwordEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eVoiceInteractionHotwordEnabled\x18\x02 \x01(\x08\"u\n\x18\x41ssistantWebEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41ssistantWebEnabled\x18\x02 \x01(\x08\"\x97\x01\n)AssistantVoiceMatchEnabledDuringOobeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$AssistantVoiceMatchEnabledDuringOobe\x18\x02 \x01(\x08\"w\n\x19SelectToSpeakEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14SelectToSpeakEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%FloatingAccessibilityMenuEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n FloatingAccessibilityMenuEnabled\x18\x02 \x01(\x08\"o\n\x15MonoAudioEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10MonoAudioEnabled\x18\x02 \x01(\x08\"u\n\x18HighContrastEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13HighContrastEnabled\x18\x02 \x01(\x08\"}\n\x1cVirtualKeyboardFeaturesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17VirtualKeyboardFeatures\x18\x02 \x01(\t\"o\n\x15\x44ictationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44ictationEnabled\x18\x02 \x01(\x08\"s\n\x17LargeCursorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12LargeCursorEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"KeyboardDefaultToFunctionKeysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dKeyboardDefaultToFunctionKeys\x18\x02 \x01(\x08\"\x9f\x01\n-ShowAccessibilityOptionsInSystemTrayMenuProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(ShowAccessibilityOptionsInSystemTrayMenu\x18\x02 \x01(\x08\"{\n\x1b\x43ursorHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43ursorHighlightEnabled\x18\x02 \x01(\x08\"o\n\x15\x41utoclickEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x41utoclickEnabled\x18\x02 \x01(\x08\"y\n\x1aSpokenFeedbackEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SpokenFeedbackEnabled\x18\x02 \x01(\x08\"\xa5\x01\n0EnhancedNetworkVoicesInSelectToSpeakAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+EnhancedNetworkVoicesInSelectToSpeakAllowed\x18\x02 \x01(\x08\"{\n\x1bVirtualKeyboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16VirtualKeyboardEnabled\x18\x02 \x01(\x08\"q\n\x16StickyKeysEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11StickyKeysEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"AccessibilityShortcutsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x41\x63\x63\x65ssibilityShortcutsEnabled\x18\x02 \x01(\x08\"u\n\x18ScreenMagnifierTypeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ScreenMagnifierType\x18\x02 \x01(\x03\"\x89\x01\n\"KeyboardFocusHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dKeyboardFocusHighlightEnabled\x18\x02 \x01(\x08\"y\n\x1a\x43\x61retHighlightEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43\x61retHighlightEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"SupervisedUserCreationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dSupervisedUserCreationEnabled\x18\x02 \x01(\x08\"\x97\x01\n)SupervisedUserContentProviderEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SupervisedUserContentProviderEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1ePrintersBulkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PrintersBulkConfiguration\x18\x02 \x01(\t\"}\n\x1cPrintingAllowedPinModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17PrintingAllowedPinModes\x18\x02 \x01(\t\"\x8d\x01\n$PrintJobHistoryExpirationPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPrintJobHistoryExpirationPeriod\x18\x02 \x01(\x03\"\xae\x01\n#PrintingAPIExtensionsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1ePrintingAPIExtensionsAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1ePrintingAllowedColorModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PrintingAllowedColorModes\x18\x02 \x01(\t\"\x87\x01\n!NativePrintersBulkAccessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNativePrintersBulkAccessMode\x18\x02 \x01(\x03\"{\n\x1b\x43loudPrintProxyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43loudPrintProxyEnabled\x18\x02 \x01(\x08\"q\n\x16PrintHeaderFooterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11PrintHeaderFooter\x18\x02 \x01(\x08\"\x9b\x01\n+PrintingSendUsernameAndFilenameEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PrintingSendUsernameAndFilenameEnabled\x18\x02 \x01(\x08\"\x87\x01\n!DeletePrintJobHistoryAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65letePrintJobHistoryAllowed\x18\x02 \x01(\x08\"u\n\x18\x44isablePrintPreviewProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x44isablePrintPreview\x18\x02 \x01(\x08\"u\n\x18PrintPostScriptModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13PrintPostScriptMode\x18\x02 \x01(\x03\"\x85\x01\n PrintPdfAsImageAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPrintPdfAsImageAvailability\x18\x02 \x01(\x08\"\xac\x01\n\"ExternalPrintServersAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xternalPrintServersAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x45xternalPrintServersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x45xternalPrintServers\x18\x02 \x01(\t\"\x9c\x01\n\x1aPrintersBulkBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PrintersBulkBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1dPrintingPaperSizeDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrintingPaperSizeDefault\x18\x02 \x01(\t\"\x8d\x01\n$NativePrintersBulkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fNativePrintersBulkConfiguration\x18\x02 \x01(\t\"\x9b\x01\n+PrintingAllowedBackgroundGraphicsModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PrintingAllowedBackgroundGraphicsModes\x18\x02 \x01(\t\"\x9c\x01\n\x1aPrintersBulkAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PrintersBulkAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fPrintingAllowedDuplexModesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPrintingAllowedDuplexModes\x18\x02 \x01(\t\"y\n\x1aPrintingDuplexDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15PrintingDuplexDefault\x18\x02 \x01(\t\"s\n\x17PrintingPinDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12PrintingPinDefault\x18\x02 \x01(\t\"{\n\x1bPrintersBulkAccessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintersBulkAccessMode\x18\x02 \x01(\x03\"w\n\x19PrintRasterizePdfDpiProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrintRasterizePdfDpi\x18\x02 \x01(\x03\"\x95\x01\n(PrintPreviewUseSystemDefaultPrinterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#PrintPreviewUseSystemDefaultPrinter\x18\x02 \x01(\x08\"\x7f\n\x1dPrintingMaxSheetsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrintingMaxSheetsAllowed\x18\x02 \x01(\x03\"u\n\x18UserPrintersAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserPrintersAllowed\x18\x02 \x01(\x08\"\x91\x01\n&PrintingBackgroundGraphicsDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!PrintingBackgroundGraphicsDefault\x18\x02 \x01(\t\"{\n\x1bPrintPdfAsImageDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintPdfAsImageDefault\x18\x02 \x01(\x08\"}\n\x1c\x44\x65\x66\x61ultPrinterSelectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x44\x65\x66\x61ultPrinterSelection\x18\x02 \x01(\t\"}\n\x1c\x43loudPrintSubmitEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43loudPrintSubmitEnabled\x18\x02 \x01(\x08\"\x98\x01\n\x18PrinterTypeDenyListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n\x13PrinterTypeDenyList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14PrintingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fPrintingEnabled\x18\x02 \x01(\x08\"\x8e\x01\n\x13NativePrintersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0eNativePrinters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19PrintingColorDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrintingColorDefault\x18\x02 \x01(\t\"\x82\x01\n\rPrintersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n\x08Printers\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eUserNativePrintersAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19UserNativePrintersAllowed\x18\x02 \x01(\x08\"\x87\x01\n!CloudPrintWarningsSuppressedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudPrintWarningsSuppressed\x18\x02 \x01(\x08\"{\n\x1bPrintRasterizationModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PrintRasterizationMode\x18\x02 \x01(\x03\"\x9b\x01\n+PasswordDismissCompromisedAlertEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&PasswordDismissCompromisedAlertEnabled\x18\x02 \x01(\x08\"\x87\x01\n!PasswordLeakDetectionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cPasswordLeakDetectionEnabled\x18\x02 \x01(\x08\"{\n\x1bPasswordManagerEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PasswordManagerEnabled\x18\x02 \x01(\x08\"\x91\x01\n&PasswordManagerAllowShowPasswordsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!PasswordManagerAllowShowPasswords\x18\x02 \x01(\x08\"u\n\x18\x43\x61stReceiverEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43\x61stReceiverEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'BrowserSwitcherExternalSitelistUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"BrowserSwitcherExternalSitelistUrl\x18\x02 \x01(\t\"\x93\x01\n\'BrowserSwitcherExternalGreylistUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"BrowserSwitcherExternalGreylistUrl\x18\x02 \x01(\t\"\xb0\x01\n$BrowserSwitcherChromeParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12J\n\x1f\x42rowserSwitcherChromeParameters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x87\x01\n!BrowserSwitcherUseIeSitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x42rowserSwitcherUseIeSitelist\x18\x02 \x01(\x08\"w\n\x19\x42rowserSwitcherDelayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x42rowserSwitcherDelay\x18\x02 \x01(\x03\"{\n\x1b\x42rowserSwitcherEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x42rowserSwitcherEnabled\x18\x02 \x01(\x08\"{\n\x1b\x41lternativeBrowserPathProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41lternativeBrowserPath\x18\x02 \x01(\t\"\x9e\x01\n\x1b\x42rowserSwitcherUrlListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x41\n\x16\x42rowserSwitcherUrlList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!AlternativeBrowserParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x41lternativeBrowserParameters\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1f\x42rowserSwitcherUrlGreylistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x42rowserSwitcherUrlGreylist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x42rowserSwitcherParsingModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x42rowserSwitcherParsingMode\x18\x02 \x01(\x03\"\x8f\x01\n%BrowserSwitcherKeepLastChromeTabProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n BrowserSwitcherKeepLastChromeTab\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x42rowserSwitcherChromePathProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x42rowserSwitcherChromePath\x18\x02 \x01(\t\"k\n\x13IsolateOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eIsolateOrigins\x18\x02 \x01(\t\"y\n\x1a\x46orceGoogleSafeSearchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46orceGoogleSafeSearch\x18\x02 \x01(\x08\"\x91\x01\n&LoginDisplayPasswordButtonEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!LoginDisplayPasswordButtonEnabled\x18\x02 \x01(\x08\"\x85\x01\n SecondaryGoogleAccountUsageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bSecondaryGoogleAccountUsage\x18\x02 \x01(\t\"\x85\x01\n EncryptedClientHelloEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x45ncryptedClientHelloEnabled\x18\x02 \x01(\x08\"y\n\x1aSSLVersionFallbackMinProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SSLVersionFallbackMin\x18\x02 \x01(\t\"s\n\x17NearbyShareAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12NearbyShareAllowed\x18\x02 \x01(\x08\"y\n\x1a\x44ownloadBubbleEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44ownloadBubbleEnabled\x18\x02 \x01(\x08\"\xa9\x01\n2DefaultSearchProviderContextMenuAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-DefaultSearchProviderContextMenuAccessAllowed\x18\x02 \x01(\x08\"s\n\x17ImportSearchEngineProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12ImportSearchEngine\x18\x02 \x01(\x08\"\x81\x01\n\x1eSystemFeaturesDisableModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SystemFeaturesDisableMode\x18\x02 \x01(\t\"\x99\x01\n*AdvancedProtectionDeepScanningEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%AdvancedProtectionDeepScanningEnabled\x18\x02 \x01(\x08\"\x85\x01\n TouchVirtualKeyboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bTouchVirtualKeyboardEnabled\x18\x02 \x01(\x08\"\xaa\x01\n!SafeBrowsingWhitelistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSafeBrowsingWhitelistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1d\x41llowSystemNotificationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowSystemNotifications\x18\x02 \x01(\x08\"\x94\x01\n\x16\x41utoOpenFileTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoOpenFileTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1ePolicyAtomicGroupsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PolicyAtomicGroupsEnabled\x18\x02 \x01(\x08\"\xa4\x01\n\x1e\x45xtensionInstallWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#CACertificateManagementAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x43\x41\x43\x65rtificateManagementAllowed\x18\x02 \x01(\x03\"q\n\x16\x46ullscreenAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x46ullscreenAllowed\x18\x02 \x01(\x08\"\x97\x01\n)EnterpriseHardwarePlatformAPIEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$EnterpriseHardwarePlatformAPIEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$LacrosDataBackwardMigrationModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fLacrosDataBackwardMigrationMode\x18\x02 \x01(\t\"g\n\x11SyncDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cSyncDisabled\x18\x02 \x01(\x08\"\xd4\x01\n6CertificateTransparencyEnforcementDisabledForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\\\n1CertificateTransparencyEnforcementDisabledForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"i\n\x12HttpsOnlyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rHttpsOnlyMode\x18\x02 \x01(\t\"}\n\x1cLensRegionSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17LensRegionSearchEnabled\x18\x02 \x01(\x08\"\xa7\x01\n1RequireOnlineRevocationChecksForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,RequireOnlineRevocationChecksForLocalAnchors\x18\x02 \x01(\x08\"\x91\x01\n&SuppressChromeFrameTurndownPromptProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!SuppressChromeFrameTurndownPrompt\x18\x02 \x01(\x08\"{\n\x1bVmManagementCliAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16VmManagementCliAllowed\x18\x02 \x01(\x08\"w\n\x19\x44\x65skTemplatesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65skTemplatesEnabled\x18\x02 \x01(\x08\"m\n\x14ImportBookmarksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fImportBookmarks\x18\x02 \x01(\x08\"\x7f\n\x1d\x41llowChromeDataInBackupsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowChromeDataInBackups\x18\x02 \x01(\x08\"y\n\x1a\x41llowedDomainsForAppsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x41llowedDomainsForApps\x18\x02 \x01(\t\"\x8e\x01\n\x13SessionLocalesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0eSessionLocales\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$AllowWebAuthnWithBrokenTlsCertsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41llowWebAuthnWithBrokenTlsCerts\x18\x02 \x01(\x08\"\x97\x01\n)StartupBrowserWindowLaunchSuppressedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$StartupBrowserWindowLaunchSuppressed\x18\x02 \x01(\x08\"\xa4\x01\n\x1eSystemFeaturesDisableListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19SystemFeaturesDisableList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x46orceNetworkInProcessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x46orceNetworkInProcess\x18\x02 \x01(\x08\"s\n\x17\x46orceBrowserSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x46orceBrowserSignin\x18\x02 \x01(\x08\"\x85\x01\n MediaRecommendationsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bMediaRecommendationsEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'CloudPolicyOverridesPlatformPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"CloudPolicyOverridesPlatformPolicy\x18\x02 \x01(\x08\"\x87\x01\n!PhoneHubNotificationsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cPhoneHubNotificationsAllowed\x18\x02 \x01(\x08\"\xa3\x01\n/MachineLevelUserCloudPolicyEnrollmentTokenProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*MachineLevelUserCloudPolicyEnrollmentToken\x18\x02 \x01(\t\"\xa8\x01\n ClearBrowsingDataOnExitListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1b\x43learBrowsingDataOnExitList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x99\x01\n*VirtualKeyboardResizesLayoutByDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%VirtualKeyboardResizesLayoutByDefault\x18\x02 \x01(\x08\"y\n\x1aShelfAutoHideBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ShelfAutoHideBehavior\x18\x02 \x01(\t\"\xa0\x01\n\x1cTabDiscardingExceptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17TabDiscardingExceptions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x99\x01\n*InsecurePrivateNetworkRequestsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%InsecurePrivateNetworkRequestsAllowed\x18\x02 \x01(\x08\"\x8b\x01\n#CloudManagementEnrollmentTokenProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x43loudManagementEnrollmentToken\x18\x02 \x01(\t\"s\n\x17LacrosAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12LacrosAvailability\x18\x02 \x01(\t\"{\n\x1bPersistentQuotaEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PersistentQuotaEnabled\x18\x02 \x01(\x08\"u\n\x18\x44isablePluginFinderProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x44isablePluginFinder\x18\x02 \x01(\x08\"w\n\x19\x41llowOutdatedPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41llowOutdatedPlugins\x18\x02 \x01(\x08\"\x83\x01\n\x1fPreconfiguredDeskTemplatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPreconfiguredDeskTemplates\x18\x02 \x01(\t\"}\n\x1cMetricsReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17MetricsReportingEnabled\x18\x02 \x01(\x08\"\xd2\x01\n5CertificateTransparencyEnforcementDisabledForCasProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0CertificateTransparencyEnforcementDisabledForCas\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1aLocalDiscoveryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15LocalDiscoveryEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%DisableSafeBrowsingProceedAnywayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n DisableSafeBrowsingProceedAnyway\x18\x02 \x01(\x08\"\x98\x01\n\x18\x41llowedInputMethodsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n\x13\x41llowedInputMethods\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bWebAppInstallForceListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WebAppInstallForceList\x18\x02 \x01(\t\"\x7f\n\x1dU2fSecurityKeyApiEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18U2fSecurityKeyApiEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1eHighEfficiencyModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19HighEfficiencyModeEnabled\x18\x02 \x01(\x08\"\xae\x01\n#PrintingAPIExtensionsWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1ePrintingAPIExtensionsWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17SmsMessagesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12SmsMessagesAllowed\x18\x02 \x01(\x08\"\x93\x01\n\'ProfilePickerOnStartupAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"ProfilePickerOnStartupAvailability\x18\x02 \x01(\x03\"k\n\x13RelaunchWindowProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eRelaunchWindow\x18\x02 \x01(\t\"m\n\x14\x46orceSafeSearchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x46orceSafeSearch\x18\x02 \x01(\x08\"s\n\x17\x44isableScreenshotsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x44isableScreenshots\x18\x02 \x01(\x08\"{\n\x1b\x44\x65veloperToolsDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x44\x65veloperToolsDisabled\x18\x02 \x01(\x08\"\x94\x01\n\x16\x41utoplayAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoplayAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17\x42rowserLabsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x42rowserLabsEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fReportCrostiniUsageEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aReportCrostiniUsageEnabled\x18\x02 \x01(\x08\"\xa2\x01\n\x1dNativeMessagingBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x41utofillAddressEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41utofillAddressEnabled\x18\x02 \x01(\x08\"{\n\x1b\x46ullscreenAlertEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46ullscreenAlertEnabled\x18\x02 \x01(\x08\"o\n\x15HideWebStoreIconProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10HideWebStoreIcon\x18\x02 \x01(\x08\"\xaa\x01\n!SecurityKeyPermitAttestationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSecurityKeyPermitAttestation\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x95\x01\n(OnFileDownloadedEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#OnFileDownloadedEnterpriseConnector\x18\x02 \x01(\t\"u\n\x18\x43\x43TToSDialogEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43\x43TToSDialogEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dIntranetRedirectBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18IntranetRedirectBehavior\x18\x02 \x01(\x03\"\x81\x01\n\x1ePhoneHubCameraRollAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PhoneHubCameraRollAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"ManagedConfigurationPerOriginProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dManagedConfigurationPerOrigin\x18\x02 \x01(\t\"\x8b\x01\n#UserDataSnapshotRetentionLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUserDataSnapshotRetentionLimit\x18\x02 \x01(\x03\"\x8b\x01\n#DeskAPIThirdPartyAccessEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65skAPIThirdPartyAccessEnabled\x18\x02 \x01(\x08\"\x97\x01\n)CORSNonWildcardRequestHeadersSupportProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$CORSNonWildcardRequestHeadersSupport\x18\x02 \x01(\x08\"q\n\x16\x42rowserThemeColorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x42rowserThemeColor\x18\x02 \x01(\t\"\xb4\x01\n&NoteTakingAppsLockScreenWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!NoteTakingAppsLockScreenWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#LockScreenMediaPlaybackEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eLockScreenMediaPlaybackEnabled\x18\x02 \x01(\x08\"s\n\x17TotalMemoryLimitMbProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12TotalMemoryLimitMb\x18\x02 \x01(\x03\"\x83\x01\n\x1fOnPrintEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aOnPrintEnterpriseConnector\x18\x02 \x01(\t\"y\n\x1aRelaunchHeadsUpPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15RelaunchHeadsUpPeriod\x18\x02 \x01(\x03\"g\n\x11WebSQLAccessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cWebSQLAccess\x18\x02 \x01(\x08\"o\n\x15ManagedBookmarksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ManagedBookmarks\x18\x02 \x01(\t\"\x83\x01\n\x1f\x44\x65veloperToolsAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x44\x65veloperToolsAvailability\x18\x02 \x01(\x03\"\x87\x01\n!SuppressUnsupportedOSWarningProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSuppressUnsupportedOSWarning\x18\x02 \x01(\x08\"\x8f\x01\n%DefaultHandlersForFileExtensionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n DefaultHandlersForFileExtensions\x18\x02 \x01(\t\"\x81\x01\n\x1eWarnBeforeQuittingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WarnBeforeQuittingEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'OnSecurityEventEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OnSecurityEventEnterpriseConnector\x18\x02 \x01(\t\"\xa3\x01\n/StrictMimetypeCheckForWorkerScriptsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*StrictMimetypeCheckForWorkerScriptsEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ManagedAccountsSigninRestrictionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ManagedAccountsSigninRestriction\x18\x02 \x01(\t\"{\n\x1bRemoteDebuggingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RemoteDebuggingAllowed\x18\x02 \x01(\x08\"\x87\x01\n!ContextualSuggestionsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43ontextualSuggestionsEnabled\x18\x02 \x01(\x08\"o\n\x15VpnConfigAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10VpnConfigAllowed\x18\x02 \x01(\x08\"s\n\x17WebRtcUdpPortRangeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12WebRtcUdpPortRange\x18\x02 \x01(\t\"\xac\x01\n\"ExternalPrintServersWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xternalPrintServersWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"i\n\x12\x44iskCacheSizeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDiskCacheSize\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x41llowFileSelectionDialogsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41llowFileSelectionDialogs\x18\x02 \x01(\x08\"\xa0\x01\n\x1c\x41udioCaptureAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x41udioCaptureAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x46orceYouTubeRestrictProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x46orceYouTubeRestrict\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x45\x63ryptfsMigrationStrategyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x45\x63ryptfsMigrationStrategy\x18\x02 \x01(\x03\"\x8b\x01\n#AutoLaunchProtocolsFromOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41utoLaunchProtocolsFromOrigins\x18\x02 \x01(\t\"g\n\x11\x44iskCacheDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0c\x44iskCacheDir\x18\x02 \x01(\t\"\x8b\x01\n#AdditionalDnsQueryTypesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41\x64\x64itionalDnsQueryTypesEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"AttestationExtensionWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x41ttestationExtensionWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#UnifiedDesktopEnabledByDefaultProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUnifiedDesktopEnabledByDefault\x18\x02 \x01(\x08\"\xa3\x01\n/SendMouseEventsDisabledFormControlsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*SendMouseEventsDisabledFormControlsEnabled\x18\x02 \x01(\x08\"\x96\x01\n\x17SpellcheckLanguageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12SpellcheckLanguage\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44nsPrefetchingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44nsPrefetchingEnabled\x18\x02 \x01(\x08\"{\n\x1bImportAutofillFormDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ImportAutofillFormData\x18\x02 \x01(\x08\"s\n\x17UserAgentReductionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12UserAgentReduction\x18\x02 \x01(\x03\"\x87\x01\n!NativeWindowOcclusionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNativeWindowOcclusionEnabled\x18\x02 \x01(\x08\"}\n\x1c\x45xternalStorageDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45xternalStorageDisabled\x18\x02 \x01(\x08\"\x83\x01\n\x1f\x41lternateErrorPagesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41lternateErrorPagesEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x44\x65\x66\x61ultDownloadDirectoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultDownloadDirectory\x18\x02 \x01(\t\"m\n\x14\x41utoplayAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41utoplayAllowed\x18\x02 \x01(\x08\"\x8f\x01\n%WebSQLInThirdPartyContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n WebSQLInThirdPartyContextEnabled\x18\x02 \x01(\x08\"\x85\x01\n DataLeakPreventionRulesListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x61taLeakPreventionRulesList\x18\x02 \x01(\t\"}\n\x1c\x42\x61\x63kForwardCacheEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42\x61\x63kForwardCacheEnabled\x18\x02 \x01(\x08\"{\n\x1bShowLogoutButtonInTrayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ShowLogoutButtonInTray\x18\x02 \x01(\x08\"g\n\x11HeadlessModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cHeadlessMode\x18\x02 \x01(\x03\"\x83\x01\n\x1fPrefixedStorageInfoEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPrefixedStorageInfoEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1ePerAppTimeLimitsWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PerAppTimeLimitsWhitelist\x18\x02 \x01(\t\"\x83\x01\n\x1fNTPCustomBackgroundEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aNTPCustomBackgroundEnabled\x18\x02 \x01(\x08\"\x87\x01\n!TaskManagerEndProcessEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cTaskManagerEndProcessEnabled\x18\x02 \x01(\x08\"k\n\x13KeyPermissionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eKeyPermissions\x18\x02 \x01(\t\"}\n\x1c\x42uiltInDnsClientEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42uiltInDnsClientEnabled\x18\x02 \x01(\x08\"\x97\x01\n)StricterMixedContentTreatmentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$StricterMixedContentTreatmentEnabled\x18\x02 \x01(\x08\"o\n\x15TripleDESEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10TripleDESEnabled\x18\x02 \x01(\x08\"\x91\x01\n&BuiltinCertificateVerifierEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!BuiltinCertificateVerifierEnabled\x18\x02 \x01(\x08\"\xb8\x01\n(EnableDeprecatedWebPlatformFeaturesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#EnableDeprecatedWebPlatformFeatures\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x90\x01\n\x14\x44isabledPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x44isabledPlugins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bMaxConnectionsPerProxyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16MaxConnectionsPerProxy\x18\x02 \x01(\x03\"\x9d\x01\n,SecurityTokenSessionNotificationSecondsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'SecurityTokenSessionNotificationSeconds\x18\x02 \x01(\x03\"\xa5\x01\n0ThrottleNonVisibleCrossOriginIframesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+ThrottleNonVisibleCrossOriginIframesAllowed\x18\x02 \x01(\x08\"\x8b\x01\n#Http09OnNonDefaultPortsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eHttp09OnNonDefaultPortsEnabled\x18\x02 \x01(\x08\"k\n\x13WebAppSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eWebAppSettings\x18\x02 \x01(\t\"\x8d\x01\n$AudioProcessHighPriorityEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41udioProcessHighPriorityEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'EnableSymantecLegacyInfrastructureProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"EnableSymantecLegacyInfrastructure\x18\x02 \x01(\x08\"\x96\x01\n\x17PinnedLauncherAppsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12PinnedLauncherApps\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8f\x01\n%SetTimeoutWithout1MsClampEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n SetTimeoutWithout1MsClampEnabled\x18\x02 \x01(\x08\"y\n\x1a\x43orsLegacyModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43orsLegacyModeEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x46loatingWorkspaceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x46loatingWorkspaceEnabled\x18\x02 \x01(\x08\"\xa6\x01\n\x1fRestrictAccountsToPatternsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aRestrictAccountsToPatterns\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bRoamingProfileLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RoamingProfileLocation\x18\x02 \x01(\t\"y\n\x1aSitePerProcessAndroidProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15SitePerProcessAndroid\x18\x02 \x01(\x08\"y\n\x1a\x41ppStoreRatingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x41ppStoreRatingEnabled\x18\x02 \x01(\x08\"\x85\x01\n UserAgentClientHintsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bUserAgentClientHintsEnabled\x18\x02 \x01(\x08\"\xe0\x01\n<RestrictedManagedGuestSessionExtensionCleanupExemptListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x62\n7RestrictedManagedGuestSessionExtensionCleanupExemptList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"}\n\x1cWebXRImmersiveArEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17WebXRImmersiveArEnabled\x18\x02 \x01(\x08\"\x87\x01\n!DefaultBrowserSettingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultBrowserSettingEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ForceLegacyDefaultReferrerPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ForceLegacyDefaultReferrerPolicy\x18\x02 \x01(\x08\"e\n\x10OsColorModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bOsColorMode\x18\x02 \x01(\t\"{\n\x1b\x46orceEphemeralProfilesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46orceEphemeralProfiles\x18\x02 \x01(\x08\"\x90\x01\n\x14WebAuthnFactorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0fWebAuthnFactors\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n RendererAppContainerEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bRendererAppContainerEnabled\x18\x02 \x01(\x08\"c\n\x0f\x44HEEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nDHEEnabled\x18\x02 \x01(\x08\"y\n\x1aIsolateOriginsAndroidProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15IsolateOriginsAndroid\x18\x02 \x01(\t\"\x8b\x01\n#AuthNegotiateDelegateWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41uthNegotiateDelegateWhitelist\x18\x02 \x01(\t\"w\n\x19\x44ownloadRestrictionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44ownloadRestrictions\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x43hromeOsLockOnIdleSuspendProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x43hromeOsLockOnIdleSuspend\x18\x02 \x01(\x08\"q\n\x16ScreenTimeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ScreenTimeEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%OptimizationGuideFetchingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n OptimizationGuideFetchingEnabled\x18\x02 \x01(\x08\"\xa8\x01\n NativePrintersBulkWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNativePrintersBulkWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"o\n\x15IncognitoEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10IncognitoEnabled\x18\x02 \x01(\x08\"y\n\x1a\x45nterpriseWebStoreURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x45nterpriseWebStoreURL\x18\x02 \x01(\t\"\x89\x01\n\"WebSQLNonSecureContextEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWebSQLNonSecureContextEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x41utofillCreditCardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41utofillCreditCardEnabled\x18\x02 \x01(\x08\"\x9d\x01\n,UserAgentClientHintsGREASEUpdateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'UserAgentClientHintsGREASEUpdateEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1eMaxInvalidationFetchDelayProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19MaxInvalidationFetchDelay\x18\x02 \x01(\x03\"u\n\x18UserFeedbackAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserFeedbackAllowed\x18\x02 \x01(\x08\"\x8f\x01\n%NTPMiddleSlotAnnouncementVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n NTPMiddleSlotAnnouncementVisible\x18\x02 \x01(\x08\"\x9b\x01\n+CommandLineFlagSecurityWarningsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&CommandLineFlagSecurityWarningsEnabled\x18\x02 \x01(\x08\"e\n\x10UserDataDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bUserDataDir\x18\x02 \x01(\t\"\x81\x01\n\x1eSigninInterceptionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SigninInterceptionEnabled\x18\x02 \x01(\x08\"s\n\x17TabFreezingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12TabFreezingEnabled\x18\x02 \x01(\x08\"q\n\x16\x45\x61syUnlockAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45\x61syUnlockAllowed\x18\x02 \x01(\x08\"\xa4\x01\n\x1eWebRtcLocalIpsAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19WebRtcLocalIpsAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1d\x42rowserGuestModeEnforcedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x42rowserGuestModeEnforced\x18\x02 \x01(\x08\"\x83\x01\n\x1fHindiInscriptLayoutEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aHindiInscriptLayoutEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"ShowAppsShortcutInBookmarkBarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dShowAppsShortcutInBookmarkBar\x18\x02 \x01(\x08\"\xb8\x01\n(UnsafelyTreatInsecureOriginAsSecureProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#UnsafelyTreatInsecureOriginAsSecure\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14UserAvatarImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fUserAvatarImage\x18\x02 \x01(\t\"u\n\x18VideoCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13VideoCaptureAllowed\x18\x02 \x01(\x08\"e\n\x10\x44isableSpdyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x44isableSpdy\x18\x02 \x01(\x08\"}\n\x1c\x43omponentUpdatesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43omponentUpdatesEnabled\x18\x02 \x01(\x08\"\x97\x01\n)NewBaseUrlInheritanceBehaviorAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$NewBaseUrlInheritanceBehaviorAllowed\x18\x02 \x01(\x08\"\x91\x01\n&PPAPISharedImagesSwapChainAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!PPAPISharedImagesSwapChainAllowed\x18\x02 \x01(\x08\"\x7f\n\x1dOpenNetworkConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18OpenNetworkConfiguration\x18\x02 \x01(\t\"\x93\x01\n\'OffsetParentNewSpecBehaviorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OffsetParentNewSpecBehaviorEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%BrowserNetworkTimeQueriesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n BrowserNetworkTimeQueriesEnabled\x18\x02 \x01(\x08\"\x87\x01\n!EnableOnlineRevocationChecksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x45nableOnlineRevocationChecks\x18\x02 \x01(\x08\"\xb4\x01\n&PolicyListMultipleSourceMergeListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!PolicyListMultipleSourceMergeList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fTargetBlankImpliesNoOpenerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aTargetBlankImpliesNoOpener\x18\x02 \x01(\x08\"\x9d\x01\n,EnableCommonNameFallbackForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'EnableCommonNameFallbackForLocalAnchors\x18\x02 \x01(\x08\"\x85\x01\n ScrollToTextFragmentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bScrollToTextFragmentEnabled\x18\x02 \x01(\x08\"\x8a\x01\n\x11URLBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x91\x01\n&OnFileTransferEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!OnFileTransferEnterpriseConnector\x18\x02 \x01(\t\"\x93\x01\n\'ClientCertificateManagementAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"ClientCertificateManagementAllowed\x18\x02 \x01(\x03\"{\n\x1bSharedClipboardEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SharedClipboardEnabled\x18\x02 \x01(\x08\"w\n\x19\x43loudUserPolicyMergeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x43loudUserPolicyMerge\x18\x02 \x01(\x08\"y\n\x1aPdfAnnotationsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15PdfAnnotationsEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$UnthrottledNestedTimeoutEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fUnthrottledNestedTimeoutEnabled\x18\x02 \x01(\x08\"e\n\x10\x45\x63heAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0b\x45\x63heAllowed\x18\x02 \x01(\x08\"\x91\x01\n&GloballyScopeHTTPAuthCacheEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!GloballyScopeHTTPAuthCacheEnabled\x18\x02 \x01(\x08\"\x85\x01\n LensDesktopNTPSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bLensDesktopNTPSearchEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#EnableDeprecatedPrivetPrintingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nableDeprecatedPrivetPrinting\x18\x02 \x01(\x08\"k\n\x13WallpaperImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eWallpaperImage\x18\x02 \x01(\t\"{\n\x1bRunAllFlashInAllowModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RunAllFlashInAllowMode\x18\x02 \x01(\x08\"\x7f\n\x1dInsightsExtensionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18InsightsExtensionEnabled\x18\x02 \x01(\x08\"w\n\x19\x42rowsingDataLifetimeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x42rowsingDataLifetime\x18\x02 \x01(\t\"}\n\x1cInstantTetheringAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17InstantTetheringAllowed\x18\x02 \x01(\x08\"\x94\x01\n\x16\x41utoplayWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12<\n\x11\x41utoplayWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x41\x63\x63\x65ssCodeCastEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x41\x63\x63\x65ssCodeCastEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%IsolatedAppsDeveloperModeAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n IsolatedAppsDeveloperModeAllowed\x18\x02 \x01(\x08\"{\n\x1b\x45mojiSuggestionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x45mojiSuggestionEnabled\x18\x02 \x01(\x08\"{\n\x1bWebComponentsV0EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WebComponentsV0Enabled\x18\x02 \x01(\x08\"u\n\x18ShoppingListEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ShoppingListEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'CloudManagementEnrollmentMandatoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"CloudManagementEnrollmentMandatory\x18\x02 \x01(\x08\"k\n\x13ShelfAlignmentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eShelfAlignment\x18\x02 \x01(\t\"{\n\x1b\x43opyPreventionSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43opyPreventionSettings\x18\x02 \x01(\t\"{\n\x1bWindowOcclusionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WindowOcclusionEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%IntensiveWakeUpThrottlingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n IntensiveWakeUpThrottlingEnabled\x18\x02 \x01(\x08\"y\n\x1aUrlParamFilterEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15UrlParamFilterEnabled\x18\x02 \x01(\x08\"{\n\x1bWifiSyncAndroidAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16WifiSyncAndroidAllowed\x18\x02 \x01(\x08\"\x85\x01\n DataCompressionProxyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x61taCompressionProxyEnabled\x18\x02 \x01(\x08\"\x9c\x01\n\x1aSyncTypesListDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SyncTypesListDisabled\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x46orceYouTubeSafetyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x46orceYouTubeSafetyMode\x18\x02 \x01(\x08\"{\n\x1b\x41pplicationLocaleValueProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41pplicationLocaleValue\x18\x02 \x01(\t\"\x9d\x01\n,DeviceLocalAccountManagedSessionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'DeviceLocalAccountManagedSessionEnabled\x18\x02 \x01(\x08\"\xa1\x01\n.EnterpriseProfileCreationKeepBrowsingDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)EnterpriseProfileCreationKeepBrowsingData\x18\x02 \x01(\x08\"c\n\x0fRC4EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nRC4Enabled\x18\x02 \x01(\x08\"\x8b\x01\n#UsbDetectorNotificationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eUsbDetectorNotificationEnabled\x18\x02 \x01(\x08\"\x92\x01\n\x15\x41llowedLanguagesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10\x41llowedLanguages\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$HardwareAccelerationModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fHardwareAccelerationModeEnabled\x18\x02 \x01(\x08\"\xa3\x01\n/AmbientAuthenticationInPrivateModesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*AmbientAuthenticationInPrivateModesEnabled\x18\x02 \x01(\x03\"w\n\x19\x43hromeCleanupEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x43hromeCleanupEnabled\x18\x02 \x01(\x08\"o\n\x15\x43hromeVariationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x43hromeVariations\x18\x02 \x01(\x03\"\x81\x01\n\x1ePaymentMethodQueryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PaymentMethodQueryEnabled\x18\x02 \x01(\x08\"i\n\x12ProxySettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rProxySettings\x18\x02 \x01(\t\"\xb9\x01\n:ExemptDomainFileTypePairsFromFileTypeDownloadWarningsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n5ExemptDomainFileTypePairsFromFileTypeDownloadWarnings\x18\x02 \x01(\t\"\xa1\x01\n.SafeBrowsingExtendedReportingOptInAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)SafeBrowsingExtendedReportingOptInAllowed\x18\x02 \x01(\x08\"\xa6\x01\n\x1f\x45nableExperimentalPoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x45nableExperimentalPolicies\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#EnableDeprecatedWebBasedSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nableDeprecatedWebBasedSignin\x18\x02 \x01(\x08\"\xa2\x01\n\x1dNativeMessagingWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18\x41udioCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41udioCaptureAllowed\x18\x02 \x01(\x08\"}\n\x1c\x45xternalStorageReadOnlyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x45xternalStorageReadOnly\x18\x02 \x01(\x08\"\x8d\x01\n$LensCameraAssistedSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fLensCameraAssistedSearchEnabled\x18\x02 \x01(\x08\"\x9b\x01\n+WebDriverOverridesIncompatiblePoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&WebDriverOverridesIncompatiblePolicies\x18\x02 \x01(\x08\"s\n\x17SessionLengthLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12SessionLengthLimit\x18\x02 \x01(\x03\"\x7f\n\x1dPrimaryMouseButtonSwitchProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PrimaryMouseButtonSwitch\x18\x02 \x01(\x08\"\x90\x01\n\x14\x46orcedLanguagesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x46orcedLanguages\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n LockIconInAddressBarEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bLockIconInAddressBarEnabled\x18\x02 \x01(\x08\"\xd2\x01\n5GetDisplayMediaSetSelectAllScreensAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0GetDisplayMediaSetSelectAllScreensAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"o\n\x15\x45ventPathEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x45ventPathEnabled\x18\x02 \x01(\x08\"y\n\x1a\x44nsOverHttpsTemplatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44nsOverHttpsTemplates\x18\x02 \x01(\t\"{\n\x1bSmartLockSigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SmartLockSigninAllowed\x18\x02 \x01(\x08\"\x9e\x01\n\x1b\x41utoOpenAllowedForURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x41\n\x16\x41utoOpenAllowedForURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x95\x01\n(ExtensionInstallEventLoggingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#ExtensionInstallEventLoggingEnabled\x18\x02 \x01(\x08\"}\n\x1cSuggestedContentEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SuggestedContentEnabled\x18\x02 \x01(\x08\"q\n\x16PolicyRefreshRateProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11PolicyRefreshRate\x18\x02 \x01(\x03\"\xa6\x01\n\x1f\x44\x65skAPIThirdPartyAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x44\x65skAPIThirdPartyAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eIncognitoModeAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19IncognitoModeAvailability\x18\x02 \x01(\x03\"\x87\x01\n!RendererCodeIntegrityEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRendererCodeIntegrityEnabled\x18\x02 \x01(\x08\"m\n\x14NTPCardsVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fNTPCardsVisible\x18\x02 \x01(\x08\"\x8b\x01\n#AdsSettingForIntrusiveAdsSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41\x64sSettingForIntrusiveAdsSites\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x41\x64vancedProtectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41\x64vancedProtectionAllowed\x18\x02 \x01(\x08\"\x9d\x01\n,UrlKeyedAnonymizedDataCollectionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'UrlKeyedAnonymizedDataCollectionEnabled\x18\x02 \x01(\x08\"{\n\x1b\x41llowDinosaurEasterEggProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41llowDinosaurEasterEgg\x18\x02 \x01(\x08\"\xd8\x01\n8CoalesceH2ConnectionsWithClientCertificatesForHostsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12^\n3CoalesceH2ConnectionsWithClientCertificatesForHosts\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18\x43learSiteDataOnExitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x43learSiteDataOnExit\x18\x02 \x01(\x08\"}\n\x1c\x46orceMaximizeOnFirstRunProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x46orceMaximizeOnFirstRun\x18\x02 \x01(\x08\"}\n\x1c\x41lwaysOpenPdfExternallyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41lwaysOpenPdfExternally\x18\x02 \x01(\x08\"q\n\x16\x43hromeAppsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x43hromeAppsEnabled\x18\x02 \x01(\x08\"w\n\x19RelaunchNotificationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14RelaunchNotification\x18\x02 \x01(\x03\"\x87\x01\n!SavingBrowserHistoryDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSavingBrowserHistoryDisabled\x18\x02 \x01(\x08\"\x87\x01\n!NTPContentSuggestionsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNTPContentSuggestionsEnabled\x18\x02 \x01(\x08\"\x85\x01\n VariationsRestrictParameterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bVariationsRestrictParameter\x18\x02 \x01(\t\"\x9d\x01\n,FetchKeepaliveDurationSecondsOnShutdownProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'FetchKeepaliveDurationSecondsOnShutdown\x18\x02 \x01(\x03\"w\n\x19\x41ppCacheForceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41ppCacheForceEnabled\x18\x02 \x01(\x08\"\x87\x01\n!SecurityTokenSessionBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSecurityTokenSessionBehavior\x18\x02 \x01(\t\"\x90\x01\n\x14\x44isabledSchemesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12:\n\x0f\x44isabledSchemes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa3\x01\n/CrossOriginWebAssemblyModuleSharingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*CrossOriginWebAssemblyModuleSharingEnabled\x18\x02 \x01(\x08\"\x95\x01\n(UseMojoVideoDecoderForPepperAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#UseMojoVideoDecoderForPepperAllowed\x18\x02 \x01(\x08\"k\n\x13InstantEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eInstantEnabled\x18\x02 \x01(\x08\"\xc0\x01\n,PolicyDictionaryMultipleSourceMergeListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12R\n\'PolicyDictionaryMultipleSourceMergeList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x97\x01\n)PromptOnMultipleMatchingCertificatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$PromptOnMultipleMatchingCertificates\x18\x02 \x01(\x08\"{\n\x1b\x43hromeRootStoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x43hromeRootStoreEnabled\x18\x02 \x01(\x08\"\x85\x01\n AllowPopupsDuringPageUnloadProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowPopupsDuringPageUnload\x18\x02 \x01(\x08\"\xa2\x01\n\x1dQuickUnlockModeWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18QuickUnlockModeWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18\x41udioSandboxEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41udioSandboxEnabled\x18\x02 \x01(\x08\"\x8a\x01\n\x11URLAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x44isabledPluginsExceptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x44isabledPluginsExceptions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa9\x01\n2WebAuthenticationRemoteProxiedRequestsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-WebAuthenticationRemoteProxiedRequestsAllowed\x18\x02 \x01(\x08\"\x87\x01\n!NetworkServiceSandboxEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNetworkServiceSandboxEnabled\x18\x02 \x01(\x08\"\xa8\x01\n SpellcheckLanguageBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bSpellcheckLanguageBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xca\x01\n1InsecurePrivateNetworkRequestsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12W\n,InsecurePrivateNetworkRequestsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1dLoadCryptoTokenExtensionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18LoadCryptoTokenExtension\x18\x02 \x01(\x08\"\xa0\x01\n\x1cVideoCaptureAllowedUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17VideoCaptureAllowedUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bSchedulerConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16SchedulerConfiguration\x18\x02 \x01(\t\"y\n\x1aWPADQuickCheckEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15WPADQuickCheckEnabled\x18\x02 \x01(\x08\"}\n\x1cSSLErrorOverrideAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SSLErrorOverrideAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"ChromeCleanupReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43hromeCleanupReportingEnabled\x18\x02 \x01(\x08\"\xb4\x01\n&SSLErrorOverrideAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!SSLErrorOverrideAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"k\n\x13GCFUserDataDirProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eGCFUserDataDir\x18\x02 \x01(\t\"\xb6\x01\n\'ContextAwareAccessSignalsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12M\n\"ContextAwareAccessSignalsAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x42lockThirdPartyCookiesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x42lockThirdPartyCookies\x18\x02 \x01(\x08\"\xa8\x01\n NativePrintersBulkBlacklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNativePrintersBulkBlacklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9f\x01\n-UnmanagedDeviceSignalsConsentFlowEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(UnmanagedDeviceSignalsConsentFlowEnabled\x18\x02 \x01(\x08\"w\n\x19PolicyScopeDetectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PolicyScopeDetection\x18\x02 \x01(\x08\"w\n\x19\x45\x64itBookmarksEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x45\x64itBookmarksEnabled\x18\x02 \x01(\x08\"g\n\x11TrashEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cTrashEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#LacrosSecondaryProfilesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eLacrosSecondaryProfilesAllowed\x18\x02 \x01(\x08\"q\n\x16SideSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SideSearchEnabled\x18\x02 \x01(\x08\"i\n\x12\x43\x45\x43PQ2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rCECPQ2Enabled\x18\x02 \x01(\x08\"o\n\x15TranslateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10TranslateEnabled\x18\x02 \x01(\x08\"\x9a\x01\n\x19HSTSPolicyBypassListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14HSTSPolicyBypassList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9f\x01\n-SamlLockScreenOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(SamlLockScreenOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"\xa5\x01\n0ForceMajorVersionToMinorPositionInUserAgentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x33\n+ForceMajorVersionToMinorPositionInUserAgent\x18\x02 \x01(\x03\"}\n\x1c\x42rowserGuestModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42rowserGuestModeEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dShowFullUrlsInAddressBarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18ShowFullUrlsInAddressBar\x18\x02 \x01(\x08\"\x95\x01\n(SecondaryGoogleAccountSigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#SecondaryGoogleAccountSigninAllowed\x18\x02 \x01(\x08\"\x8b\x01\n#IsolatedWebAppInstallForceListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eIsolatedWebAppInstallForceList\x18\x02 \x01(\t\"\x95\x01\n(SuggestLogoutAfterClosingLastWindowProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#SuggestLogoutAfterClosingLastWindow\x18\x02 \x01(\x08\"\xa1\x01\n.DataLeakPreventionClipboardCheckSizeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DataLeakPreventionClipboardCheckSizeLimit\x18\x02 \x01(\x03\"i\n\x12SSLVersionMinProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSSLVersionMin\x18\x02 \x01(\t\"\x97\x01\n)SafeBrowsingForTrustedSourcesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SafeBrowsingForTrustedSourcesEnabled\x18\x02 \x01(\x08\"s\n\x17\x42ookmarkBarEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x42ookmarkBarEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$AccessibilityImageLabelsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x41\x63\x63\x65ssibilityImageLabelsEnabled\x18\x02 \x01(\x08\"q\n\x16JavascriptEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11JavascriptEnabled\x18\x02 \x01(\x08\"m\n\x14\x46\x61stPairEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x46\x61stPairEnabled\x18\x02 \x01(\x08\"\x9d\x01\n,CaptivePortalAuthenticationIgnoresProxyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'CaptivePortalAuthenticationIgnoresProxy\x18\x02 \x01(\x08\"i\n\x12\x42rowserSigninProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rBrowserSignin\x18\x02 \x01(\x03\"k\n\x13MediaCacheSizeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eMediaCacheSize\x18\x02 \x01(\x03\"\xaf\x01\n5ManagedGuestSessionAutoLaunchNotificationReducedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0ManagedGuestSessionAutoLaunchNotificationReduced\x18\x02 \x01(\x08\"\x8b\x01\n#SandboxExternalProtocolBlockedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eSandboxExternalProtocolBlocked\x18\x02 \x01(\x08\"\x81\x01\n\x1eThirdPartyBlockingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19ThirdPartyBlockingEnabled\x18\x02 \x01(\x08\"\x9b\x01\n+DisplayCapturePermissionsPolicyEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&DisplayCapturePermissionsPolicyEnabled\x18\x02 \x01(\x08\"}\n\x1c\x42rowserAddPersonEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42rowserAddPersonEnabled\x18\x02 \x01(\x08\"\x8d\x01\n$PhoneHubTaskContinuationAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPhoneHubTaskContinuationAllowed\x18\x02 \x01(\x08\"m\n\x14PhoneHubAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fPhoneHubAllowed\x18\x02 \x01(\x08\"i\n\x12\x44isable3DAPIsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDisable3DAPIs\x18\x02 \x01(\x08\"q\n\x16HideWebStorePromoProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11HideWebStorePromo\x18\x02 \x01(\x08\"m\n\x14LacrosSelectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fLacrosSelection\x18\x02 \x01(\t\"\xa3\x01\n/CloudUserPolicyOverridesCloudMachinePolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*CloudUserPolicyOverridesCloudMachinePolicy\x18\x02 \x01(\x08\"\x8e\x01\n\x13\x45nabledPluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x39\n\x0e\x45nabledPlugins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x97\x01\n)AbusiveExperienceInterventionEnforceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$AbusiveExperienceInterventionEnforce\x18\x02 \x01(\x08\"{\n\x1bHistoryClustersVisibleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16HistoryClustersVisible\x18\x02 \x01(\x08\"\xa3\x01\n/SharedArrayBufferUnrestrictedAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x32\n*SharedArrayBufferUnrestrictedAccessAllowed\x18\x02 \x01(\x08\"\x8a\x01\n\x11URLBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x42\x61\x63kgroundModeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x42\x61\x63kgroundModeEnabled\x18\x02 \x01(\x08\"\x99\x01\n*ForceLogoutUnauthenticatedUserEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%ForceLogoutUnauthenticatedUserEnabled\x18\x02 \x01(\x08\"\xde\x01\n;CertificateTransparencyEnforcementDisabledForLegacyCasProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x61\n6CertificateTransparencyEnforcementDisabledForLegacyCas\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"q\n\x16\x45nableSyncConsentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45nableSyncConsent\x18\x02 \x01(\x08\"\x9b\x01\n+SuppressDifferentOriginSubframeDialogsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&SuppressDifferentOriginSubframeDialogs\x18\x02 \x01(\x08\"\x89\x01\n\"WebRtcAllowLegacyTLSProtocolsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWebRtcAllowLegacyTLSProtocols\x18\x02 \x01(\x08\"\x81\x01\n\x1ePromptForDownloadLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PromptForDownloadLocation\x18\x02 \x01(\x08\"w\n\x19ImportSavedPasswordsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14ImportSavedPasswords\x18\x02 \x01(\x08\"\x95\x01\n(ForceEnablePepperVideoDecoderDevAPIProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#ForceEnablePepperVideoDecoderDevAPI\x18\x02 \x01(\x08\"\x87\x01\n!InsecureFormsWarningsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cInsecureFormsWarningsEnabled\x18\x02 \x01(\x08\"{\n\x1bPromotionalTabsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PromotionalTabsEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%OriginAgentClusterDefaultEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n OriginAgentClusterDefaultEnabled\x18\x02 \x01(\x08\"w\n\x19SearchSuggestEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14SearchSuggestEnabled\x18\x02 \x01(\x08\"\x85\x01\n PacHttpsUrlStrippingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPacHttpsUrlStrippingEnabled\x18\x02 \x01(\x08\"\xac\x01\n\"ExplicitlyAllowedNetworkPortsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x45xplicitlyAllowedNetworkPorts\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"}\n\x1cRestrictSigninToPatternProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17RestrictSigninToPattern\x18\x02 \x01(\t\"\x95\x01\n(BrowserLegacyExtensionPointsBlockedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#BrowserLegacyExtensionPointsBlocked\x18\x02 \x01(\x08\"\x7f\n\x1dSpellCheckServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18SpellCheckServiceEnabled\x18\x02 \x01(\x08\"m\n\x14TabUnderAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fTabUnderAllowed\x18\x02 \x01(\x08\"\x87\x01\n!BatterySaverModeAvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x42\x61tterySaverModeAvailability\x18\x02 \x01(\x03\"\x93\x01\n\'OnBulkDataEntryEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"OnBulkDataEntryEnterpriseConnector\x18\x02 \x01(\t\"i\n\x12LacrosAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rLacrosAllowed\x18\x02 \x01(\x08\"\x93\x01\n\'DataLeakPreventionReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DataLeakPreventionReportingEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x41llowNativeNotificationsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x41llowNativeNotifications\x18\x02 \x01(\x08\"\x8a\x01\n\x11URLWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n\x0cURLWhitelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa7\x01\n1ExternalProtocolDialogShowAlwaysOpenCheckboxProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,ExternalProtocolDialogShowAlwaysOpenCheckbox\x18\x02 \x01(\x08\"\x83\x01\n\x1fRelaunchNotificationPeriodProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aRelaunchNotificationPeriod\x18\x02 \x01(\x03\"\xb2\x01\n%LookalikeWarningAllowlistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12K\n LookalikeWarningAllowlistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xb4\x01\n&NoteTakingAppsLockScreenAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!NoteTakingAppsLockScreenAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"k\n\x13SitePerProcessProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eSitePerProcess\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x42ruschettaVMConfigurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x42ruschettaVMConfiguration\x18\x02 \x01(\t\"\x87\x01\n!DNSInterceptionChecksEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44NSInterceptionChecksEnabled\x18\x02 \x01(\x08\"\x7f\n\x1d\x44\x65sktopSharingHubEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65sktopSharingHubEnabled\x18\x02 \x01(\x08\"\x87\x01\n!AccessCodeCastDeviceDurationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x41\x63\x63\x65ssCodeCastDeviceDuration\x18\x02 \x01(\x03\"\xb4\x01\n&DeviceAttributesAllowedForOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12L\n!DeviceAttributesAllowedForOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x99\x01\n*EnterpriseAuthenticationAppLinkPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%EnterpriseAuthenticationAppLinkPolicy\x18\x02 \x01(\t\"y\n\x1aUseLegacyFormControlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15UseLegacyFormControls\x18\x02 \x01(\x08\"\x97\x01\n)TLS13HardeningForLocalAnchorsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$TLS13HardeningForLocalAnchorsEnabled\x18\x02 \x01(\x08\"e\n\x10QuicAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bQuicAllowed\x18\x02 \x01(\x08\"\x96\x01\n\x17\x43orsMitigationListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12\x43orsMitigationList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"m\n\x14UserDisplayNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fUserDisplayName\x18\x02 \x01(\t\"\x8d\x01\n$WebRtcEventLogCollectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fWebRtcEventLogCollectionAllowed\x18\x02 \x01(\x08\"o\n\x15WebRtcIPHandlingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10WebRtcIPHandling\x18\x02 \x01(\t\"\xcc\x01\n2KeepFullscreenWithoutNotificationUrlAllowListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12X\n-KeepFullscreenWithoutNotificationUrlAllowList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1f\x46loatingWorkspaceV2EnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x46loatingWorkspaceV2Enabled\x18\x02 \x01(\x08\"m\n\x14\x41utoFillEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41utoFillEnabled\x18\x02 \x01(\x08\"s\n\x17\x43lickToCallEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x43lickToCallEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1eSignedHTTPExchangeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19SignedHTTPExchangeEnabled\x18\x02 \x01(\x08\"i\n\x12SSLVersionMaxProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSSLVersionMax\x18\x02 \x01(\t\"s\n\x17\x41udioOutputAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x41udioOutputAllowed\x18\x02 \x01(\x08\"}\n\x1c\x43ontextualSearchEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43ontextualSearchEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x44isableSSLRecordSplittingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44isableSSLRecordSplitting\x18\x02 \x01(\x08\"\x7f\n\x1dNetworkPredictionOptionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NetworkPredictionOptions\x18\x02 \x01(\x03\"k\n\x13ImportHomepageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eImportHomepage\x18\x02 \x01(\x08\"\x8b\x01\n#EnterpriseRealTimeUrlCheckModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x45nterpriseRealTimeUrlCheckMode\x18\x02 \x01(\x03\"q\n\x16SpellcheckEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SpellcheckEnabled\x18\x02 \x01(\x08\"m\n\x14\x41llowScreenLockProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x41llowScreenLock\x18\x02 \x01(\x08\"\x89\x01\n\"WelcomePageOnOSUpgradeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dWelcomePageOnOSUpgradeEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x45nableSha1ForLocalAnchorsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x45nableSha1ForLocalAnchors\x18\x02 \x01(\x08\"i\n\x12SigninAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rSigninAllowed\x18\x02 \x01(\x08\"\x85\x01\n AllowDeletingBrowserHistoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowDeletingBrowserHistory\x18\x02 \x01(\x08\"u\n\x18\x41uthServerWhitelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13\x41uthServerWhitelist\x18\x02 \x01(\t\"q\n\x16TermsOfServiceURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11TermsOfServiceURL\x18\x02 \x01(\t\"\x91\x01\n&OnFileAttachedEnterpriseConnectorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!OnFileAttachedEnterpriseConnector\x18\x02 \x01(\t\"\x8f\x01\n%ChromeOsMultiProfileUserBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ChromeOsMultiProfileUserBehavior\x18\x02 \x01(\t\"}\n\x1cSafeSitesFilterBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17SafeSitesFilterBehavior\x18\x02 \x01(\x03\"\xa8\x01\n SpellcheckLanguageBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bSpellcheckLanguageBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1b\x45nterpriseWebStoreNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x45nterpriseWebStoreName\x18\x02 \x01(\t\"\x85\x01\n AllowSyncXHRInPageDismissalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x41llowSyncXHRInPageDismissal\x18\x02 \x01(\x08\"{\n\x1b\x41lwaysAuthorizePluginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16\x41lwaysAuthorizePlugins\x18\x02 \x01(\x08\"\xca\x01\n1OverrideSecurityRestrictionsOnInsecureOriginProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12W\n,OverrideSecurityRestrictionsOnInsecureOrigin\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17GhostWindowEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12GhostWindowEnabled\x18\x02 \x01(\x08\"q\n\x16TosDialogBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11TosDialogBehavior\x18\x02 \x01(\x03\"i\n\x12ImportHistoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rImportHistory\x18\x02 \x01(\x08\"\x87\x01\n!RoamingProfileSupportEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRoamingProfileSupportEnabled\x18\x02 \x01(\x08\"\x9f\x01\n-GaiaLockScreenOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(GaiaLockScreenOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"\x87\x01\n!CloudProfileReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudProfileReportingEnabled\x18\x02 \x01(\x08\"s\n\x17\x46ullRestoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x46ullRestoreEnabled\x18\x02 \x01(\x08\"q\n\x16\x44ownloadDirectoryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x44ownloadDirectory\x18\x02 \x01(\t\"o\n\x15\x44nsOverHttpsModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44nsOverHttpsMode\x18\x02 \x01(\t\"\xa1\x01\n.DefaultSearchProviderSuggestURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DefaultSearchProviderSuggestURLPostParams\x18\x02 \x01(\t\"\x87\x01\n!DefaultSearchProviderIconURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderIconURL\x18\x02 \x01(\t\"\x8b\x01\n#DefaultSearchProviderNewTabURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65\x66\x61ultSearchProviderNewTabURL\x18\x02 \x01(\t\"\x81\x01\n\x1e\x44\x65\x66\x61ultSearchProviderNameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultSearchProviderName\x18\x02 \x01(\t\"\x87\x01\n!DefaultSearchProviderKeywordProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderKeyword\x18\x02 \x01(\t\"\x8d\x01\n$DefaultSearchProviderInstantURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultSearchProviderInstantURL\x18\x02 \x01(\t\"\x89\x01\n\"DefaultSearchProviderImageURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultSearchProviderImageURL\x18\x02 \x01(\t\"\x9d\x01\n,DefaultSearchProviderImageURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12/\n\'DefaultSearchProviderImageURLPostParams\x18\x02 \x01(\t\"\x8d\x01\n$DefaultSearchProviderSuggestURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultSearchProviderSuggestURL\x18\x02 \x01(\t\"\xab\x01\n3DefaultSearchProviderSearchTermsReplacementKeyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x36\n.DefaultSearchProviderSearchTermsReplacementKey\x18\x02 \x01(\t\"\x87\x01\n!DefaultSearchProviderEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x44\x65\x66\x61ultSearchProviderEnabled\x18\x02 \x01(\x08\"\xa1\x01\n.DefaultSearchProviderInstantURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x31\n)DefaultSearchProviderInstantURLPostParams\x18\x02 \x01(\t\"\xae\x01\n#DefaultSearchProviderEncodingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12I\n\x1e\x44\x65\x66\x61ultSearchProviderEncodings\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#DefaultSearchProviderSearchURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x44\x65\x66\x61ultSearchProviderSearchURL\x18\x02 \x01(\t\"\xb6\x01\n\'DefaultSearchProviderAlternateURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12M\n\"DefaultSearchProviderAlternateURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9f\x01\n-DefaultSearchProviderSearchURLPostParamsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(DefaultSearchProviderSearchURLPostParams\x18\x02 \x01(\t\"{\n\x1bRecoveryFactorBehaviorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RecoveryFactorBehavior\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x41ttestationEnabledForUserProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41ttestationEnabledForUser\x18\x02 \x01(\x08\"\xac\x01\n\"AttestationExtensionAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x41ttestationExtensionAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa0\x01\n\x1c\x43hromeFrameContentTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43hromeFrameContentTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1dNewWindowsInKioskAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NewWindowsInKioskAllowed\x18\x02 \x01(\x08\"\x8f\x01\n%KioskTroubleshootingToolsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n KioskTroubleshootingToolsEnabled\x18\x02 \x01(\x08\"m\n\x14ProxyServerModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fProxyServerMode\x18\x02 \x01(\x03\"a\n\x0eProxyModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x11\n\tProxyMode\x18\x02 \x01(\t\"m\n\x14ProxyBypassListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fProxyBypassList\x18\x02 \x01(\t\"e\n\x10ProxyServerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bProxyServer\x18\x02 \x01(\t\"e\n\x10ProxyPacUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bProxyPacUrl\x18\x02 \x01(\t\"\xa0\x01\n\x1c\x45xtensionInstallSourcesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x45xtensionInstallSources\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1a\x45xtensionAllowedTypesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x45xtensionAllowedTypes\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallForcelistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallForcelist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa4\x01\n\x1e\x45xtensionInstallAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x45xtensionInstallAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$ExtensionManifestV2AvailabilityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x45xtensionManifestV2Availability\x18\x02 \x01(\x03\"\x89\x01\n\"ExtensionAllowInsecureUpdatesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x45xtensionAllowInsecureUpdates\x18\x02 \x01(\x08\"q\n\x16\x45xtensionSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45xtensionSettings\x18\x02 \x01(\t\"}\n\x1c\x42lockExternalExtensionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x42lockExternalExtensions\x18\x02 \x01(\x08\"o\n\x15KerberosAccountsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10KerberosAccounts\x18\x02 \x01(\t\"\x83\x01\n\x1fKerberosDomainAutocompleteProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aKerberosDomainAutocomplete\x18\x02 \x01(\t\"\x8d\x01\n$KerberosRememberPasswordEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fKerberosRememberPasswordEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fKerberosAddAccountsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aKerberosAddAccountsAllowed\x18\x02 \x01(\x08\"\x8f\x01\n%KerberosUseCustomPrefilledConfigProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n KerberosUseCustomPrefilledConfig\x18\x02 \x01(\x08\"m\n\x14KerberosEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0fKerberosEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"KerberosCustomPrefilledConfigProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dKerberosCustomPrefilledConfig\x18\x02 \x01(\t\"\x87\x01\n!NetBiosShareDiscoveryEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cNetBiosShareDiscoveryEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#NTLMShareAuthenticationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eNTLMShareAuthenticationEnabled\x18\x02 \x01(\x08\"\x7f\n\x1dNetworkFileSharesAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18NetworkFileSharesAllowed\x18\x02 \x01(\x08\"\x97\x01\n)NetworkFileSharesPreconfiguredSharesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$NetworkFileSharesPreconfiguredShares\x18\x02 \x01(\t\"\x8f\x01\n%RequiredClientCertificateForUserProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RequiredClientCertificateForUser\x18\x02 \x01(\t\"\x9f\x01\n-SamlPasswordExpirationAdvanceWarningDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n(SamlPasswordExpirationAdvanceWarningDays\x18\x02 \x01(\x03\"\x93\x01\n\'SamlInSessionPasswordChangeEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"SamlInSessionPasswordChangeEnabled\x18\x02 \x01(\x08\"\x91\x01\n&LockScreenReauthenticationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!LockScreenReauthenticationEnabled\x18\x02 \x01(\x08\"\x83\x01\n\x1fSAMLOfflineSigninTimeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aSAMLOfflineSigninTimeLimit\x18\x02 \x01(\x03\"\x95\x01\n(PasswordProtectionChangePasswordURLProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#PasswordProtectionChangePasswordURL\x18\x02 \x01(\t\"u\n\x18SafeBrowsingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13SafeBrowsingEnabled\x18\x02 \x01(\x08\"\x97\x01\n)SafeBrowsingExtendedReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$SafeBrowsingExtendedReportingEnabled\x18\x02 \x01(\x08\"\xaa\x01\n!SafeBrowsingAllowlistDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cSafeBrowsingAllowlistDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa8\x01\n PasswordProtectionLoginURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bPasswordProtectionLoginURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8f\x01\n%PasswordProtectionWarningTriggerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PasswordProtectionWarningTrigger\x18\x02 \x01(\x03\"\x85\x01\n SafeBrowsingProtectionLevelProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bSafeBrowsingProtectionLevel\x18\x02 \x01(\x03\"u\n\x18ReportMachineIDDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13ReportMachineIDData\x18\x02 \x01(\x08\"y\n\x1a\x43loudReportingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x43loudReportingEnabled\x18\x02 \x01(\x08\"\x87\x01\n!CloudExtensionRequestEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x43loudExtensionRequestEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#ReportExtensionsAndPluginsDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eReportExtensionsAndPluginsData\x18\x02 \x01(\x08\"\x89\x01\n\"CloudReportingUploadFrequencyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43loudReportingUploadFrequency\x18\x02 \x01(\x03\"o\n\x15ReportUserIDDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ReportUserIDData\x18\x02 \x01(\x08\"o\n\x15ReportPolicyDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ReportPolicyData\x18\x02 \x01(\x08\"{\n\x1bReportSafeBrowsingDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ReportSafeBrowsingData\x18\x02 \x01(\x08\"q\n\x16ReportVersionDataProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ReportVersionData\x18\x02 \x01(\x08\"w\n\x19HomepageIsNewTabPageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14HomepageIsNewTabPage\x18\x02 \x01(\x08\"o\n\x15RestoreOnStartupProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10RestoreOnStartup\x18\x02 \x01(\x03\"\x9a\x01\n\x19RestoreOnStartupURLsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14RestoreOnStartupURLs\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"s\n\x17NewTabPageLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12NewTabPageLocation\x18\x02 \x01(\t\"k\n\x13ShowHomeButtonProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eShowHomeButton\x18\x02 \x01(\x08\"o\n\x15HomepageLocationProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10HomepageLocation\x18\x02 \x01(\t\"\x8b\x01\n#ArcBackupRestoreServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1e\x41rcBackupRestoreServiceEnabled\x18\x02 \x01(\x03\"\x87\x01\n!ArcAppToWebAppSharingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1c\x41rcAppToWebAppSharingEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ArcAppInstallEventLoggingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ArcAppInstallEventLoggingEnabled\x18\x02 \x01(\x08\"}\n\x1c\x41rcCertificatesSyncModeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41rcCertificatesSyncMode\x18\x02 \x01(\x03\"}\n\x1c\x41rcBackupRestoreEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x41rcBackupRestoreEnabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x41rcLocationServiceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x41rcLocationServiceEnabled\x18\x02 \x01(\x08\"\x91\x01\n&AppRecommendationZeroStateEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!AppRecommendationZeroStateEnabled\x18\x02 \x01(\x08\"c\n\x0f\x41rcEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nArcEnabled\x18\x02 \x01(\x08\"\x8f\x01\n%ArcGoogleLocationServicesEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n ArcGoogleLocationServicesEnabled\x18\x02 \x01(\x03\"a\n\x0e\x41rcPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x11\n\tArcPolicy\x18\x02 \x01(\t\"i\n\x12\x44riveDisabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rDriveDisabled\x18\x02 \x01(\x08\"\x81\x01\n\x1e\x44riveDisabledOverCellularProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44riveDisabledOverCellular\x18\x02 \x01(\x08\"\xba\x01\n)SameOriginTabCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12O\n$SameOriginTabCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"ScreenCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dScreenCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19ScreenCaptureAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14ScreenCaptureAllowed\x18\x02 \x01(\x08\"\xac\x01\n\"WindowCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1fTabCaptureAllowedByOriginsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aTabCaptureAllowedByOrigins\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"{\n\x1bPinUnlockMinimumLengthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PinUnlockMinimumLength\x18\x02 \x01(\x03\"\x7f\n\x1dPinUnlockWeakPinsAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18PinUnlockWeakPinsAllowed\x18\x02 \x01(\x08\"s\n\x17QuickUnlockTimeoutProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12QuickUnlockTimeout\x18\x02 \x01(\x03\"\xa2\x01\n\x1dQuickUnlockModeAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18QuickUnlockModeAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fPinUnlockAutosubmitEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPinUnlockAutosubmitEnabled\x18\x02 \x01(\x08\"{\n\x1bPinUnlockMaximumLengthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16PinUnlockMaximumLength\x18\x02 \x01(\x03\"\x97\x01\n)ProjectorDogfoodForFamilyLinkEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$ProjectorDogfoodForFamilyLinkEnabled\x18\x02 \x01(\x08\"o\n\x15ProjectorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ProjectorEnabled\x18\x02 \x01(\x08\"q\n\x16\x45nableMediaRouterProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11\x45nableMediaRouter\x18\x02 \x01(\x08\"y\n\x1aShowCastIconInToolbarProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ShowCastIconInToolbar\x18\x02 \x01(\x08\"\x99\x01\n*ShowCastSessionsStartedByOtherDevicesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%ShowCastSessionsStartedByOtherDevices\x18\x02 \x01(\x08\"\x83\x01\n\x1fMediaRouterCastAllowAllIPsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aMediaRouterCastAllowAllIPs\x18\x02 \x01(\x08\"\x83\x01\n\x1f\x43\x61lendarIntegrationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x43\x61lendarIntegrationEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"PrivacySandboxAdTopicsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dPrivacySandboxAdTopicsEnabled\x18\x02 \x01(\x08\"\x95\x01\n(PrivacySandboxSiteEnabledAdsEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#PrivacySandboxSiteEnabledAdsEnabled\x18\x02 \x01(\x08\"\x85\x01\n PrivacySandboxPromptEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPrivacySandboxPromptEnabled\x18\x02 \x01(\x08\"\x93\x01\n\'PrivacySandboxAdMeasurementEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"PrivacySandboxAdMeasurementEnabled\x18\x02 \x01(\x08\"\x97\x01\n)DnsOverHttpsTemplatesWithIdentifiersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12,\n$DnsOverHttpsTemplatesWithIdentifiers\x18\x02 \x01(\t\"\xbb\x01\n;AccessControlAllowMethodsInCORSPreflightSpecConformantProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12>\n6AccessControlAllowMethodsInCORSPreflightSpecConformant\x18\x02 \x01(\x08\"o\n\x15\x44nsOverHttpsSaltProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10\x44nsOverHttpsSalt\x18\x02 \x01(\t\"{\n\x1bReportArcStatusEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ReportArcStatusEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"NativeMessagingUserLevelHostsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dNativeMessagingUserLevelHosts\x18\x02 \x01(\x08\"\xa2\x01\n\x1dNativeMessagingBlocklistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingBlocklist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dNativeMessagingAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18NativeMessagingAllowlist\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8b\x01\n#GaiaOfflineSigninTimeLimitDaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eGaiaOfflineSigninTimeLimitDays\x18\x02 \x01(\x03\"u\n\x18UserPluginVmAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserPluginVmAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"PluginVmDataCollectionAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dPluginVmDataCollectionAllowed\x18\x02 \x01(\x08\"k\n\x13PluginVmUserIdProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0ePluginVmUserId\x18\x02 \x01(\t\"i\n\x12PluginVmImageProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x15\n\rPluginVmImage\x18\x02 \x01(\t\"\x89\x01\n\"PluginVmRequiredFreeDiskSpaceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dPluginVmRequiredFreeDiskSpace\x18\x02 \x01(\x03\"w\n\x19PrivacyScreenEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PrivacyScreenEnabled\x18\x02 \x01(\x08\"k\n\x13UsageTimeLimitProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eUsageTimeLimit\x18\x02 \x01(\t\"\x81\x01\n\x1ePerAppTimeLimitsAllowlistProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19PerAppTimeLimitsAllowlist\x18\x02 \x01(\t\"\x7f\n\x1d\x45\x64uCoexistenceToSVersionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x45\x64uCoexistenceToSVersion\x18\x02 \x01(\t\"o\n\x15PerAppTimeLimitsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10PerAppTimeLimits\x18\x02 \x01(\t\"{\n\x1bParentAccessCodeConfigProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ParentAccessCodeConfig\x18\x02 \x01(\t\"\x85\x01\n ChromeFrameRendererSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x43hromeFrameRendererSettings\x18\x02 \x01(\x03\"\x83\x01\n\x1f\x41\x64\x64itionalLaunchParametersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1a\x41\x64\x64itionalLaunchParameters\x18\x02 \x01(\t\"\xa0\x01\n\x1cRenderInChromeFrameListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17RenderInChromeFrameList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x92\x01\n\x15RenderInHostListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10RenderInHostList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"q\n\x16SkipMetadataCheckProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11SkipMetadataCheck\x18\x02 \x01(\x08\"\x91\x01\n&QuickAnswersUnitConversionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!QuickAnswersUnitConversionEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"QuickAnswersDefinitionEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dQuickAnswersDefinitionEnabled\x18\x02 \x01(\x08\"\x8b\x01\n#QuickAnswersTranslationEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eQuickAnswersTranslationEnabled\x18\x02 \x01(\x08\"u\n\x18QuickAnswersEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13QuickAnswersEnabled\x18\x02 \x01(\x08\"\x89\x01\n\"CrostiniPortForwardingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43rostiniPortForwardingAllowed\x18\x02 \x01(\x08\"}\n\x1c\x43rostiniAnsiblePlaybookProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x43rostiniAnsiblePlaybook\x18\x02 \x01(\t\"\x81\x01\n\x1e\x43rostiniRootAccessAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x43rostiniRootAccessAllowed\x18\x02 \x01(\x08\"\x8f\x01\n%CrostiniArcAdbSideloadingAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n CrostiniArcAdbSideloadingAllowed\x18\x02 \x01(\x03\"\x7f\n\x1dSystemTerminalSshAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18SystemTerminalSshAllowed\x18\x02 \x01(\x08\"\x89\x01\n\"CrostiniExportImportUIAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x43rostiniExportImportUIAllowed\x18\x02 \x01(\x08\"m\n\x14\x43rostiniAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x17\n\x0f\x43rostiniAllowed\x18\x02 \x01(\x08\"o\n\x15IdleDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10IdleDelayBattery\x18\x02 \x01(\x03\"s\n\x17IdleWarningDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12IdleWarningDelayAC\x18\x02 \x01(\x03\"k\n\x13LidCloseActionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0eLidCloseAction\x18\x02 \x01(\x03\"\x83\x01\n\x1fPresentationIdleDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aPresentationIdleDelayScale\x18\x02 \x01(\x03\"y\n\x1aScreenOffDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ScreenOffDelayBattery\x18\x02 \x01(\x03\"c\n\x0fIdleActionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x12\n\nIdleAction\x18\x02 \x01(\x03\"w\n\x19\x41llowScreenWakeLocksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x41llowScreenWakeLocks\x18\x02 \x01(\x08\"}\n\x1cScreenBrightnessPercentProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17ScreenBrightnessPercent\x18\x02 \x01(\t\"o\n\x15ScreenLockDelaysProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenLockDelays\x18\x02 \x01(\t\"\x8d\x01\n$PresentationScreenDimDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fPresentationScreenDimDelayScale\x18\x02 \x01(\x03\"}\n\x1cIdleWarningDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17IdleWarningDelayBattery\x18\x02 \x01(\x03\"q\n\x16ScreenLockDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11ScreenLockDelayAC\x18\x02 \x01(\x03\"y\n\x1aScreenDimDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15ScreenDimDelayBattery\x18\x02 \x01(\x03\"w\n\x19PowerSmartDimEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14PowerSmartDimEnabled\x18\x02 \x01(\x08\"q\n\x16IdleActionBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x19\n\x11IdleActionBattery\x18\x02 \x01(\x03\"e\n\x10IdleDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bIdleDelayAC\x18\x02 \x01(\x03\"o\n\x15ScreenDimDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenDimDelayAC\x18\x02 \x01(\x03\"\x8f\x01\n%PowerManagementUsesAudioActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PowerManagementUsesAudioActivity\x18\x02 \x01(\x08\"\x83\x01\n\x1fWaitForInitialUserActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aWaitForInitialUserActivity\x18\x02 \x01(\x08\"\x85\x01\n PowerManagementIdleSettingsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1bPowerManagementIdleSettings\x18\x02 \x01(\t\"\x8d\x01\n$UserActivityScreenDimDelayScaleProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fUserActivityScreenDimDelayScale\x18\x02 \x01(\x03\"g\n\x11IdleActionACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x14\n\x0cIdleActionAC\x18\x02 \x01(\x03\"k\n\x13\x41llowWakeLocksProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x16\n\x0e\x41llowWakeLocks\x18\x02 \x01(\x08\"\x93\x01\n\'DevicePowerAdaptiveChargingEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DevicePowerAdaptiveChargingEnabled\x18\x02 \x01(\x08\"{\n\x1bScreenLockDelayBatteryProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16ScreenLockDelayBattery\x18\x02 \x01(\x03\"o\n\x15ScreenOffDelayACProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x18\n\x10ScreenOffDelayAC\x18\x02 \x01(\x03\"\x8f\x01\n%PowerManagementUsesVideoActivityProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n PowerManagementUsesVideoActivity\x18\x02 \x01(\x08\"\x91\x01\n&RemoteAccessHostFirewallTraversalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!RemoteAccessHostFirewallTraversal\x18\x02 \x01(\x08\"\x7f\n\x1dRemoteAccessHostTokenUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18RemoteAccessHostTokenUrl\x18\x02 \x01(\t\"\x93\x01\n\'RemoteAccessHostTokenValidationUrlProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostTokenValidationUrl\x18\x02 \x01(\t\"\x89\x01\n\"RemoteAccessHostMatchUsernameProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1dRemoteAccessHostMatchUsername\x18\x02 \x01(\x08\"\xa9\x01\n2RemoteAccessHostMaximumSessionDurationMinutesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-RemoteAccessHostMaximumSessionDurationMinutes\x18\x02 \x01(\x03\"\xaf\x01\n5RemoteAccessHostAllowUiAccessForRemoteAssistanceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0RemoteAccessHostAllowUiAccessForRemoteAssistance\x18\x02 \x01(\x08\"\xa9\x01\n2RemoteAccessHostAllowRemoteSupportConnectionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x35\n-RemoteAccessHostAllowRemoteSupportConnections\x18\x02 \x01(\x08\"\xa7\x01\n1RemoteAccessHostAllowRemoteAccessConnectionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x34\n,RemoteAccessHostAllowRemoteAccessConnections\x18\x02 \x01(\x08\"\x9b\x01\n+RemoteAccessHostAllowRelayedConnectionProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&RemoteAccessHostAllowRelayedConnection\x18\x02 \x01(\x08\"\x8d\x01\n$RemoteAccessHostAllowGnubbyAuthProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1fRemoteAccessHostAllowGnubbyAuth\x18\x02 \x01(\x08\"\x8f\x01\n%RemoteAccessHostRequireTwoFactorProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RemoteAccessHostRequireTwoFactor\x18\x02 \x01(\x08\"\x87\x01\n!RemoteAccessHostClientDomainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRemoteAccessHostClientDomain\x18\x02 \x01(\t\"\x87\x01\n!RemoteAccessHostUdpPortRangeProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cRemoteAccessHostUdpPortRange\x18\x02 \x01(\t\"\x91\x01\n&RemoteAccessHostAllowFileTransferProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!RemoteAccessHostAllowFileTransfer\x18\x02 \x01(\x08\"\xaf\x01\n5RemoteAccessHostTokenValidationCertificateIssuerProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x38\n0RemoteAccessHostTokenValidationCertificateIssuer\x18\x02 \x01(\t\"\xa6\x01\n\x1fRemoteAccessHostDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aRemoteAccessHostDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x93\x01\n\'RemoteAccessHostAllowClientPairingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostAllowClientPairing\x18\x02 \x01(\x08\"\x95\x01\n(RemoteAccessHostEnableUserInterfaceProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#RemoteAccessHostEnableUserInterface\x18\x02 \x01(\x08\"\x8b\x01\n#RemoteAccessHostRequireCurtainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12&\n\x1eRemoteAccessHostRequireCurtain\x18\x02 \x01(\x08\"\x95\x01\n(RemoteAccessClientFirewallTraversalProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#RemoteAccessClientFirewallTraversal\x18\x02 \x01(\x08\"\x99\x01\n*RemoteAccessHostDebugOverridePoliciesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12-\n%RemoteAccessHostDebugOverridePolicies\x18\x02 \x01(\t\"\x8f\x01\n%RemoteAccessHostTalkGadgetPrefixProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12(\n RemoteAccessHostTalkGadgetPrefix\x18\x02 \x01(\t\"\xb2\x01\n%RemoteAccessHostClientDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12K\n RemoteAccessHostClientDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x93\x01\n\'RemoteAccessHostClipboardSizeBytesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"RemoteAccessHostClipboardSizeBytes\x18\x02 \x01(\x03\"{\n\x1bRemoteAccessHostDomainProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1e\n\x16RemoteAccessHostDomain\x18\x02 \x01(\t\"\x7f\n\x1d\x44\x65\x66\x61ultJavaScriptSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultJavaScriptSetting\x18\x02 \x01(\x03\"\xa4\x01\n\x1e\x46ileSystemWriteAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x46ileSystemWriteAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19ImagesBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14ImagesBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultWebUsbGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultWebUsbGuardSetting\x18\x02 \x01(\x03\"\x87\x01\n!SerialAllowUsbDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12$\n\x1cSerialAllowUsbDevicesForUrls\x18\x02 \x01(\t\"\x95\x01\n(LegacySameSiteCookieBehaviorEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12+\n#LegacySameSiteCookieBehaviorEnabled\x18\x02 \x01(\x03\"\x9a\x01\n\x19KeygenBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14KeygenBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultCookiesSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultCookiesSetting\x18\x02 \x01(\x03\"\x89\x01\n\"DefaultInsecureContentSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultInsecureContentSetting\x18\x02 \x01(\x03\"\x92\x01\n\x15WebHidAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10WebHidAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"}\n\x1c\x44\x65\x66\x61ultClipboardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1f\n\x17\x44\x65\x66\x61ultClipboardSetting\x18\x02 \x01(\x03\"\x93\x01\n\'DefaultFileSystemWriteGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12*\n\"DefaultFileSystemWriteGuardSetting\x18\x02 \x01(\x03\"\xa2\x01\n\x1dJavaScriptAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18JavaScriptAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x91\x01\n&DefaultFileSystemReadGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12)\n!DefaultFileSystemReadGuardSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19SerialBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14SerialBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!FileSystemReadBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x46ileSystemReadBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa8\x01\n NotificationsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNotificationsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!JavaScriptJitBlockedForSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cJavaScriptJitBlockedForSites\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"InsecureContentAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dInsecureContentAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x92\x01\n\x15SerialAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10SerialAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eWebHidAllowDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WebHidAllowDevicesForUrls\x18\x02 \x01(\t\"\x92\x01\n\x15WebUsbAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12;\n\x10WebUsbAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dLocalFontsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18LocalFontsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1f\x46ileHandlingBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x46ileHandlingBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa8\x01\n NotificationsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x46\n\x1bNotificationsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultSensorsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultSensorsSetting\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x44\x65\x66\x61ultMediaStreamSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultMediaStreamSetting\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x44\x65\x66\x61ultWebHidGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultWebHidGuardSetting\x18\x02 \x01(\x03\"\xb8\x01\n(PdfLocalFileAccessAllowedForDomainsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12N\n#PdfLocalFileAccessAllowedForDomains\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa0\x01\n\x1c\x43lipboardBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43lipboardBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1eWebUsbAllowDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19WebUsbAllowDevicesForUrls\x18\x02 \x01(\t\"\xad\x01\n4FileSystemSyncAccessHandleAsyncInterfaceEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x37\n/FileSystemSyncAccessHandleAsyncInterfaceEnabled\x18\x02 \x01(\x08\"\x9a\x01\n\x19KeygenAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14KeygenAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19PopupsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14PopupsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19WebHidBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14WebHidBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x44\x65\x66\x61ultImagesSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultImagesSetting\x18\x02 \x01(\x03\"\x8d\x01\n$DefaultWebBluetoothGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultWebBluetoothGuardSetting\x18\x02 \x01(\x03\"\xac\x01\n\"WindowPlacementBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowPlacementBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"y\n\x1a\x44\x65\x66\x61ultPluginsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1d\n\x15\x44\x65\x66\x61ultPluginsSetting\x18\x02 \x01(\x03\"\xa2\x01\n\x1d\x46ileSystemReadAskForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18\x46ileSystemReadAskForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"InsecureContentBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dInsecureContentBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x8d\x01\n$DefaultFileHandlingGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\'\n\x1f\x44\x65\x66\x61ultFileHandlingGuardSetting\x18\x02 \x01(\x03\"\x9c\x01\n\x1aSensorsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SensorsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xd2\x01\n5LegacySameSiteCookieBehaviorEnabledForDomainListProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12[\n0LegacySameSiteCookieBehaviorEnabledForDomainList\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xaa\x01\n!JavaScriptJitAllowedForSitesProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cJavaScriptJitAllowedForSites\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa2\x01\n\x1dLocalFontsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18LocalFontsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x44\x65\x66\x61ultPopupsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultPopupsSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19WebUsbBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14WebUsbBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1aPluginsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PluginsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1aPluginsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15PluginsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1aSensorsBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15SensorsBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa6\x01\n\x1fSerialAllowAllPortsForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1aSerialAllowAllPortsForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"w\n\x19\x44\x65\x66\x61ultKeygenSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1c\n\x14\x44\x65\x66\x61ultKeygenSetting\x18\x02 \x01(\x03\"\xa6\x01\n\x1f\x46ileHandlingAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x45\n\x1a\x46ileHandlingAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9b\x01\n+WebHidAllowDevicesWithHidUsagesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12.\n&WebHidAllowDevicesWithHidUsagesForUrls\x18\x02 \x01(\t\"\xaa\x01\n!AutoSelectCertificateForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1c\x41utoSelectCertificateForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x7f\n\x1d\x44\x65\x66\x61ultLocalFontsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12 \n\x18\x44\x65\x66\x61ultLocalFontsSetting\x18\x02 \x01(\x03\"\xac\x01\n\"WindowPlacementAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1dWindowPlacementAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9c\x01\n\x1a\x43ookiesBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x43ookiesBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x89\x01\n\"DefaultWindowPlacementSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12%\n\x1d\x44\x65\x66\x61ultWindowPlacementSetting\x18\x02 \x01(\x03\"\x9c\x01\n\x1a\x43ookiesAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12@\n\x15\x43ookiesAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n DefaultJavaScriptJitSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x65\x66\x61ultJavaScriptJitSetting\x18\x02 \x01(\x03\"\x9a\x01\n\x19PopupsAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14PopupsAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x83\x01\n\x1fRegisteredProtocolHandlersProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\"\n\x1aRegisteredProtocolHandlers\x18\x02 \x01(\t\"\xa2\x01\n\x1dJavaScriptBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x43\n\x18JavaScriptBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xac\x01\n\"FileSystemWriteBlockedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12H\n\x1d\x46ileSystemWriteBlockedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x85\x01\n DefaultNotificationsSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12#\n\x1b\x44\x65\x66\x61ultNotificationsSetting\x18\x02 \x01(\x03\"\x81\x01\n\x1e\x44\x65\x66\x61ultSerialGuardSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultSerialGuardSetting\x18\x02 \x01(\x03\"\xa4\x01\n\x1e\x43ookiesSessionOnlyForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x44\n\x19\x43ookiesSessionOnlyForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xa0\x01\n\x1c\x43lipboardAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x42\n\x17\x43lipboardAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x81\x01\n\x1e\x44\x65\x66\x61ultGeolocationSettingProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12!\n\x19\x44\x65\x66\x61ultGeolocationSetting\x18\x02 \x01(\x03\"\xaa\x01\n!WebHidAllowAllDevicesForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12G\n\x1cWebHidAllowAllDevicesForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\x9a\x01\n\x19ImagesAllowedForUrlsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12?\n\x14ImagesAllowedForUrls\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"u\n\x18UserBorealisAllowedProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1b\n\x13UserBorealisAllowed\x18\x02 \x01(\x08\"s\n\x17\x43loudAPAuthEnabledProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x1a\n\x12\x43loudAPAuthEnabled\x18\x02 \x01(\x03\"e\n\x10IdleTimeoutProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x13\n\x0bIdleTimeout\x18\x02 \x01(\x03\"\x96\x01\n\x17IdleTimeoutActionsProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12=\n\x12IdleTimeoutActions\x18\x02 \x01(\x0b\x32!.enterprise_management.StringList\"\xf3\x0b\n\x17\x43hromeSettingsSubProto1\x12P\n\x15\x41ppStoreRatingEnabled\x18\x0c \x01(\x0b\x32\x31.enterprise_management.AppStoreRatingEnabledProto\x12n\n$NewBaseUrlInheritanceBehaviorAllowed\x18\x01 \x01(\x0b\x32@.enterprise_management.NewBaseUrlInheritanceBehaviorAllowedProto\x12h\n!PPAPISharedImagesSwapChainAllowed\x18\x07 \x01(\x0b\x32=.enterprise_management.PPAPISharedImagesSwapChainAllowedProto\x12\x62\n\x1eUsbDetectorNotificationEnabled\x18\x04 \x01(\x0b\x32:.enterprise_management.UsbDetectorNotificationEnabledProto\x12l\n#UseMojoVideoDecoderForPepperAllowed\x18\x06 \x01(\x0b\x32?.enterprise_management.UseMojoVideoDecoderForPepperAllowedProto\x12\x44\n\x0fLacrosSelection\x18\x05 \x01(\x0b\x32+.enterprise_management.LacrosSelectionProto\x12l\n#ForceEnablePepperVideoDecoderDevAPI\x18\x11 \x01(\x0b\x32?.enterprise_management.ForceEnablePepperVideoDecoderDevAPIProto\x12\x66\n KioskTroubleshootingToolsEnabled\x18\x10 \x01(\x0b\x32<.enterprise_management.KioskTroubleshootingToolsEnabledProto\x12\x66\n KerberosUseCustomPrefilledConfig\x18\r \x01(\x0b\x32<.enterprise_management.KerberosUseCustomPrefilledConfigProto\x12p\n%ShowCastSessionsStartedByOtherDevices\x18\x02 \x01(\x0b\x32\x41.enterprise_management.ShowCastSessionsStartedByOtherDevicesProto\x12`\n\x1dPrivacySandboxAdTopicsEnabled\x18\t \x01(\x0b\x32\x39.enterprise_management.PrivacySandboxAdTopicsEnabledProto\x12l\n#PrivacySandboxSiteEnabledAdsEnabled\x18\n \x01(\x0b\x32?.enterprise_management.PrivacySandboxSiteEnabledAdsEnabledProto\x12\\\n\x1bPrivacySandboxPromptEnabled\x18\x08 \x01(\x0b\x32\x37.enterprise_management.PrivacySandboxPromptEnabledProto\x12j\n\"PrivacySandboxAdMeasurementEnabled\x18\x0b \x01(\x0b\x32>.enterprise_management.PrivacySandboxAdMeasurementEnabledProto\x12J\n\x12\x43loudAPAuthEnabled\x18\x03 \x01(\x0b\x32..enterprise_management.CloudAPAuthEnabledProto\"\xb8\xbb\x04\n\x13\x43hromeSettingsProto\x12H\n\x11GSSAPILibraryName\x18! \x01(\x0b\x32-.enterprise_management.GSSAPILibraryNameProto\x12\x41\n\rNtlmV2Enabled\x18\x8b\x03 \x01(\x0b\x32).enterprise_management.NtlmV2EnabledProto\x12\x64\n\x1f\x44isableAuthNegotiateCnameLookup\x18\x1d \x01(\x0b\x32;.enterprise_management.DisableAuthNegotiateCnameLookupProto\x12M\n\x13\x41uthServerAllowlist\x18\xed\x05 \x01(\x0b\x32/.enterprise_management.AuthServerAllowlistProto\x12<\n\x0b\x41uthSchemes\x18\x1c \x01(\x0b\x32\'.enterprise_management.AuthSchemesProto\x12T\n\x17\x45nableAuthNegotiatePort\x18\x1e \x01(\x0b\x32\x33.enterprise_management.EnableAuthNegotiatePortProto\x12\x65\n\x1f\x41uthAndroidNegotiateAccountType\x18\xb3\x02 \x01(\x0b\x32;.enterprise_management.AuthAndroidNegotiateAccountTypeProto\x12g\n AuthNegotiateDelegateByKdcPolicy\x18\x92\x04 \x01(\x0b\x32<.enterprise_management.AuthNegotiateDelegateByKdcPolicyProto\x12k\n\"IntegratedWebAuthenticationAllowed\x18\xaa\x06 \x01(\x0b\x32>.enterprise_management.IntegratedWebAuthenticationAllowedProto\x12W\n\x18\x42\x61sicAuthOverHttpEnabled\x18\xa8\x06 \x01(\x0b\x32\x34.enterprise_management.BasicAuthOverHttpEnabledProto\x12m\n#AllHttpAuthSchemesAllowedForOrigins\x18\xb8\x07 \x01(\x0b\x32?.enterprise_management.AllHttpAuthSchemesAllowedForOriginsProto\x12Z\n\x1a\x41llowCrossOriginAuthPrompt\x18[ \x01(\x0b\x32\x36.enterprise_management.AllowCrossOriginAuthPromptProto\x12\x63\n\x1e\x41uthNegotiateDelegateAllowlist\x18\xec\x05 \x01(\x0b\x32:.enterprise_management.AuthNegotiateDelegateAllowlistProto\x12Q\n\x15\x46irstPartySetsEnabled\x18\xb6\x07 \x01(\x0b\x32\x31.enterprise_management.FirstPartySetsEnabledProto\x12U\n\x17\x46irstPartySetsOverrides\x18\xcb\x07 \x01(\x0b\x32\x33.enterprise_management.FirstPartySetsOverridesProto\x12\x63\n\x1eVoiceInteractionContextEnabled\x18\x91\x04 \x01(\x0b\x32:.enterprise_management.VoiceInteractionContextEnabledProto\x12U\n\x17\x41ssistantOnboardingMode\x18\xdb\x05 \x01(\x0b\x32\x33.enterprise_management.AssistantOnboardingModeProto\x12m\n#VoiceInteractionQuickAnswersEnabled\x18\xb8\x05 \x01(\x0b\x32?.enterprise_management.VoiceInteractionQuickAnswersEnabledProto\x12\x63\n\x1eVoiceInteractionHotwordEnabled\x18\x93\x04 \x01(\x0b\x32:.enterprise_management.VoiceInteractionHotwordEnabledProto\x12M\n\x13\x41ssistantWebEnabled\x18\xf5\x07 \x01(\x0b\x32/.enterprise_management.AssistantWebEnabledProto\x12o\n$AssistantVoiceMatchEnabledDuringOobe\x18\xf7\x06 \x01(\x0b\x32@.enterprise_management.AssistantVoiceMatchEnabledDuringOobeProto\x12O\n\x14SelectToSpeakEnabled\x18\xbf\x04 \x01(\x0b\x32\x30.enterprise_management.SelectToSpeakEnabledProto\x12g\n FloatingAccessibilityMenuEnabled\x18\xb5\x05 \x01(\x0b\x32<.enterprise_management.FloatingAccessibilityMenuEnabledProto\x12G\n\x10MonoAudioEnabled\x18\xd6\x04 \x01(\x0b\x32,.enterprise_management.MonoAudioEnabledProto\x12M\n\x13HighContrastEnabled\x18\xd7\x01 \x01(\x0b\x32/.enterprise_management.HighContrastEnabledProto\x12U\n\x17VirtualKeyboardFeatures\x18\xcf\x05 \x01(\x0b\x32\x33.enterprise_management.VirtualKeyboardFeaturesProto\x12G\n\x10\x44ictationEnabled\x18\xd2\x04 \x01(\x0b\x32,.enterprise_management.DictationEnabledProto\x12K\n\x12LargeCursorEnabled\x18\xd5\x01 \x01(\x0b\x32..enterprise_management.LargeCursorEnabledProto\x12\x61\n\x1dKeyboardDefaultToFunctionKeys\x18\x86\x02 \x01(\x0b\x32\x39.enterprise_management.KeyboardDefaultToFunctionKeysProto\x12w\n(ShowAccessibilityOptionsInSystemTrayMenu\x18\xbe\x01 \x01(\x0b\x32\x44.enterprise_management.ShowAccessibilityOptionsInSystemTrayMenuProto\x12S\n\x16\x43ursorHighlightEnabled\x18\xd4\x04 \x01(\x0b\x32\x32.enterprise_management.CursorHighlightEnabledProto\x12G\n\x10\x41utoclickEnabled\x18\xd7\x04 \x01(\x0b\x32,.enterprise_management.AutoclickEnabledProto\x12Q\n\x15SpokenFeedbackEnabled\x18\xd6\x01 \x01(\x0b\x32\x31.enterprise_management.SpokenFeedbackEnabledProto\x12}\n+EnhancedNetworkVoicesInSelectToSpeakAllowed\x18\xfa\x06 \x01(\x0b\x32G.enterprise_management.EnhancedNetworkVoicesInSelectToSpeakAllowedProto\x12S\n\x16VirtualKeyboardEnabled\x18\x81\x02 \x01(\x0b\x32\x32.enterprise_management.VirtualKeyboardEnabledProto\x12I\n\x11StickyKeysEnabled\x18\xb3\x04 \x01(\x0b\x32-.enterprise_management.StickyKeysEnabledProto\x12\x61\n\x1d\x41\x63\x63\x65ssibilityShortcutsEnabled\x18\x95\x05 \x01(\x0b\x32\x39.enterprise_management.AccessibilityShortcutsEnabledProto\x12M\n\x13ScreenMagnifierType\x18\xd8\x01 \x01(\x0b\x32/.enterprise_management.ScreenMagnifierTypeProto\x12\x61\n\x1dKeyboardFocusHighlightEnabled\x18\xd3\x04 \x01(\x0b\x32\x39.enterprise_management.KeyboardFocusHighlightEnabledProto\x12Q\n\x15\x43\x61retHighlightEnabled\x18\xd5\x04 \x01(\x0b\x32\x31.enterprise_management.CaretHighlightEnabledProto\x12\x61\n\x1dSupervisedUserCreationEnabled\x18\xe1\x01 \x01(\x0b\x32\x39.enterprise_management.SupervisedUserCreationEnabledProto\x12o\n$SupervisedUserContentProviderEnabled\x18\xba\x02 \x01(\x0b\x32@.enterprise_management.SupervisedUserContentProviderEnabledProto\x12Y\n\x19PrintersBulkConfiguration\x18\x84\x06 \x01(\x0b\x32\x35.enterprise_management.PrintersBulkConfigurationProto\x12U\n\x17PrintingAllowedPinModes\x18\x8f\x04 \x01(\x0b\x32\x33.enterprise_management.PrintingAllowedPinModesProto\x12\x65\n\x1fPrintJobHistoryExpirationPeriod\x18\xf3\x04 \x01(\x0b\x32;.enterprise_management.PrintJobHistoryExpirationPeriodProto\x12\x63\n\x1ePrintingAPIExtensionsAllowlist\x18\x91\x06 \x01(\x0b\x32:.enterprise_management.PrintingAPIExtensionsAllowlistProto\x12Y\n\x19PrintingAllowedColorModes\x18\xdc\x03 \x01(\x0b\x32\x35.enterprise_management.PrintingAllowedColorModesProto\x12_\n\x1cNativePrintersBulkAccessMode\x18\x81\x03 \x01(\x0b\x32\x38.enterprise_management.NativePrintersBulkAccessModeProto\x12R\n\x16\x43loudPrintProxyEnabled\x18\x0f \x01(\x0b\x32\x32.enterprise_management.CloudPrintProxyEnabledProto\x12I\n\x11PrintHeaderFooter\x18\xe2\x03 \x01(\x0b\x32-.enterprise_management.PrintHeaderFooterProto\x12s\n&PrintingSendUsernameAndFilenameEnabled\x18\xfc\x03 \x01(\x0b\x32\x42.enterprise_management.PrintingSendUsernameAndFilenameEnabledProto\x12_\n\x1c\x44\x65letePrintJobHistoryAllowed\x18\xd2\x05 \x01(\x0b\x32\x38.enterprise_management.DeletePrintJobHistoryAllowedProto\x12L\n\x13\x44isablePrintPreview\x18w \x01(\x0b\x32/.enterprise_management.DisablePrintPreviewProto\x12M\n\x13PrintPostScriptMode\x18\x81\x07 \x01(\x0b\x32/.enterprise_management.PrintPostScriptModeProto\x12]\n\x1bPrintPdfAsImageAvailability\x18\xfb\x06 \x01(\x0b\x32\x37.enterprise_management.PrintPdfAsImageAvailabilityProto\x12\x61\n\x1d\x45xternalPrintServersAllowlist\x18\xf0\x05 \x01(\x0b\x32\x39.enterprise_management.ExternalPrintServersAllowlistProto\x12O\n\x14\x45xternalPrintServers\x18\xbe\x04 \x01(\x0b\x32\x30.enterprise_management.ExternalPrintServersProto\x12Q\n\x15PrintersBulkBlocklist\x18\x8d\x06 \x01(\x0b\x32\x31.enterprise_management.PrintersBulkBlocklistProto\x12W\n\x18PrintingPaperSizeDefault\x18\xe1\x03 \x01(\x0b\x32\x34.enterprise_management.PrintingPaperSizeDefaultProto\x12\x65\n\x1fNativePrintersBulkConfiguration\x18\x80\x03 \x01(\x0b\x32;.enterprise_management.NativePrintersBulkConfigurationProto\x12s\n&PrintingAllowedBackgroundGraphicsModes\x18\xef\x04 \x01(\x0b\x32\x42.enterprise_management.PrintingAllowedBackgroundGraphicsModesProto\x12Q\n\x15PrintersBulkAllowlist\x18\x8e\x06 \x01(\x0b\x32\x31.enterprise_management.PrintersBulkAllowlistProto\x12[\n\x1aPrintingAllowedDuplexModes\x18\xdd\x03 \x01(\x0b\x32\x36.enterprise_management.PrintingAllowedDuplexModesProto\x12Q\n\x15PrintingDuplexDefault\x18\xe0\x03 \x01(\x0b\x32\x31.enterprise_management.PrintingDuplexDefaultProto\x12K\n\x12PrintingPinDefault\x18\x90\x04 \x01(\x0b\x32..enterprise_management.PrintingPinDefaultProto\x12S\n\x16PrintersBulkAccessMode\x18\x86\x06 \x01(\x0b\x32\x32.enterprise_management.PrintersBulkAccessModeProto\x12O\n\x14PrintRasterizePdfDpi\x18\xfc\x06 \x01(\x0b\x32\x30.enterprise_management.PrintRasterizePdfDpiProto\x12m\n#PrintPreviewUseSystemDefaultPrinter\x18\xf7\x02 \x01(\x0b\x32?.enterprise_management.PrintPreviewUseSystemDefaultPrinterProto\x12W\n\x18PrintingMaxSheetsAllowed\x18\xb6\x05 \x01(\x0b\x32\x34.enterprise_management.PrintingMaxSheetsAllowedProto\x12M\n\x13UserPrintersAllowed\x18\x82\x06 \x01(\x0b\x32/.enterprise_management.UserPrintersAllowedProto\x12i\n!PrintingBackgroundGraphicsDefault\x18\xf0\x04 \x01(\x0b\x32=.enterprise_management.PrintingBackgroundGraphicsDefaultProto\x12S\n\x16PrintPdfAsImageDefault\x18\x82\x07 \x01(\x0b\x32\x32.enterprise_management.PrintPdfAsImageDefaultProto\x12U\n\x17\x44\x65\x66\x61ultPrinterSelection\x18\xb6\x02 \x01(\x0b\x32\x33.enterprise_management.DefaultPrinterSelectionProto\x12T\n\x17\x43loudPrintSubmitEnabled\x18o \x01(\x0b\x32\x33.enterprise_management.CloudPrintSubmitEnabledProto\x12M\n\x13PrinterTypeDenyList\x18\x89\x05 \x01(\x0b\x32/.enterprise_management.PrinterTypeDenyListProto\x12\x44\n\x0fPrintingEnabled\x18\x0e \x01(\x0b\x32+.enterprise_management.PrintingEnabledProto\x12\x43\n\x0eNativePrinters\x18\xe0\x02 \x01(\x0b\x32*.enterprise_management.NativePrintersProto\x12O\n\x14PrintingColorDefault\x18\xdf\x03 \x01(\x0b\x32\x30.enterprise_management.PrintingColorDefaultProto\x12\x37\n\x08Printers\x18\x83\x06 \x01(\x0b\x32$.enterprise_management.PrintersProto\x12Y\n\x19UserNativePrintersAllowed\x18\xb3\x03 \x01(\x0b\x32\x35.enterprise_management.UserNativePrintersAllowedProto\x12_\n\x1c\x43loudPrintWarningsSuppressed\x18\x8f\x06 \x01(\x0b\x32\x38.enterprise_management.CloudPrintWarningsSuppressedProto\x12S\n\x16PrintRasterizationMode\x18\xc4\x05 \x01(\x0b\x32\x32.enterprise_management.PrintRasterizationModeProto\x12s\n&PasswordDismissCompromisedAlertEnabled\x18\xb4\x07 \x01(\x0b\x32\x42.enterprise_management.PasswordDismissCompromisedAlertEnabledProto\x12_\n\x1cPasswordLeakDetectionEnabled\x18\xc6\x04 \x01(\x0b\x32\x38.enterprise_management.PasswordLeakDetectionEnabledProto\x12R\n\x16PasswordManagerEnabled\x18\x12 \x01(\x0b\x32\x32.enterprise_management.PasswordManagerEnabledProto\x12h\n!PasswordManagerAllowShowPasswords\x18\x13 \x01(\x0b\x32=.enterprise_management.PasswordManagerAllowShowPasswordsProto\x12M\n\x13\x43\x61stReceiverEnabled\x18\xfc\x02 \x01(\x0b\x32/.enterprise_management.CastReceiverEnabledProto\x12k\n\"BrowserSwitcherExternalSitelistUrl\x18\x81\x04 \x01(\x0b\x32>.enterprise_management.BrowserSwitcherExternalSitelistUrlProto\x12k\n\"BrowserSwitcherExternalGreylistUrl\x18\xb6\x04 \x01(\x0b\x32>.enterprise_management.BrowserSwitcherExternalGreylistUrlProto\x12\x65\n\x1f\x42rowserSwitcherChromeParameters\x18\x95\x04 \x01(\x0b\x32;.enterprise_management.BrowserSwitcherChromeParametersProto\x12_\n\x1c\x42rowserSwitcherUseIeSitelist\x18\xf4\x03 \x01(\x0b\x32\x38.enterprise_management.BrowserSwitcherUseIeSitelistProto\x12O\n\x14\x42rowserSwitcherDelay\x18\x8e\x04 \x01(\x0b\x32\x30.enterprise_management.BrowserSwitcherDelayProto\x12S\n\x16\x42rowserSwitcherEnabled\x18\x87\x04 \x01(\x0b\x32\x32.enterprise_management.BrowserSwitcherEnabledProto\x12S\n\x16\x41lternativeBrowserPath\x18\xf0\x03 \x01(\x0b\x32\x32.enterprise_management.AlternativeBrowserPathProto\x12S\n\x16\x42rowserSwitcherUrlList\x18\xf2\x03 \x01(\x0b\x32\x32.enterprise_management.BrowserSwitcherUrlListProto\x12_\n\x1c\x41lternativeBrowserParameters\x18\xf1\x03 \x01(\x0b\x32\x38.enterprise_management.AlternativeBrowserParametersProto\x12[\n\x1a\x42rowserSwitcherUrlGreylist\x18\xf3\x03 \x01(\x0b\x32\x36.enterprise_management.BrowserSwitcherUrlGreylistProto\x12[\n\x1a\x42rowserSwitcherParsingMode\x18\xe4\x06 \x01(\x0b\x32\x36.enterprise_management.BrowserSwitcherParsingModeProto\x12g\n BrowserSwitcherKeepLastChromeTab\x18\x89\x04 \x01(\x0b\x32<.enterprise_management.BrowserSwitcherKeepLastChromeTabProto\x12Y\n\x19\x42rowserSwitcherChromePath\x18\x94\x04 \x01(\x0b\x32\x35.enterprise_management.BrowserSwitcherChromePathProto\x12\x43\n\x0eIsolateOrigins\x18\x90\x03 \x01(\x0b\x32*.enterprise_management.IsolateOriginsProto\x12Q\n\x15\x46orceGoogleSafeSearch\x18\x9c\x02 \x01(\x0b\x32\x31.enterprise_management.ForceGoogleSafeSearchProto\x12i\n!LoginDisplayPasswordButtonEnabled\x18\xbf\x05 \x01(\x0b\x32=.enterprise_management.LoginDisplayPasswordButtonEnabledProto\x12]\n\x1bSecondaryGoogleAccountUsage\x18\xbe\x07 \x01(\x0b\x32\x37.enterprise_management.SecondaryGoogleAccountUsageProto\x12]\n\x1b\x45ncryptedClientHelloEnabled\x18\xe6\x07 \x01(\x0b\x32\x37.enterprise_management.EncryptedClientHelloEnabledProto\x12Q\n\x15SSLVersionFallbackMin\x18\x9a\x02 \x01(\x0b\x32\x31.enterprise_management.SSLVersionFallbackMinProto\x12K\n\x12NearbyShareAllowed\x18\xfb\x05 \x01(\x0b\x32..enterprise_management.NearbyShareAllowedProto\x12Q\n\x15\x44ownloadBubbleEnabled\x18\xcc\x07 \x01(\x0b\x32\x31.enterprise_management.DownloadBubbleEnabledProto\x12\x81\x01\n-DefaultSearchProviderContextMenuAccessAllowed\x18\xcd\x05 \x01(\x0b\x32I.enterprise_management.DefaultSearchProviderContextMenuAccessAllowedProto\x12J\n\x12ImportSearchEngine\x18\x66 \x01(\x0b\x32..enterprise_management.ImportSearchEngineProto\x12Y\n\x19SystemFeaturesDisableMode\x18\xa9\x06 \x01(\x0b\x32\x35.enterprise_management.SystemFeaturesDisableModeProto\x12q\n%AdvancedProtectionDeepScanningEnabled\x18\x9d\x05 \x01(\x0b\x32\x41.enterprise_management.AdvancedProtectionDeepScanningEnabledProto\x12]\n\x1bTouchVirtualKeyboardEnabled\x18\x8f\x02 \x01(\x0b\x32\x37.enterprise_management.TouchVirtualKeyboardEnabledProto\x12_\n\x1cSafeBrowsingWhitelistDomains\x18\xa8\x03 \x01(\x0b\x32\x38.enterprise_management.SafeBrowsingWhitelistDomainsProto\x12W\n\x18\x41llowSystemNotifications\x18\xbe\x06 \x01(\x0b\x32\x34.enterprise_management.AllowSystemNotificationsProto\x12I\n\x11\x41utoOpenFileTypes\x18\xbe\x05 \x01(\x0b\x32-.enterprise_management.AutoOpenFileTypesProto\x12Y\n\x19PolicyAtomicGroupsEnabled\x18\xca\x04 \x01(\x0b\x32\x35.enterprise_management.PolicyAtomicGroupsEnabledProto\x12X\n\x19\x45xtensionInstallWhitelist\x18# \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallWhitelistProto\x12\x63\n\x1e\x43\x41\x43\x65rtificateManagementAllowed\x18\xc5\x04 \x01(\x0b\x32:.enterprise_management.CACertificateManagementAllowedProto\x12I\n\x11\x46ullscreenAllowed\x18\xf2\x01 \x01(\x0b\x32-.enterprise_management.FullscreenAllowedProto\x12o\n$EnterpriseHardwarePlatformAPIEnabled\x18\xe5\x03 \x01(\x0b\x32@.enterprise_management.EnterpriseHardwarePlatformAPIEnabledProto\x12\x65\n\x1fLacrosDataBackwardMigrationMode\x18\xf6\x07 \x01(\x0b\x32;.enterprise_management.LacrosDataBackwardMigrationModeProto\x12>\n\x0cSyncDisabled\x18\x16 \x01(\x0b\x32(.enterprise_management.SyncDisabledProto\x12\x89\x01\n1CertificateTransparencyEnforcementDisabledForUrls\x18\xd1\x02 \x01(\x0b\x32M.enterprise_management.CertificateTransparencyEnforcementDisabledForUrlsProto\x12\x41\n\rHttpsOnlyMode\x18\xe8\x06 \x01(\x0b\x32).enterprise_management.HttpsOnlyModeProto\x12U\n\x17LensRegionSearchEnabled\x18\xf8\x06 \x01(\x0b\x32\x33.enterprise_management.LensRegionSearchEnabledProto\x12\x7f\n,RequireOnlineRevocationChecksForLocalAnchors\x18\xed\x01 \x01(\x0b\x32H.enterprise_management.RequireOnlineRevocationChecksForLocalAnchorsProto\x12i\n!SuppressChromeFrameTurndownPrompt\x18\xdf\x01 \x01(\x0b\x32=.enterprise_management.SuppressChromeFrameTurndownPromptProto\x12S\n\x16VmManagementCliAllowed\x18\xc3\x04 \x01(\x0b\x32\x32.enterprise_management.VmManagementCliAllowedProto\x12O\n\x14\x44\x65skTemplatesEnabled\x18\x90\x07 \x01(\x0b\x32\x30.enterprise_management.DeskTemplatesEnabledProto\x12\x44\n\x0fImportBookmarks\x18\x63 \x01(\x0b\x32+.enterprise_management.ImportBookmarksProto\x12W\n\x18\x41llowChromeDataInBackups\x18\xca\x07 \x01(\x0b\x32\x34.enterprise_management.AllowChromeDataInBackupsProto\x12Q\n\x15\x41llowedDomainsForApps\x18\xcd\x02 \x01(\x0b\x32\x31.enterprise_management.AllowedDomainsForAppsProto\x12\x43\n\x0eSessionLocales\x18\x94\x02 \x01(\x0b\x32*.enterprise_management.SessionLocalesProto\x12\x65\n\x1f\x41llowWebAuthnWithBrokenTlsCerts\x18\x87\x08 \x01(\x0b\x32;.enterprise_management.AllowWebAuthnWithBrokenTlsCertsProto\x12o\n$StartupBrowserWindowLaunchSuppressed\x18\xba\x04 \x01(\x0b\x32@.enterprise_management.StartupBrowserWindowLaunchSuppressedProto\x12Y\n\x19SystemFeaturesDisableList\x18\xb3\x05 \x01(\x0b\x32\x35.enterprise_management.SystemFeaturesDisableListProto\x12Q\n\x15\x46orceNetworkInProcess\x18\x8b\x04 \x01(\x0b\x32\x31.enterprise_management.ForceNetworkInProcessProto\x12K\n\x12\x46orceBrowserSignin\x18\xdc\x02 \x01(\x0b\x32..enterprise_management.ForceBrowserSigninProto\x12]\n\x1bMediaRecommendationsEnabled\x18\x96\x06 \x01(\x0b\x32\x37.enterprise_management.MediaRecommendationsEnabledProto\x12k\n\"CloudPolicyOverridesPlatformPolicy\x18\xff\x02 \x01(\x0b\x32>.enterprise_management.CloudPolicyOverridesPlatformPolicyProto\x12_\n\x1cPhoneHubNotificationsAllowed\x18\x9e\x06 \x01(\x0b\x32\x38.enterprise_management.PhoneHubNotificationsAllowedProto\x12{\n*MachineLevelUserCloudPolicyEnrollmentToken\x18\xae\x03 \x01(\x0b\x32\x46.enterprise_management.MachineLevelUserCloudPolicyEnrollmentTokenProto\x12]\n\x1b\x43learBrowsingDataOnExitList\x18\xab\x06 \x01(\x0b\x32\x37.enterprise_management.ClearBrowsingDataOnExitListProto\x12q\n%VirtualKeyboardResizesLayoutByDefault\x18\x82\x08 \x01(\x0b\x32\x41.enterprise_management.VirtualKeyboardResizesLayoutByDefaultProto\x12Q\n\x15ShelfAutoHideBehavior\x18\xa8\x01 \x01(\x0b\x32\x31.enterprise_management.ShelfAutoHideBehaviorProto\x12U\n\x17TabDiscardingExceptions\x18\xf4\x07 \x01(\x0b\x32\x33.enterprise_management.TabDiscardingExceptionsProto\x12q\n%InsecurePrivateNetworkRequestsAllowed\x18\x80\x06 \x01(\x0b\x32\x41.enterprise_management.InsecurePrivateNetworkRequestsAllowedProto\x12\x63\n\x1e\x43loudManagementEnrollmentToken\x18\x80\x04 \x01(\x0b\x32:.enterprise_management.CloudManagementEnrollmentTokenProto\x12K\n\x12LacrosAvailability\x18\xd9\x06 \x01(\x0b\x32..enterprise_management.LacrosAvailabilityProto\x12S\n\x16PersistentQuotaEnabled\x18\xec\x07 \x01(\x0b\x32\x32.enterprise_management.PersistentQuotaEnabledProto\x12L\n\x13\x44isablePluginFinder\x18\x44 \x01(\x0b\x32/.enterprise_management.DisablePluginFinderProto\x12N\n\x14\x41llowOutdatedPlugins\x18S \x01(\x0b\x32\x30.enterprise_management.AllowOutdatedPluginsProto\x12[\n\x1aPreconfiguredDeskTemplates\x18\x91\x07 \x01(\x0b\x32\x36.enterprise_management.PreconfiguredDeskTemplatesProto\x12T\n\x17MetricsReportingEnabled\x18\x11 \x01(\x0b\x32\x33.enterprise_management.MetricsReportingEnabledProto\x12\x87\x01\n0CertificateTransparencyEnforcementDisabledForCas\x18\xb5\x03 \x01(\x0b\x32L.enterprise_management.CertificateTransparencyEnforcementDisabledForCasProto\x12Q\n\x15LocalDiscoveryEnabled\x18\x98\x05 \x01(\x0b\x32\x31.enterprise_management.LocalDiscoveryEnabledProto\x12g\n DisableSafeBrowsingProceedAnyway\x18\x98\x01 \x01(\x0b\x32<.enterprise_management.DisableSafeBrowsingProceedAnywayProto\x12M\n\x13\x41llowedInputMethods\x18\xca\x03 \x01(\x0b\x32/.enterprise_management.AllowedInputMethodsProto\x12S\n\x16WebAppInstallForceList\x18\xd6\x03 \x01(\x0b\x32\x32.enterprise_management.WebAppInstallForceListProto\x12W\n\x18U2fSecurityKeyApiEnabled\x18\x89\x07 \x01(\x0b\x32\x34.enterprise_management.U2fSecurityKeyApiEnabledProto\x12Y\n\x19HighEfficiencyModeEnabled\x18\xf0\x07 \x01(\x0b\x32\x35.enterprise_management.HighEfficiencyModeEnabledProto\x12\x63\n\x1ePrintingAPIExtensionsWhitelist\x18\x9a\x05 \x01(\x0b\x32:.enterprise_management.PrintingAPIExtensionsWhitelistProto\x12K\n\x12SmsMessagesAllowed\x18\xd7\x03 \x01(\x0b\x32..enterprise_management.SmsMessagesAllowedProto\x12k\n\"ProfilePickerOnStartupAvailability\x18\xac\x06 \x01(\x0b\x32>.enterprise_management.ProfilePickerOnStartupAvailabilityProto\x12\x43\n\x0eRelaunchWindow\x18\xd8\x06 \x01(\x0b\x32*.enterprise_management.RelaunchWindowProto\x12\x45\n\x0f\x46orceSafeSearch\x18\xa4\x01 \x01(\x0b\x32+.enterprise_management.ForceSafeSearchProto\x12K\n\x12\x44isableScreenshots\x18\x9b\x01 \x01(\x0b\x32..enterprise_management.DisableScreenshotsProto\x12R\n\x16\x44\x65veloperToolsDisabled\x18& \x01(\x0b\x32\x32.enterprise_management.DeveloperToolsDisabledProto\x12I\n\x11\x41utoplayAllowlist\x18\xe8\x05 \x01(\x0b\x32-.enterprise_management.AutoplayAllowlistProto\x12K\n\x12\x42rowserLabsEnabled\x18\xb2\x06 \x01(\x0b\x32..enterprise_management.BrowserLabsEnabledProto\x12[\n\x1aReportCrostiniUsageEnabled\x18\xe6\x03 \x01(\x0b\x32\x36.enterprise_management.ReportCrostiniUsageEnabledProto\x12W\n\x18NativeMessagingBlacklist\x18\xfd\x01 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingBlacklistProto\x12S\n\x16\x41utofillAddressEnabled\x18\xcd\x03 \x01(\x0b\x32\x32.enterprise_management.AutofillAddressEnabledProto\x12S\n\x16\x46ullscreenAlertEnabled\x18\xa6\x06 \x01(\x0b\x32\x32.enterprise_management.FullscreenAlertEnabledProto\x12G\n\x10HideWebStoreIcon\x18\xbf\x01 \x01(\x0b\x32,.enterprise_management.HideWebStoreIconProto\x12_\n\x1cSecurityKeyPermitAttestation\x18\x94\x03 \x01(\x0b\x32\x38.enterprise_management.SecurityKeyPermitAttestationProto\x12m\n#OnFileDownloadedEnterpriseConnector\x18\xba\x05 \x01(\x0b\x32?.enterprise_management.OnFileDownloadedEnterpriseConnectorProto\x12M\n\x13\x43\x43TToSDialogEnabled\x18\xfa\x05 \x01(\x0b\x32/.enterprise_management.CCTToSDialogEnabledProto\x12W\n\x18IntranetRedirectBehavior\x18\x9a\x06 \x01(\x0b\x32\x34.enterprise_management.IntranetRedirectBehaviorProto\x12Y\n\x19PhoneHubCameraRollAllowed\x18\xaa\x07 \x01(\x0b\x32\x35.enterprise_management.PhoneHubCameraRollAllowedProto\x12\x61\n\x1dManagedConfigurationPerOrigin\x18\xaf\x06 \x01(\x0b\x32\x39.enterprise_management.ManagedConfigurationPerOriginProto\x12\x63\n\x1eUserDataSnapshotRetentionLimit\x18\xa3\x05 \x01(\x0b\x32:.enterprise_management.UserDataSnapshotRetentionLimitProto\x12\x63\n\x1e\x44\x65skAPIThirdPartyAccessEnabled\x18\xfd\x07 \x01(\x0b\x32:.enterprise_management.DeskAPIThirdPartyAccessEnabledProto\x12o\n$CORSNonWildcardRequestHeadersSupport\x18\x9b\x07 \x01(\x0b\x32@.enterprise_management.CORSNonWildcardRequestHeadersSupportProto\x12I\n\x11\x42rowserThemeColor\x18\xca\x06 \x01(\x0b\x32-.enterprise_management.BrowserThemeColorProto\x12i\n!NoteTakingAppsLockScreenWhitelist\x18\xfb\x02 \x01(\x0b\x32=.enterprise_management.NoteTakingAppsLockScreenWhitelistProto\x12\x63\n\x1eLockScreenMediaPlaybackEnabled\x18\xc7\x04 \x01(\x0b\x32:.enterprise_management.LockScreenMediaPlaybackEnabledProto\x12K\n\x12TotalMemoryLimitMb\x18\xea\x04 \x01(\x0b\x32..enterprise_management.TotalMemoryLimitMbProto\x12[\n\x1aOnPrintEnterpriseConnector\x18\xa5\x07 \x01(\x0b\x32\x36.enterprise_management.OnPrintEnterpriseConnectorProto\x12Q\n\x15RelaunchHeadsUpPeriod\x18\xb9\x04 \x01(\x0b\x32\x31.enterprise_management.RelaunchHeadsUpPeriodProto\x12?\n\x0cWebSQLAccess\x18\xc8\x07 \x01(\x0b\x32(.enterprise_management.WebSQLAccessProto\x12G\n\x10ManagedBookmarks\x18\xe5\x01 \x01(\x0b\x32,.enterprise_management.ManagedBookmarksProto\x12[\n\x1a\x44\x65veloperToolsAvailability\x18\xbd\x03 \x01(\x0b\x32\x36.enterprise_management.DeveloperToolsAvailabilityProto\x12_\n\x1cSuppressUnsupportedOSWarning\x18\xc6\x02 \x01(\x0b\x32\x38.enterprise_management.SuppressUnsupportedOSWarningProto\x12g\n DefaultHandlersForFileExtensions\x18\xff\x07 \x01(\x0b\x32<.enterprise_management.DefaultHandlersForFileExtensionsProto\x12Y\n\x19WarnBeforeQuittingEnabled\x18\xcf\x07 \x01(\x0b\x32\x35.enterprise_management.WarnBeforeQuittingEnabledProto\x12k\n\"OnSecurityEventEnterpriseConnector\x18\xbd\x05 \x01(\x0b\x32>.enterprise_management.OnSecurityEventEnterpriseConnectorProto\x12{\n*StrictMimetypeCheckForWorkerScriptsEnabled\x18\xf7\x07 \x01(\x0b\x32\x46.enterprise_management.StrictMimetypeCheckForWorkerScriptsEnabledProto\x12g\n ManagedAccountsSigninRestriction\x18\xde\x06 \x01(\x0b\x32<.enterprise_management.ManagedAccountsSigninRestrictionProto\x12S\n\x16RemoteDebuggingAllowed\x18\xe2\x06 \x01(\x0b\x32\x32.enterprise_management.RemoteDebuggingAllowedProto\x12_\n\x1c\x43ontextualSuggestionsEnabled\x18\xc6\x03 \x01(\x0b\x32\x38.enterprise_management.ContextualSuggestionsEnabledProto\x12G\n\x10VpnConfigAllowed\x18\xe7\x03 \x01(\x0b\x32,.enterprise_management.VpnConfigAllowedProto\x12K\n\x12WebRtcUdpPortRange\x18\xd5\x02 \x01(\x0b\x32..enterprise_management.WebRtcUdpPortRangeProto\x12\x61\n\x1d\x45xternalPrintServersWhitelist\x18\xf9\x04 \x01(\x0b\x32\x39.enterprise_management.ExternalPrintServersWhitelistProto\x12@\n\rDiskCacheSize\x18p \x01(\x0b\x32).enterprise_management.DiskCacheSizeProto\x12X\n\x19\x41llowFileSelectionDialogs\x18V \x01(\x0b\x32\x35.enterprise_management.AllowFileSelectionDialogsProto\x12U\n\x17\x41udioCaptureAllowedUrls\x18\xd2\x01 \x01(\x0b\x32\x33.enterprise_management.AudioCaptureAllowedUrlsProto\x12O\n\x14\x46orceYouTubeRestrict\x18\xde\x02 \x01(\x0b\x32\x30.enterprise_management.ForceYouTubeRestrictProto\x12Y\n\x19\x45\x63ryptfsMigrationStrategy\x18\xfa\x02 \x01(\x0b\x32\x35.enterprise_management.EcryptfsMigrationStrategyProto\x12\x63\n\x1e\x41utoLaunchProtocolsFromOrigins\x18\xd4\x05 \x01(\x0b\x32:.enterprise_management.AutoLaunchProtocolsFromOriginsProto\x12>\n\x0c\x44iskCacheDir\x18Z \x01(\x0b\x32(.enterprise_management.DiskCacheDirProto\x12\x63\n\x1e\x41\x64\x64itionalDnsQueryTypesEnabled\x18\xdb\x06 \x01(\x0b\x32:.enterprise_management.AdditionalDnsQueryTypesEnabledProto\x12\x61\n\x1d\x41ttestationExtensionWhitelist\x18\xcb\x01 \x01(\x0b\x32\x39.enterprise_management.AttestationExtensionWhitelistProto\x12\x63\n\x1eUnifiedDesktopEnabledByDefault\x18\xb5\x02 \x01(\x0b\x32:.enterprise_management.UnifiedDesktopEnabledByDefaultProto\x12{\n*SendMouseEventsDisabledFormControlsEnabled\x18\x8a\x08 \x01(\x0b\x32\x46.enterprise_management.SendMouseEventsDisabledFormControlsEnabledProto\x12K\n\x12SpellcheckLanguage\x18\x97\x03 \x01(\x0b\x32..enterprise_management.SpellcheckLanguageProto\x12P\n\x15\x44nsPrefetchingEnabled\x18\t \x01(\x0b\x32\x31.enterprise_management.DnsPrefetchingEnabledProto\x12S\n\x16ImportAutofillFormData\x18\x97\x02 \x01(\x0b\x32\x32.enterprise_management.ImportAutofillFormDataProto\x12K\n\x12UserAgentReduction\x18\xa6\x07 \x01(\x0b\x32..enterprise_management.UserAgentReductionProto\x12_\n\x1cNativeWindowOcclusionEnabled\x18\xa5\x05 \x01(\x0b\x32\x38.enterprise_management.NativeWindowOcclusionEnabledProto\x12U\n\x17\x45xternalStorageDisabled\x18\x9a\x01 \x01(\x0b\x32\x33.enterprise_management.ExternalStorageDisabledProto\x12Z\n\x1a\x41lternateErrorPagesEnabled\x18\x07 \x01(\x0b\x32\x36.enterprise_management.AlternateErrorPagesEnabledProto\x12W\n\x18\x44\x65\x66\x61ultDownloadDirectory\x18\x93\x03 \x01(\x0b\x32\x34.enterprise_management.DefaultDownloadDirectoryProto\x12\x45\n\x0f\x41utoplayAllowed\x18\xb0\x03 \x01(\x0b\x32+.enterprise_management.AutoplayAllowedProto\x12g\n WebSQLInThirdPartyContextEnabled\x18\x88\x07 \x01(\x0b\x32<.enterprise_management.WebSQLInThirdPartyContextEnabledProto\x12]\n\x1b\x44\x61taLeakPreventionRulesList\x18\x94\x06 \x01(\x0b\x32\x37.enterprise_management.DataLeakPreventionRulesListProto\x12U\n\x17\x42\x61\x63kForwardCacheEnabled\x18\xf8\x05 \x01(\x0b\x32\x33.enterprise_management.BackForwardCacheEnabledProto\x12S\n\x16ShowLogoutButtonInTray\x18\xa6\x01 \x01(\x0b\x32\x32.enterprise_management.ShowLogoutButtonInTrayProto\x12?\n\x0cHeadlessMode\x18\xcc\x06 \x01(\x0b\x32(.enterprise_management.HeadlessModeProto\x12[\n\x1aPrefixedStorageInfoEnabled\x18\xee\x07 \x01(\x0b\x32\x36.enterprise_management.PrefixedStorageInfoEnabledProto\x12Y\n\x19PerAppTimeLimitsWhitelist\x18\x94\x05 \x01(\x0b\x32\x35.enterprise_management.PerAppTimeLimitsWhitelistProto\x12[\n\x1aNTPCustomBackgroundEnabled\x18\x8f\x05 \x01(\x0b\x32\x36.enterprise_management.NTPCustomBackgroundEnabledProto\x12_\n\x1cTaskManagerEndProcessEnabled\x18\xc9\x02 \x01(\x0b\x32\x38.enterprise_management.TaskManagerEndProcessEnabledProto\x12\x43\n\x0eKeyPermissions\x18\xb0\x02 \x01(\x0b\x32*.enterprise_management.KeyPermissionsProto\x12U\n\x17\x42uiltInDnsClientEnabled\x18\xa7\x01 \x01(\x0b\x32\x33.enterprise_management.BuiltInDnsClientEnabledProto\x12o\n$StricterMixedContentTreatmentEnabled\x18\x8e\x05 \x01(\x0b\x32@.enterprise_management.StricterMixedContentTreatmentEnabledProto\x12G\n\x10TripleDESEnabled\x18\xdc\x06 \x01(\x0b\x32,.enterprise_management.TripleDESEnabledProto\x12i\n!BuiltinCertificateVerifierEnabled\x18\xc1\x04 \x01(\x0b\x32=.enterprise_management.BuiltinCertificateVerifierEnabledProto\x12m\n#EnableDeprecatedWebPlatformFeatures\x18\x90\x02 \x01(\x0b\x32?.enterprise_management.EnableDeprecatedWebPlatformFeaturesProto\x12X\n\x19\x45xtensionInstallBlacklist\x18\" \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallBlacklistProto\x12\x44\n\x0f\x44isabledPlugins\x18\x15 \x01(\x0b\x32+.enterprise_management.DisabledPluginsProto\x12R\n\x16MaxConnectionsPerProxy\x18^ \x01(\x0b\x32\x32.enterprise_management.MaxConnectionsPerProxyProto\x12u\n\'SecurityTokenSessionNotificationSeconds\x18\xa2\x06 \x01(\x0b\x32\x43.enterprise_management.SecurityTokenSessionNotificationSecondsProto\x12}\n+ThrottleNonVisibleCrossOriginIframesAllowed\x18\x8f\x08 \x01(\x0b\x32G.enterprise_management.ThrottleNonVisibleCrossOriginIframesAllowedProto\x12\x63\n\x1eHttp09OnNonDefaultPortsEnabled\x18\xdb\x02 \x01(\x0b\x32:.enterprise_management.Http09OnNonDefaultPortsEnabledProto\x12\x43\n\x0eWebAppSettings\x18\xba\x06 \x01(\x0b\x32*.enterprise_management.WebAppSettingsProto\x12\x65\n\x1f\x41udioProcessHighPriorityEnabled\x18\xc6\x06 \x01(\x0b\x32;.enterprise_management.AudioProcessHighPriorityEnabledProto\x12k\n\"EnableSymantecLegacyInfrastructure\x18\x9f\x03 \x01(\x0b\x32>.enterprise_management.EnableSymantecLegacyInfrastructureProto\x12K\n\x12PinnedLauncherApps\x18\x92\x01 \x01(\x0b\x32..enterprise_management.PinnedLauncherAppsProto\x12g\n SetTimeoutWithout1MsClampEnabled\x18\xc9\x07 \x01(\x0b\x32<.enterprise_management.SetTimeoutWithout1MsClampEnabledProto\x12Q\n\x15\x43orsLegacyModeEnabled\x18\xf8\x04 \x01(\x0b\x32\x31.enterprise_management.CorsLegacyModeEnabledProto\x12W\n\x18\x46loatingWorkspaceEnabled\x18\xc1\x07 \x01(\x0b\x32\x34.enterprise_management.FloatingWorkspaceEnabledProto\x12[\n\x1aRestrictAccountsToPatterns\x18\x9c\x03 \x01(\x0b\x32\x36.enterprise_management.RestrictAccountsToPatternsProto\x12S\n\x16RoamingProfileLocation\x18\xe9\x02 \x01(\x0b\x32\x32.enterprise_management.RoamingProfileLocationProto\x12Q\n\x15SitePerProcessAndroid\x18\xc0\x03 \x01(\x0b\x32\x31.enterprise_management.SitePerProcessAndroidProto\x12]\n\x1bUserAgentClientHintsEnabled\x18\xd7\x05 \x01(\x0b\x32\x37.enterprise_management.UserAgentClientHintsEnabledProto\x12\x95\x01\n7RestrictedManagedGuestSessionExtensionCleanupExemptList\x18\xf1\x06 \x01(\x0b\x32S.enterprise_management.RestrictedManagedGuestSessionExtensionCleanupExemptListProto\x12U\n\x17WebXRImmersiveArEnabled\x18\xb6\x06 \x01(\x0b\x32\x33.enterprise_management.WebXRImmersiveArEnabledProto\x12^\n\x1c\x44\x65\x66\x61ultBrowserSettingEnabled\x18\x05 \x01(\x0b\x32\x38.enterprise_management.DefaultBrowserSettingEnabledProto\x12g\n ForceLegacyDefaultReferrerPolicy\x18\x8a\x05 \x01(\x0b\x32<.enterprise_management.ForceLegacyDefaultReferrerPolicyProto\x12=\n\x0bOsColorMode\x18\xdc\x07 \x01(\x0b\x32\'.enterprise_management.OsColorModeProto\x12S\n\x16\x46orceEphemeralProfiles\x18\xf7\x01 \x01(\x0b\x32\x32.enterprise_management.ForceEphemeralProfilesProto\x12\x45\n\x0fWebAuthnFactors\x18\xc6\x07 \x01(\x0b\x32+.enterprise_management.WebAuthnFactorsProto\x12]\n\x1bRendererAppContainerEnabled\x18\xdd\x07 \x01(\x0b\x32\x37.enterprise_management.RendererAppContainerEnabledProto\x12;\n\nDHEEnabled\x18\xd0\x02 \x01(\x0b\x32&.enterprise_management.DHEEnabledProto\x12Q\n\x15IsolateOriginsAndroid\x18\xbf\x03 \x01(\x0b\x32\x31.enterprise_management.IsolateOriginsAndroidProto\x12\x62\n\x1e\x41uthNegotiateDelegateWhitelist\x18 \x01(\x0b\x32:.enterprise_management.AuthNegotiateDelegateWhitelistProto\x12O\n\x14\x44ownloadRestrictions\x18\xf5\x02 \x01(\x0b\x32\x30.enterprise_management.DownloadRestrictionsProto\x12X\n\x19\x43hromeOsLockOnIdleSuspend\x18? \x01(\x0b\x32\x35.enterprise_management.ChromeOsLockOnIdleSuspendProto\x12I\n\x11ScreenTimeEnabled\x18\xd8\x07 \x01(\x0b\x32-.enterprise_management.ScreenTimeEnabledProto\x12g\n OptimizationGuideFetchingEnabled\x18\xc5\x07 \x01(\x0b\x32<.enterprise_management.OptimizationGuideFetchingEnabledProto\x12]\n\x1bNativePrintersBulkWhitelist\x18\x83\x03 \x01(\x0b\x32\x37.enterprise_management.NativePrintersBulkWhitelistProto\x12\x46\n\x10IncognitoEnabled\x18\x0c \x01(\x0b\x32,.enterprise_management.IncognitoEnabledProto\x12P\n\x15\x45nterpriseWebStoreURL\x18r \x01(\x0b\x32\x31.enterprise_management.EnterpriseWebStoreURLProto\x12\x61\n\x1dWebSQLNonSecureContextEnabled\x18\xe3\x07 \x01(\x0b\x32\x39.enterprise_management.WebSQLNonSecureContextEnabledProto\x12Y\n\x19\x41utofillCreditCardEnabled\x18\x8a\x03 \x01(\x0b\x32\x35.enterprise_management.AutofillCreditCardEnabledProto\x12u\n\'UserAgentClientHintsGREASEUpdateEnabled\x18\x9e\x07 \x01(\x0b\x32\x43.enterprise_management.UserAgentClientHintsGREASEUpdateEnabledProto\x12Y\n\x19MaxInvalidationFetchDelay\x18\xe6\x01 \x01(\x0b\x32\x35.enterprise_management.MaxInvalidationFetchDelayProto\x12M\n\x13UserFeedbackAllowed\x18\xbc\x04 \x01(\x0b\x32/.enterprise_management.UserFeedbackAllowedProto\x12g\n NTPMiddleSlotAnnouncementVisible\x18\xaf\x07 \x01(\x0b\x32<.enterprise_management.NTPMiddleSlotAnnouncementVisibleProto\x12s\n&CommandLineFlagSecurityWarningsEnabled\x18\xb8\x04 \x01(\x0b\x32\x42.enterprise_management.CommandLineFlagSecurityWarningsEnabledProto\x12<\n\x0bUserDataDir\x18\x41 \x01(\x0b\x32\'.enterprise_management.UserDataDirProto\x12Y\n\x19SigninInterceptionEnabled\x18\xad\x06 \x01(\x0b\x32\x35.enterprise_management.SigninInterceptionEnabledProto\x12K\n\x12TabFreezingEnabled\x18\xce\x03 \x01(\x0b\x32..enterprise_management.TabFreezingEnabledProto\x12I\n\x11\x45\x61syUnlockAllowed\x18\x92\x02 \x01(\x0b\x32-.enterprise_management.EasyUnlockAllowedProto\x12Y\n\x19WebRtcLocalIpsAllowedUrls\x18\x82\x05 \x01(\x0b\x32\x35.enterprise_management.WebRtcLocalIpsAllowedUrlsProto\x12W\n\x18\x42rowserGuestModeEnforced\x18\xc0\x04 \x01(\x0b\x32\x34.enterprise_management.BrowserGuestModeEnforcedProto\x12[\n\x1aHindiInscriptLayoutEnabled\x18\x83\x08 \x01(\x0b\x32\x36.enterprise_management.HindiInscriptLayoutEnabledProto\x12\x61\n\x1dShowAppsShortcutInBookmarkBar\x18\x8d\x02 \x01(\x0b\x32\x39.enterprise_management.ShowAppsShortcutInBookmarkBarProto\x12m\n#UnsafelyTreatInsecureOriginAsSecure\x18\x92\x03 \x01(\x0b\x32?.enterprise_management.UnsafelyTreatInsecureOriginAsSecureProto\x12\x45\n\x0fUserAvatarImage\x18\xfb\x01 \x01(\x0b\x32+.enterprise_management.UserAvatarImageProto\x12M\n\x13VideoCaptureAllowed\x18\xa9\x01 \x01(\x0b\x32/.enterprise_management.VideoCaptureAllowedProto\x12<\n\x0b\x44isableSpdy\x18\n \x01(\x0b\x32\'.enterprise_management.DisableSpdyProto\x12U\n\x17\x43omponentUpdatesEnabled\x18\xd8\x02 \x01(\x0b\x32\x33.enterprise_management.ComponentUpdatesEnabledProto\x12V\n\x18OpenNetworkConfiguration\x18m \x01(\x0b\x32\x34.enterprise_management.OpenNetworkConfigurationProto\x12k\n\"OffsetParentNewSpecBehaviorEnabled\x18\x89\x08 \x01(\x0b\x32>.enterprise_management.OffsetParentNewSpecBehaviorEnabledProto\x12g\n BrowserNetworkTimeQueriesEnabled\x18\xf4\x02 \x01(\x0b\x32<.enterprise_management.BrowserNetworkTimeQueriesEnabledProto\x12_\n\x1c\x45nableOnlineRevocationChecks\x18\x83\x01 \x01(\x0b\x32\x38.enterprise_management.EnableOnlineRevocationChecksProto\x12i\n!PolicyListMultipleSourceMergeList\x18\xac\x04 \x01(\x0b\x32=.enterprise_management.PolicyListMultipleSourceMergeListProto\x12[\n\x1aTargetBlankImpliesNoOpener\x18\xa4\x06 \x01(\x0b\x32\x36.enterprise_management.TargetBlankImpliesNoOpenerProto\x12u\n\'EnableCommonNameFallbackForLocalAnchors\x18\xf0\x02 \x01(\x0b\x32\x43.enterprise_management.EnableCommonNameFallbackForLocalAnchorsProto\x12]\n\x1bScrollToTextFragmentEnabled\x18\xb1\x05 \x01(\x0b\x32\x37.enterprise_management.ScrollToTextFragmentEnabledProto\x12>\n\x0cURLBlacklist\x18i \x01(\x0b\x32(.enterprise_management.URLBlacklistProto\x12i\n!OnFileTransferEnterpriseConnector\x18\xe1\x07 \x01(\x0b\x32=.enterprise_management.OnFileTransferEnterpriseConnectorProto\x12k\n\"ClientCertificateManagementAllowed\x18\x88\x04 \x01(\x0b\x32>.enterprise_management.ClientCertificateManagementAllowedProto\x12S\n\x16SharedClipboardEnabled\x18\xe4\x04 \x01(\x0b\x32\x32.enterprise_management.SharedClipboardEnabledProto\x12O\n\x14\x43loudUserPolicyMerge\x18\xdd\x06 \x01(\x0b\x32\x30.enterprise_management.CloudUserPolicyMergeProto\x12Q\n\x15PdfAnnotationsEnabled\x18\xce\x06 \x01(\x0b\x32\x31.enterprise_management.PdfAnnotationsEnabledProto\x12\x65\n\x1fUnthrottledNestedTimeoutEnabled\x18\xde\x07 \x01(\x0b\x32;.enterprise_management.UnthrottledNestedTimeoutEnabledProto\x12=\n\x0b\x45\x63heAllowed\x18\xab\x07 \x01(\x0b\x32\'.enterprise_management.EcheAllowedProto\x12i\n!GloballyScopeHTTPAuthCacheEnabled\x18\x85\x05 \x01(\x0b\x32=.enterprise_management.GloballyScopeHTTPAuthCacheEnabledProto\x12]\n\x1bLensDesktopNTPSearchEnabled\x18\x85\x08 \x01(\x0b\x32\x37.enterprise_management.LensDesktopNTPSearchEnabledProto\x12\x63\n\x1e\x45nableDeprecatedPrivetPrinting\x18\xb1\x06 \x01(\x0b\x32:.enterprise_management.EnableDeprecatedPrivetPrintingProto\x12\x43\n\x0eWallpaperImage\x18\x88\x02 \x01(\x0b\x32*.enterprise_management.WallpaperImageProto\x12S\n\x16RunAllFlashInAllowMode\x18\x89\x03 \x01(\x0b\x32\x32.enterprise_management.RunAllFlashInAllowModeProto\x12W\n\x18InsightsExtensionEnabled\x18\xd1\x07 \x01(\x0b\x32\x34.enterprise_management.InsightsExtensionEnabledProto\x12O\n\x14\x42rowsingDataLifetime\x18\x99\x06 \x01(\x0b\x32\x30.enterprise_management.BrowsingDataLifetimeProto\x12U\n\x17InstantTetheringAllowed\x18\xf1\x02 \x01(\x0b\x32\x33.enterprise_management.InstantTetheringAllowedProto\x12I\n\x11\x41utoplayWhitelist\x18\xb1\x03 \x01(\x0b\x32-.enterprise_management.AutoplayWhitelistProto\x12Q\n\x15\x41\x63\x63\x65ssCodeCastEnabled\x18\x8d\x07 \x01(\x0b\x32\x31.enterprise_management.AccessCodeCastEnabledProto\x12g\n IsolatedAppsDeveloperModeAllowed\x18\xc0\x07 \x01(\x0b\x32<.enterprise_management.IsolatedAppsDeveloperModeAllowedProto\x12S\n\x16\x45mojiSuggestionEnabled\x18\xd3\x05 \x01(\x0b\x32\x32.enterprise_management.EmojiSuggestionEnabledProto\x12S\n\x16WebComponentsV0Enabled\x18\x86\x05 \x01(\x0b\x32\x32.enterprise_management.WebComponentsV0EnabledProto\x12M\n\x13ShoppingListEnabled\x18\xfc\x07 \x01(\x0b\x32/.enterprise_management.ShoppingListEnabledProto\x12k\n\"CloudManagementEnrollmentMandatory\x18\xfb\x03 \x01(\x0b\x32>.enterprise_management.CloudManagementEnrollmentMandatoryProto\x12\x43\n\x0eShelfAlignment\x18\xee\x04 \x01(\x0b\x32*.enterprise_management.ShelfAlignmentProto\x12S\n\x16\x43opyPreventionSettings\x18\xa2\x07 \x01(\x0b\x32\x32.enterprise_management.CopyPreventionSettingsProto\x12S\n\x16WindowOcclusionEnabled\x18\xb3\x06 \x01(\x0b\x32\x32.enterprise_management.WindowOcclusionEnabledProto\x12g\n IntensiveWakeUpThrottlingEnabled\x18\xcb\x05 \x01(\x0b\x32<.enterprise_management.IntensiveWakeUpThrottlingEnabledProto\x12Q\n\x15UrlParamFilterEnabled\x18\xd7\x07 \x01(\x0b\x32\x31.enterprise_management.UrlParamFilterEnabledProto\x12S\n\x16WifiSyncAndroidAllowed\x18\xa0\x06 \x01(\x0b\x32\x32.enterprise_management.WifiSyncAndroidAllowedProto\x12]\n\x1b\x44\x61taCompressionProxyEnabled\x18\xf3\x01 \x01(\x0b\x32\x37.enterprise_management.DataCompressionProxyEnabledProto\x12Q\n\x15SyncTypesListDisabled\x18\x8b\x05 \x01(\x0b\x32\x31.enterprise_management.SyncTypesListDisabledProto\x12S\n\x16\x46orceYouTubeSafetyMode\x18\x9d\x02 \x01(\x0b\x32\x32.enterprise_management.ForceYouTubeSafetyModeProto\x12R\n\x16\x41pplicationLocaleValue\x18\x06 \x01(\x0b\x32\x32.enterprise_management.ApplicationLocaleValueProto\x12u\n\'DeviceLocalAccountManagedSessionEnabled\x18\xd1\x03 \x01(\x0b\x32\x43.enterprise_management.DeviceLocalAccountManagedSessionEnabledProto\x12y\n)EnterpriseProfileCreationKeepBrowsingData\x18\xe8\x07 \x01(\x0b\x32\x45.enterprise_management.EnterpriseProfileCreationKeepBrowsingDataProto\x12;\n\nRC4Enabled\x18\xb8\x02 \x01(\x0b\x32&.enterprise_management.RC4EnabledProto\x12G\n\x10\x41llowedLanguages\x18\xbe\x03 \x01(\x0b\x32,.enterprise_management.AllowedLanguagesProto\x12\x65\n\x1fHardwareAccelerationModeEnabled\x18\xb2\x02 \x01(\x0b\x32;.enterprise_management.HardwareAccelerationModeEnabledProto\x12{\n*AmbientAuthenticationInPrivateModesEnabled\x18\x8c\x05 \x01(\x0b\x32\x46.enterprise_management.AmbientAuthenticationInPrivateModesEnabledProto\x12O\n\x14\x43hromeCleanupEnabled\x18\xbb\x03 \x01(\x0b\x32\x30.enterprise_management.ChromeCleanupEnabledProto\x12G\n\x10\x43hromeVariations\x18\x99\x05 \x01(\x0b\x32,.enterprise_management.ChromeVariationsProto\x12Y\n\x19PaymentMethodQueryEnabled\x18\x8d\x05 \x01(\x0b\x32\x35.enterprise_management.PaymentMethodQueryEnabledProto\x12@\n\rProxySettings\x18v \x01(\x0b\x32).enterprise_management.ProxySettingsProto\x12\x91\x01\n5ExemptDomainFileTypePairsFromFileTypeDownloadWarnings\x18\xb5\x07 \x01(\x0b\x32Q.enterprise_management.ExemptDomainFileTypePairsFromFileTypeDownloadWarningsProto\x12y\n)SafeBrowsingExtendedReportingOptInAllowed\x18\xad\x02 \x01(\x0b\x32\x45.enterprise_management.SafeBrowsingExtendedReportingOptInAllowedProto\x12[\n\x1a\x45nableExperimentalPolicies\x18\xc9\x05 \x01(\x0b\x32\x36.enterprise_management.EnableExperimentalPoliciesProto\x12\x63\n\x1e\x45nableDeprecatedWebBasedSignin\x18\x8b\x02 \x01(\x0b\x32:.enterprise_management.EnableDeprecatedWebBasedSigninProto\x12W\n\x18NativeMessagingWhitelist\x18\xfe\x01 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingWhitelistProto\x12M\n\x13\x41udioCaptureAllowed\x18\xa2\x01 \x01(\x0b\x32/.enterprise_management.AudioCaptureAllowedProto\x12U\n\x17\x45xternalStorageReadOnly\x18\xd9\x02 \x01(\x0b\x32\x33.enterprise_management.ExternalStorageReadOnlyProto\x12\x65\n\x1fLensCameraAssistedSearchEnabled\x18\xd7\x06 \x01(\x0b\x32;.enterprise_management.LensCameraAssistedSearchEnabledProto\x12s\n&WebDriverOverridesIncompatiblePolicies\x18\xa0\x03 \x01(\x0b\x32\x42.enterprise_management.WebDriverOverridesIncompatiblePoliciesProto\x12K\n\x12SessionLengthLimit\x18\xac\x01 \x01(\x0b\x32..enterprise_management.SessionLengthLimitProto\x12W\n\x18PrimaryMouseButtonSwitch\x18\x91\x05 \x01(\x0b\x32\x34.enterprise_management.PrimaryMouseButtonSwitchProto\x12\x45\n\x0f\x46orcedLanguages\x18\xc9\x06 \x01(\x0b\x32+.enterprise_management.ForcedLanguagesProto\x12]\n\x1bLockIconInAddressBarEnabled\x18\xdf\x06 \x01(\x0b\x32\x37.enterprise_management.LockIconInAddressBarEnabledProto\x12\x87\x01\n0GetDisplayMediaSetSelectAllScreensAllowedForUrls\x18\xce\x07 \x01(\x0b\x32L.enterprise_management.GetDisplayMediaSetSelectAllScreensAllowedForUrlsProto\x12G\n\x10\x45ventPathEnabled\x18\xe0\x07 \x01(\x0b\x32,.enterprise_management.EventPathEnabledProto\x12Q\n\x15\x44nsOverHttpsTemplates\x18\x84\x05 \x01(\x0b\x32\x31.enterprise_management.DnsOverHttpsTemplatesProto\x12S\n\x16SmartLockSigninAllowed\x18\xea\x03 \x01(\x0b\x32\x32.enterprise_management.SmartLockSigninAllowedProto\x12S\n\x16\x41utoOpenAllowedForURLs\x18\xc5\x05 \x01(\x0b\x32\x32.enterprise_management.AutoOpenAllowedForURLsProto\x12m\n#ExtensionInstallEventLoggingEnabled\x18\xd9\x05 \x01(\x0b\x32?.enterprise_management.ExtensionInstallEventLoggingEnabledProto\x12U\n\x17SuggestedContentEnabled\x18\xd8\x05 \x01(\x0b\x32\x33.enterprise_management.SuggestedContentEnabledProto\x12H\n\x11PolicyRefreshRate\x18: \x01(\x0b\x32-.enterprise_management.PolicyRefreshRateProto\x12[\n\x1a\x44\x65skAPIThirdPartyAllowlist\x18\x81\x08 \x01(\x0b\x32\x36.enterprise_management.DeskAPIThirdPartyAllowlistProto\x12X\n\x19IncognitoModeAvailability\x18_ \x01(\x0b\x32\x35.enterprise_management.IncognitoModeAvailabilityProto\x12_\n\x1cRendererCodeIntegrityEnabled\x18\xd8\x04 \x01(\x0b\x32\x38.enterprise_management.RendererCodeIntegrityEnabledProto\x12\x45\n\x0fNTPCardsVisible\x18\xa7\x06 \x01(\x0b\x32+.enterprise_management.NTPCardsVisibleProto\x12\x63\n\x1e\x41\x64sSettingForIntrusiveAdsSites\x18\x9b\x03 \x01(\x0b\x32:.enterprise_management.AdsSettingForIntrusiveAdsSitesProto\x12Y\n\x19\x41\x64vancedProtectionAllowed\x18\xaf\x05 \x01(\x0b\x32\x35.enterprise_management.AdvancedProtectionAllowedProto\x12u\n\'UrlKeyedAnonymizedDataCollectionEnabled\x18\xcf\x03 \x01(\x0b\x32\x43.enterprise_management.UrlKeyedAnonymizedDataCollectionEnabledProto\x12S\n\x16\x41llowDinosaurEasterEgg\x18\xb7\x02 \x01(\x0b\x32\x32.enterprise_management.AllowDinosaurEasterEggProto\x12\x8d\x01\n3CoalesceH2ConnectionsWithClientCertificatesForHosts\x18\xd4\x03 \x01(\x0b\x32O.enterprise_management.CoalesceH2ConnectionsWithClientCertificatesForHostsProto\x12L\n\x13\x43learSiteDataOnExit\x18\x43 \x01(\x0b\x32/.enterprise_management.ClearSiteDataOnExitProto\x12U\n\x17\x46orceMaximizeOnFirstRun\x18\xac\x02 \x01(\x0b\x32\x33.enterprise_management.ForceMaximizeOnFirstRunProto\x12U\n\x17\x41lwaysOpenPdfExternally\x18\xdd\x02 \x01(\x0b\x32\x33.enterprise_management.AlwaysOpenPdfExternallyProto\x12I\n\x11\x43hromeAppsEnabled\x18\xfe\x06 \x01(\x0b\x32-.enterprise_management.ChromeAppsEnabledProto\x12O\n\x14RelaunchNotification\x18\xa5\x03 \x01(\x0b\x32\x30.enterprise_management.RelaunchNotificationProto\x12^\n\x1cSavingBrowserHistoryDisabled\x18\r \x01(\x0b\x32\x38.enterprise_management.SavingBrowserHistoryDisabledProto\x12_\n\x1cNTPContentSuggestionsEnabled\x18\xd4\x02 \x01(\x0b\x32\x38.enterprise_management.NTPContentSuggestionsEnabledProto\x12]\n\x1bVariationsRestrictParameter\x18\xc6\x01 \x01(\x0b\x32\x37.enterprise_management.VariationsRestrictParameterProto\x12u\n\'FetchKeepaliveDurationSecondsOnShutdown\x18\xbd\x06 \x01(\x0b\x32\x43.enterprise_management.FetchKeepaliveDurationSecondsOnShutdownProto\x12O\n\x14\x41ppCacheForceEnabled\x18\xc2\x05 \x01(\x0b\x32\x30.enterprise_management.AppCacheForceEnabledProto\x12_\n\x1cSecurityTokenSessionBehavior\x18\xa1\x06 \x01(\x0b\x32\x38.enterprise_management.SecurityTokenSessionBehaviorProto\x12\x44\n\x0f\x44isabledSchemes\x18W \x01(\x0b\x32+.enterprise_management.DisabledSchemesProto\x12{\n*CrossOriginWebAssemblyModuleSharingEnabled\x18\xf0\x06 \x01(\x0b\x32\x46.enterprise_management.CrossOriginWebAssemblyModuleSharingEnabledProto\x12\x42\n\x0eInstantEnabled\x18@ \x01(\x0b\x32*.enterprise_management.InstantEnabledProto\x12u\n\'PolicyDictionaryMultipleSourceMergeList\x18\xb7\x04 \x01(\x0b\x32\x43.enterprise_management.PolicyDictionaryMultipleSourceMergeListProto\x12o\n$PromptOnMultipleMatchingCertificates\x18\x8b\x07 \x01(\x0b\x32@.enterprise_management.PromptOnMultipleMatchingCertificatesProto\x12S\n\x16\x43hromeRootStoreEnabled\x18\xe2\x07 \x01(\x0b\x32\x32.enterprise_management.ChromeRootStoreEnabledProto\x12]\n\x1b\x41llowPopupsDuringPageUnload\x18\x97\x04 \x01(\x0b\x32\x37.enterprise_management.AllowPopupsDuringPageUnloadProto\x12W\n\x18QuickUnlockModeWhitelist\x18\xe2\x02 \x01(\x0b\x32\x34.enterprise_management.QuickUnlockModeWhitelistProto\x12M\n\x13\x41udioSandboxEnabled\x18\xf5\x04 \x01(\x0b\x32/.enterprise_management.AudioSandboxEnabledProto\x12?\n\x0cURLAllowlist\x18\xe3\x05 \x01(\x0b\x32(.enterprise_management.URLAllowlistProto\x12X\n\x19\x44isabledPluginsExceptions\x18Q \x01(\x0b\x32\x35.enterprise_management.DisabledPluginsExceptionsProto\x12\x81\x01\n-WebAuthenticationRemoteProxiedRequestsAllowed\x18\xc7\x07 \x01(\x0b\x32I.enterprise_management.WebAuthenticationRemoteProxiedRequestsAllowedProto\x12_\n\x1cNetworkServiceSandboxEnabled\x18\x8f\x07 \x01(\x0b\x32\x38.enterprise_management.NetworkServiceSandboxEnabledProto\x12]\n\x1bSpellcheckLanguageBlacklist\x18\x9a\x04 \x01(\x0b\x32\x37.enterprise_management.SpellcheckLanguageBlacklistProto\x12\x7f\n,InsecurePrivateNetworkRequestsAllowedForUrls\x18\x81\x06 \x01(\x0b\x32H.enterprise_management.InsecurePrivateNetworkRequestsAllowedForUrlsProto\x12W\n\x18LoadCryptoTokenExtension\x18\xef\x07 \x01(\x0b\x32\x34.enterprise_management.LoadCryptoTokenExtensionProto\x12U\n\x17VideoCaptureAllowedUrls\x18\xd3\x01 \x01(\x0b\x32\x33.enterprise_management.VideoCaptureAllowedUrlsProto\x12S\n\x16SchedulerConfiguration\x18\x8c\x04 \x01(\x0b\x32\x32.enterprise_management.SchedulerConfigurationProto\x12Q\n\x15WPADQuickCheckEnabled\x18\x87\x02 \x01(\x0b\x32\x31.enterprise_management.WPADQuickCheckEnabledProto\x12U\n\x17SSLErrorOverrideAllowed\x18\xae\x02 \x01(\x0b\x32\x33.enterprise_management.SSLErrorOverrideAllowedProto\x12\x61\n\x1d\x43hromeCleanupReportingEnabled\x18\xbc\x03 \x01(\x0b\x32\x39.enterprise_management.ChromeCleanupReportingEnabledProto\x12i\n!SSLErrorOverrideAllowedForOrigins\x18\xb5\x06 \x01(\x0b\x32=.enterprise_management.SSLErrorOverrideAllowedForOriginsProto\x12\x42\n\x0eGCFUserDataDir\x18Y \x01(\x0b\x32*.enterprise_management.GCFUserDataDirProto\x12k\n\"ContextAwareAccessSignalsAllowlist\x18\xbc\x06 \x01(\x0b\x32>.enterprise_management.ContextAwareAccessSignalsAllowlistProto\x12R\n\x16\x42lockThirdPartyCookies\x18) \x01(\x0b\x32\x32.enterprise_management.BlockThirdPartyCookiesProto\x12]\n\x1bNativePrintersBulkBlacklist\x18\x82\x03 \x01(\x0b\x32\x37.enterprise_management.NativePrintersBulkBlacklistProto\x12w\n(UnmanagedDeviceSignalsConsentFlowEnabled\x18\xeb\x07 \x01(\x0b\x32\x44.enterprise_management.UnmanagedDeviceSignalsConsentFlowEnabledProto\x12O\n\x14PolicyScopeDetection\x18\xdf\x07 \x01(\x0b\x32\x30.enterprise_management.PolicyScopeDetectionProto\x12N\n\x14\x45\x64itBookmarksEnabled\x18U \x01(\x0b\x32\x30.enterprise_management.EditBookmarksEnabledProto\x12?\n\x0cTrashEnabled\x18\xfb\x07 \x01(\x0b\x32(.enterprise_management.TrashEnabledProto\x12\x63\n\x1eLacrosSecondaryProfilesAllowed\x18\xc2\x06 \x01(\x0b\x32:.enterprise_management.LacrosSecondaryProfilesAllowedProto\x12I\n\x11SideSearchEnabled\x18\x8c\x07 \x01(\x0b\x32-.enterprise_management.SideSearchEnabledProto\x12\x41\n\rCECPQ2Enabled\x18\xcb\x06 \x01(\x0b\x32).enterprise_management.CECPQ2EnabledProto\x12\x46\n\x10TranslateEnabled\x18R \x01(\x0b\x32,.enterprise_management.TranslateEnabledProto\x12O\n\x14HSTSPolicyBypassList\x18\xdb\x04 \x01(\x0b\x32\x30.enterprise_management.HSTSPolicyBypassListProto\x12w\n(SamlLockScreenOfflineSigninTimeLimitDays\x18\xc4\x06 \x01(\x0b\x32\x44.enterprise_management.SamlLockScreenOfflineSigninTimeLimitDaysProto\x12}\n+ForceMajorVersionToMinorPositionInUserAgent\x18\xb7\x07 \x01(\x0b\x32G.enterprise_management.ForceMajorVersionToMinorPositionInUserAgentProto\x12U\n\x17\x42rowserGuestModeEnabled\x18\x95\x02 \x01(\x0b\x32\x33.enterprise_management.BrowserGuestModeEnabledProto\x12W\n\x18ShowFullUrlsInAddressBar\x18\xe5\x05 \x01(\x0b\x32\x34.enterprise_management.ShowFullUrlsInAddressBarProto\x12m\n#SecondaryGoogleAccountSigninAllowed\x18\x98\x03 \x01(\x0b\x32?.enterprise_management.SecondaryGoogleAccountSigninAllowedProto\x12\x63\n\x1eIsolatedWebAppInstallForceList\x18\x80\x08 \x01(\x0b\x32:.enterprise_management.IsolatedWebAppInstallForceListProto\x12m\n#SuggestLogoutAfterClosingLastWindow\x18\xd5\x06 \x01(\x0b\x32?.enterprise_management.SuggestLogoutAfterClosingLastWindowProto\x12y\n)DataLeakPreventionClipboardCheckSizeLimit\x18\xef\x06 \x01(\x0b\x32\x45.enterprise_management.DataLeakPreventionClipboardCheckSizeLimitProto\x12\x41\n\rSSLVersionMin\x18\x99\x02 \x01(\x0b\x32).enterprise_management.SSLVersionMinProto\x12o\n$SafeBrowsingForTrustedSourcesEnabled\x18\xf9\x02 \x01(\x0b\x32@.enterprise_management.SafeBrowsingForTrustedSourcesEnabledProto\x12J\n\x12\x42ookmarkBarEnabled\x18T \x01(\x0b\x32..enterprise_management.BookmarkBarEnabledProto\x12\x65\n\x1f\x41\x63\x63\x65ssibilityImageLabelsEnabled\x18\xc1\x05 \x01(\x0b\x32;.enterprise_management.AccessibilityImageLabelsEnabledProto\x12H\n\x11JavascriptEnabled\x18\x0b \x01(\x0b\x32-.enterprise_management.JavascriptEnabledProto\x12\x45\n\x0f\x46\x61stPairEnabled\x18\x92\x07 \x01(\x0b\x32+.enterprise_management.FastPairEnabledProto\x12u\n\'CaptivePortalAuthenticationIgnoresProxy\x18\xa9\x02 \x01(\x0b\x32\x43.enterprise_management.CaptivePortalAuthenticationIgnoresProxyProto\x12\x41\n\rBrowserSignin\x18\xe9\x03 \x01(\x0b\x32).enterprise_management.BrowserSigninProto\x12\x42\n\x0eMediaCacheSize\x18q \x01(\x0b\x32*.enterprise_management.MediaCacheSizeProto\x12\x87\x01\n0ManagedGuestSessionAutoLaunchNotificationReduced\x18\xb2\x05 \x01(\x0b\x32L.enterprise_management.ManagedGuestSessionAutoLaunchNotificationReducedProto\x12\x63\n\x1eSandboxExternalProtocolBlocked\x18\x93\x07 \x01(\x0b\x32:.enterprise_management.SandboxExternalProtocolBlockedProto\x12Y\n\x19ThirdPartyBlockingEnabled\x18\x99\x03 \x01(\x0b\x32\x35.enterprise_management.ThirdPartyBlockingEnabledProto\x12s\n&DisplayCapturePermissionsPolicyEnabled\x18\xf2\x06 \x01(\x0b\x32\x42.enterprise_management.DisplayCapturePermissionsPolicyEnabledProto\x12U\n\x17\x42rowserAddPersonEnabled\x18\x96\x02 \x01(\x0b\x32\x33.enterprise_management.BrowserAddPersonEnabledProto\x12\x65\n\x1fPhoneHubTaskContinuationAllowed\x18\x9f\x06 \x01(\x0b\x32;.enterprise_management.PhoneHubTaskContinuationAllowedProto\x12\x45\n\x0fPhoneHubAllowed\x18\x9d\x06 \x01(\x0b\x32+.enterprise_management.PhoneHubAllowedProto\x12@\n\rDisable3DAPIs\x18\x39 \x01(\x0b\x32).enterprise_management.Disable3DAPIsProto\x12H\n\x11HideWebStorePromo\x18\x62 \x01(\x0b\x32-.enterprise_management.HideWebStorePromoProto\x12{\n*CloudUserPolicyOverridesCloudMachinePolicy\x18\x85\x07 \x01(\x0b\x32\x46.enterprise_management.CloudUserPolicyOverridesCloudMachinePolicyProto\x12\x42\n\x0e\x45nabledPlugins\x18P \x01(\x0b\x32*.enterprise_management.EnabledPluginsProto\x12o\n$AbusiveExperienceInterventionEnforce\x18\x96\x03 \x01(\x0b\x32@.enterprise_management.AbusiveExperienceInterventionEnforceProto\x12S\n\x16HistoryClustersVisible\x18\xa0\x07 \x01(\x0b\x32\x32.enterprise_management.HistoryClustersVisibleProto\x12{\n*SharedArrayBufferUnrestrictedAccessAllowed\x18\xd6\x06 \x01(\x0b\x32\x46.enterprise_management.SharedArrayBufferUnrestrictedAccessAllowedProto\x12?\n\x0cURLBlocklist\x18\xe2\x05 \x01(\x0b\x32(.enterprise_management.URLBlocklistProto\x12Q\n\x15\x42\x61\x63kgroundModeEnabled\x18\x8c\x01 \x01(\x0b\x32\x31.enterprise_management.BackgroundModeEnabledProto\x12q\n%ForceLogoutUnauthenticatedUserEnabled\x18\xa9\x05 \x01(\x0b\x32\x41.enterprise_management.ForceLogoutUnauthenticatedUserEnabledProto\x12\x93\x01\n6CertificateTransparencyEnforcementDisabledForLegacyCas\x18\xb6\x03 \x01(\x0b\x32R.enterprise_management.CertificateTransparencyEnforcementDisabledForLegacyCasProto\x12I\n\x11\x45nableSyncConsent\x18\xc5\x03 \x01(\x0b\x32-.enterprise_management.EnableSyncConsentProto\x12s\n&SuppressDifferentOriginSubframeDialogs\x18\xbf\x06 \x01(\x0b\x32\x42.enterprise_management.SuppressDifferentOriginSubframeDialogsProto\x12\x61\n\x1dWebRtcAllowLegacyTLSProtocols\x18\x95\x06 \x01(\x0b\x32\x39.enterprise_management.WebRtcAllowLegacyTLSProtocolsProto\x12Y\n\x19PromptForDownloadLocation\x18\x8d\x03 \x01(\x0b\x32\x35.enterprise_management.PromptForDownloadLocationProto\x12N\n\x14ImportSavedPasswords\x18g \x01(\x0b\x32\x30.enterprise_management.ImportSavedPasswordsProto\x12_\n\x1cInsecureFormsWarningsEnabled\x18\xee\x05 \x01(\x0b\x32\x38.enterprise_management.InsecureFormsWarningsEnabledProto\x12S\n\x16PromotionalTabsEnabled\x18\xc8\x03 \x01(\x0b\x32\x32.enterprise_management.PromotionalTabsEnabledProto\x12g\n OriginAgentClusterDefaultEnabled\x18\xa7\x07 \x01(\x0b\x32<.enterprise_management.OriginAgentClusterDefaultEnabledProto\x12N\n\x14SearchSuggestEnabled\x18\x08 \x01(\x0b\x32\x30.enterprise_management.SearchSuggestEnabledProto\x12]\n\x1bPacHttpsUrlStrippingEnabled\x18\xce\x02 \x01(\x0b\x32\x37.enterprise_management.PacHttpsUrlStrippingEnabledProto\x12\x61\n\x1d\x45xplicitlyAllowedNetworkPorts\x18\xd3\x06 \x01(\x0b\x32\x39.enterprise_management.ExplicitlyAllowedNetworkPortsProto\x12U\n\x17RestrictSigninToPattern\x18\x95\x01 \x01(\x0b\x32\x33.enterprise_management.RestrictSigninToPatternProto\x12m\n#BrowserLegacyExtensionPointsBlocked\x18\xff\x06 \x01(\x0b\x32?.enterprise_management.BrowserLegacyExtensionPointsBlockedProto\x12W\n\x18SpellCheckServiceEnabled\x18\x99\x01 \x01(\x0b\x32\x34.enterprise_management.SpellCheckServiceEnabledProto\x12\x45\n\x0fTabUnderAllowed\x18\xb2\x03 \x01(\x0b\x32+.enterprise_management.TabUnderAllowedProto\x12_\n\x1c\x42\x61tterySaverModeAvailability\x18\xf3\x07 \x01(\x0b\x32\x38.enterprise_management.BatterySaverModeAvailabilityProto\x12k\n\"OnBulkDataEntryEnterpriseConnector\x18\xbb\x05 \x01(\x0b\x32>.enterprise_management.OnBulkDataEntryEnterpriseConnectorProto\x12\x41\n\rLacrosAllowed\x18\x9b\x06 \x01(\x0b\x32).enterprise_management.LacrosAllowedProto\x12k\n\"DataLeakPreventionReportingEnabled\x18\xda\x06 \x01(\x0b\x32>.enterprise_management.DataLeakPreventionReportingEnabledProto\x12W\n\x18\x41llowNativeNotifications\x18\xa8\x05 \x01(\x0b\x32\x34.enterprise_management.AllowNativeNotificationsProto\x12>\n\x0cURLWhitelist\x18j \x01(\x0b\x32(.enterprise_management.URLWhitelistProto\x12\x7f\n,ExternalProtocolDialogShowAlwaysOpenCheckbox\x18\xfa\x04 \x01(\x0b\x32H.enterprise_management.ExternalProtocolDialogShowAlwaysOpenCheckboxProto\x12[\n\x1aRelaunchNotificationPeriod\x18\xa6\x03 \x01(\x0b\x32\x36.enterprise_management.RelaunchNotificationPeriodProto\x12g\n LookalikeWarningAllowlistDomains\x18\x90\x06 \x01(\x0b\x32<.enterprise_management.LookalikeWarningAllowlistDomainsProto\x12i\n!NoteTakingAppsLockScreenAllowlist\x18\xf9\x05 \x01(\x0b\x32=.enterprise_management.NoteTakingAppsLockScreenAllowlistProto\x12\x43\n\x0eSitePerProcess\x18\x91\x03 \x01(\x0b\x32*.enterprise_management.SitePerProcessProto\x12Y\n\x19\x42ruschettaVMConfiguration\x18\x8b\x08 \x01(\x0b\x32\x35.enterprise_management.BruschettaVMConfigurationProto\x12_\n\x1c\x44NSInterceptionChecksEnabled\x18\x90\x05 \x01(\x0b\x32\x38.enterprise_management.DNSInterceptionChecksEnabledProto\x12W\n\x18\x44\x65sktopSharingHubEnabled\x18\xe9\x06 \x01(\x0b\x32\x34.enterprise_management.DesktopSharingHubEnabledProto\x12_\n\x1c\x41\x63\x63\x65ssCodeCastDeviceDuration\x18\x8e\x07 \x01(\x0b\x32\x38.enterprise_management.AccessCodeCastDeviceDurationProto\x12i\n!DeviceAttributesAllowedForOrigins\x18\xe3\x06 \x01(\x0b\x32=.enterprise_management.DeviceAttributesAllowedForOriginsProto\x12q\n%EnterpriseAuthenticationAppLinkPolicy\x18\xd2\x07 \x01(\x0b\x32\x41.enterprise_management.EnterpriseAuthenticationAppLinkPolicyProto\x12Q\n\x15UseLegacyFormControls\x18\xad\x05 \x01(\x0b\x32\x31.enterprise_management.UseLegacyFormControlsProto\x12o\n$TLS13HardeningForLocalAnchorsEnabled\x18\xf4\x04 \x01(\x0b\x32@.enterprise_management.TLS13HardeningForLocalAnchorsEnabledProto\x12=\n\x0bQuicAllowed\x18\xaf\x02 \x01(\x0b\x32\'.enterprise_management.QuicAllowedProto\x12K\n\x12\x43orsMitigationList\x18\xf7\x04 \x01(\x0b\x32..enterprise_management.CorsMitigationListProto\x12\x45\n\x0fUserDisplayName\x18\xab\x01 \x01(\x0b\x32+.enterprise_management.UserDisplayNameProto\x12\x65\n\x1fWebRtcEventLogCollectionAllowed\x18\xd2\x03 \x01(\x0b\x32;.enterprise_management.WebRtcEventLogCollectionAllowedProto\x12G\n\x10WebRtcIPHandling\x18\xcd\x06 \x01(\x0b\x32,.enterprise_management.WebRtcIPHandlingProto\x12\x81\x01\n-KeepFullscreenWithoutNotificationUrlAllowList\x18\xa4\x07 \x01(\x0b\x32I.enterprise_management.KeepFullscreenWithoutNotificationUrlAllowListProto\x12[\n\x1a\x46loatingWorkspaceV2Enabled\x18\x91\x08 \x01(\x0b\x32\x36.enterprise_management.FloatingWorkspaceV2EnabledProto\x12\x44\n\x0f\x41utoFillEnabled\x18\x14 \x01(\x0b\x32+.enterprise_management.AutoFillEnabledProto\x12K\n\x12\x43lickToCallEnabled\x18\x87\x05 \x01(\x0b\x32..enterprise_management.ClickToCallEnabledProto\x12Y\n\x19SignedHTTPExchangeEnabled\x18\xa0\x04 \x01(\x0b\x32\x35.enterprise_management.SignedHTTPExchangeEnabledProto\x12\x41\n\rSSLVersionMax\x18\xeb\x02 \x01(\x0b\x32).enterprise_management.SSLVersionMaxProto\x12K\n\x12\x41udioOutputAllowed\x18\xa1\x01 \x01(\x0b\x32..enterprise_management.AudioOutputAllowedProto\x12U\n\x17\x43ontextualSearchEnabled\x18\x9b\x02 \x01(\x0b\x32\x33.enterprise_management.ContextualSearchEnabledProto\x12X\n\x19\x44isableSSLRecordSplitting\x18x \x01(\x0b\x32\x35.enterprise_management.DisableSSLRecordSplittingProto\x12W\n\x18NetworkPredictionOptions\x18\x93\x02 \x01(\x0b\x32\x34.enterprise_management.NetworkPredictionOptionsProto\x12\x42\n\x0eImportHomepage\x18\x65 \x01(\x0b\x32*.enterprise_management.ImportHomepageProto\x12\x63\n\x1e\x45nterpriseRealTimeUrlCheckMode\x18\xda\x05 \x01(\x0b\x32:.enterprise_management.EnterpriseRealTimeUrlCheckModeProto\x12I\n\x11SpellcheckEnabled\x18\x9a\x03 \x01(\x0b\x32-.enterprise_management.SpellcheckEnabledProto\x12\x45\n\x0f\x41llowScreenLock\x18\xcb\x02 \x01(\x0b\x32+.enterprise_management.AllowScreenLockProto\x12\x61\n\x1dWelcomePageOnOSUpgradeEnabled\x18\xb1\x02 \x01(\x0b\x32\x39.enterprise_management.WelcomePageOnOSUpgradeEnabledProto\x12Y\n\x19\x45nableSha1ForLocalAnchors\x18\xd6\x02 \x01(\x0b\x32\x35.enterprise_management.EnableSha1ForLocalAnchorsProto\x12\x41\n\rSigninAllowed\x18\xc0\x01 \x01(\x0b\x32).enterprise_management.SigninAllowedProto\x12]\n\x1b\x41llowDeletingBrowserHistory\x18\xbd\x01 \x01(\x0b\x32\x37.enterprise_management.AllowDeletingBrowserHistoryProto\x12L\n\x13\x41uthServerWhitelist\x18\x1f \x01(\x0b\x32/.enterprise_management.AuthServerWhitelistProto\x12I\n\x11TermsOfServiceURL\x18\xbc\x01 \x01(\x0b\x32-.enterprise_management.TermsOfServiceURLProto\x12i\n!OnFileAttachedEnterpriseConnector\x18\xb7\x05 \x01(\x0b\x32=.enterprise_management.OnFileAttachedEnterpriseConnectorProto\x12g\n ChromeOsMultiProfileUserBehavior\x18\xf6\x01 \x01(\x0b\x32<.enterprise_management.ChromeOsMultiProfileUserBehaviorProto\x12U\n\x17SafeSitesFilterBehavior\x18\xc9\x03 \x01(\x0b\x32\x33.enterprise_management.SafeSitesFilterBehaviorProto\x12]\n\x1bSpellcheckLanguageBlocklist\x18\xef\x05 \x01(\x0b\x32\x37.enterprise_management.SpellcheckLanguageBlocklistProto\x12R\n\x16\x45nterpriseWebStoreName\x18s \x01(\x0b\x32\x32.enterprise_management.EnterpriseWebStoreNameProto\x12]\n\x1b\x41llowSyncXHRInPageDismissal\x18\xde\x04 \x01(\x0b\x32\x37.enterprise_management.AllowSyncXHRInPageDismissalProto\x12R\n\x16\x41lwaysAuthorizePlugins\x18X \x01(\x0b\x32\x32.enterprise_management.AlwaysAuthorizePluginsProto\x12\x7f\n,OverrideSecurityRestrictionsOnInsecureOrigin\x18\xcb\x03 \x01(\x0b\x32H.enterprise_management.OverrideSecurityRestrictionsOnInsecureOriginProto\x12K\n\x12GhostWindowEnabled\x18\x84\x07 \x01(\x0b\x32..enterprise_management.GhostWindowEnabledProto\x12I\n\x11TosDialogBehavior\x18\xa3\x06 \x01(\x0b\x32-.enterprise_management.TosDialogBehaviorProto\x12@\n\rImportHistory\x18\x64 \x01(\x0b\x32).enterprise_management.ImportHistoryProto\x12_\n\x1cRoamingProfileSupportEnabled\x18\xe8\x02 \x01(\x0b\x32\x38.enterprise_management.RoamingProfileSupportEnabledProto\x12w\n(GaiaLockScreenOfflineSigninTimeLimitDays\x18\xc3\x06 \x01(\x0b\x32\x44.enterprise_management.GaiaLockScreenOfflineSigninTimeLimitDaysProto\x12_\n\x1c\x43loudProfileReportingEnabled\x18\xb0\x07 \x01(\x0b\x32\x38.enterprise_management.CloudProfileReportingEnabledProto\x12K\n\x12\x46ullRestoreEnabled\x18\x83\x07 \x01(\x0b\x32..enterprise_management.FullRestoreEnabledProto\x12H\n\x11\x44ownloadDirectory\x18\x42 \x01(\x0b\x32-.enterprise_management.DownloadDirectoryProto\x12G\n\x10\x44nsOverHttpsMode\x18\xc8\x04 \x01(\x0b\x32,.enterprise_management.DnsOverHttpsModeProto\x12y\n)DefaultSearchProviderSuggestURLPostParams\x18\xe9\x01 \x01(\x0b\x32\x45.enterprise_management.DefaultSearchProviderSuggestURLPostParamsProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderIconURL\x18\x30 \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderIconURLProto\x12\x63\n\x1e\x44\x65\x66\x61ultSearchProviderNewTabURL\x18\xef\x01 \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderNewTabURLProto\x12X\n\x19\x44\x65\x66\x61ultSearchProviderName\x18+ \x01(\x0b\x32\x35.enterprise_management.DefaultSearchProviderNameProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderKeyword\x18, \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderKeywordProto\x12\x64\n\x1f\x44\x65\x66\x61ultSearchProviderInstantURL\x18/ \x01(\x0b\x32;.enterprise_management.DefaultSearchProviderInstantURLProto\x12\x61\n\x1d\x44\x65\x66\x61ultSearchProviderImageURL\x18\xe7\x01 \x01(\x0b\x32\x39.enterprise_management.DefaultSearchProviderImageURLProto\x12u\n\'DefaultSearchProviderImageURLPostParams\x18\xeb\x01 \x01(\x0b\x32\x43.enterprise_management.DefaultSearchProviderImageURLPostParamsProto\x12\x64\n\x1f\x44\x65\x66\x61ultSearchProviderSuggestURL\x18. \x01(\x0b\x32;.enterprise_management.DefaultSearchProviderSuggestURLProto\x12\x83\x01\n.DefaultSearchProviderSearchTermsReplacementKey\x18\xad\x01 \x01(\x0b\x32J.enterprise_management.DefaultSearchProviderSearchTermsReplacementKeyProto\x12^\n\x1c\x44\x65\x66\x61ultSearchProviderEnabled\x18* \x01(\x0b\x32\x38.enterprise_management.DefaultSearchProviderEnabledProto\x12y\n)DefaultSearchProviderInstantURLPostParams\x18\xea\x01 \x01(\x0b\x32\x45.enterprise_management.DefaultSearchProviderInstantURLPostParamsProto\x12\x62\n\x1e\x44\x65\x66\x61ultSearchProviderEncodings\x18\x31 \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderEncodingsProto\x12\x62\n\x1e\x44\x65\x66\x61ultSearchProviderSearchURL\x18- \x01(\x0b\x32:.enterprise_management.DefaultSearchProviderSearchURLProto\x12k\n\"DefaultSearchProviderAlternateURLs\x18\xa3\x01 \x01(\x0b\x32>.enterprise_management.DefaultSearchProviderAlternateURLsProto\x12w\n(DefaultSearchProviderSearchURLPostParams\x18\xe8\x01 \x01(\x0b\x32\x44.enterprise_management.DefaultSearchProviderSearchURLPostParamsProto\x12S\n\x16RecoveryFactorBehavior\x18\xf8\x07 \x01(\x0b\x32\x32.enterprise_management.RecoveryFactorBehaviorProto\x12Y\n\x19\x41ttestationEnabledForUser\x18\xca\x01 \x01(\x0b\x32\x35.enterprise_management.AttestationEnabledForUserProto\x12\x61\n\x1d\x41ttestationExtensionAllowlist\x18\x93\x06 \x01(\x0b\x32\x39.enterprise_management.AttestationExtensionAllowlistProto\x12T\n\x17\x43hromeFrameContentTypes\x18> \x01(\x0b\x32\x33.enterprise_management.ChromeFrameContentTypesProto\x12W\n\x18NewWindowsInKioskAllowed\x18\xe5\x07 \x01(\x0b\x32\x34.enterprise_management.NewWindowsInKioskAllowedProto\x12\x44\n\x0fProxyServerMode\x18\x18 \x01(\x0b\x32+.enterprise_management.ProxyServerModeProto\x12\x38\n\tProxyMode\x18\x17 \x01(\x0b\x32%.enterprise_management.ProxyModeProto\x12\x44\n\x0fProxyBypassList\x18\x1b \x01(\x0b\x32+.enterprise_management.ProxyBypassListProto\x12<\n\x0bProxyServer\x18\x19 \x01(\x0b\x32\'.enterprise_management.ProxyServerProto\x12<\n\x0bProxyPacUrl\x18\x1a \x01(\x0b\x32\'.enterprise_management.ProxyPacUrlProto\x12U\n\x17\x45xtensionInstallSources\x18\x96\x01 \x01(\x0b\x32\x33.enterprise_management.ExtensionInstallSourcesProto\x12Q\n\x15\x45xtensionAllowedTypes\x18\xaa\x01 \x01(\x0b\x32\x31.enterprise_management.ExtensionAllowedTypesProto\x12Y\n\x19\x45xtensionInstallBlocklist\x18\xe6\x05 \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallBlocklistProto\x12X\n\x19\x45xtensionInstallForcelist\x18$ \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallForcelistProto\x12Y\n\x19\x45xtensionInstallAllowlist\x18\xe4\x05 \x01(\x0b\x32\x35.enterprise_management.ExtensionInstallAllowlistProto\x12\x65\n\x1f\x45xtensionManifestV2Availability\x18\x88\x08 \x01(\x0b\x32;.enterprise_management.ExtensionManifestV2AvailabilityProto\x12\x61\n\x1d\x45xtensionAllowInsecureUpdates\x18\x86\x04 \x01(\x0b\x32\x39.enterprise_management.ExtensionAllowInsecureUpdatesProto\x12I\n\x11\x45xtensionSettings\x18\x98\x02 \x01(\x0b\x32-.enterprise_management.ExtensionSettingsProto\x12U\n\x17\x42lockExternalExtensions\x18\xff\x04 \x01(\x0b\x32\x33.enterprise_management.BlockExternalExtensionsProto\x12G\n\x10KerberosAccounts\x18\xb2\x04 \x01(\x0b\x32,.enterprise_management.KerberosAccountsProto\x12[\n\x1aKerberosDomainAutocomplete\x18\xe9\x07 \x01(\x0b\x32\x36.enterprise_management.KerberosDomainAutocompleteProto\x12\x65\n\x1fKerberosRememberPasswordEnabled\x18\xb0\x04 \x01(\x0b\x32;.enterprise_management.KerberosRememberPasswordEnabledProto\x12[\n\x1aKerberosAddAccountsAllowed\x18\xb1\x04 \x01(\x0b\x32\x36.enterprise_management.KerberosAddAccountsAllowedProto\x12\x45\n\x0fKerberosEnabled\x18\xaf\x04 \x01(\x0b\x32+.enterprise_management.KerberosEnabledProto\x12\x61\n\x1dKerberosCustomPrefilledConfig\x18\xea\x07 \x01(\x0b\x32\x39.enterprise_management.KerberosCustomPrefilledConfigProto\x12_\n\x1cNetBiosShareDiscoveryEnabled\x18\xd5\x03 \x01(\x0b\x32\x38.enterprise_management.NetBiosShareDiscoveryEnabledProto\x12\x63\n\x1eNTLMShareAuthenticationEnabled\x18\xeb\x03 \x01(\x0b\x32:.enterprise_management.NTLMShareAuthenticationEnabledProto\x12W\n\x18NetworkFileSharesAllowed\x18\xd0\x03 \x01(\x0b\x32\x34.enterprise_management.NetworkFileSharesAllowedProto\x12o\n$NetworkFileSharesPreconfiguredShares\x18\xec\x03 \x01(\x0b\x32@.enterprise_management.NetworkFileSharesPreconfiguredSharesProto\x12g\n RequiredClientCertificateForUser\x18\xaa\x05 \x01(\x0b\x32<.enterprise_management.RequiredClientCertificateForUserProto\x12w\n(SamlPasswordExpirationAdvanceWarningDays\x18\xad\x04 \x01(\x0b\x32\x44.enterprise_management.SamlPasswordExpirationAdvanceWarningDaysProto\x12k\n\"SamlInSessionPasswordChangeEnabled\x18\xa3\x04 \x01(\x0b\x32>.enterprise_management.SamlInSessionPasswordChangeEnabledProto\x12i\n!LockScreenReauthenticationEnabled\x18\xd1\x05 \x01(\x0b\x32=.enterprise_management.LockScreenReauthenticationEnabledProto\x12[\n\x1aSAMLOfflineSigninTimeLimit\x18\x80\x02 \x01(\x0b\x32\x36.enterprise_management.SAMLOfflineSigninTimeLimitProto\x12m\n#PasswordProtectionChangePasswordURL\x18\xaa\x03 \x01(\x0b\x32?.enterprise_management.PasswordProtectionChangePasswordURLProto\x12L\n\x13SafeBrowsingEnabled\x18\x10 \x01(\x0b\x32/.enterprise_management.SafeBrowsingEnabledProto\x12o\n$SafeBrowsingExtendedReportingEnabled\x18\xaf\x03 \x01(\x0b\x32@.enterprise_management.SafeBrowsingExtendedReportingEnabledProto\x12_\n\x1cSafeBrowsingAllowlistDomains\x18\xde\x05 \x01(\x0b\x32\x38.enterprise_management.SafeBrowsingAllowlistDomainsProto\x12]\n\x1bPasswordProtectionLoginURLs\x18\xa9\x03 \x01(\x0b\x32\x37.enterprise_management.PasswordProtectionLoginURLsProto\x12g\n PasswordProtectionWarningTrigger\x18\x9d\x03 \x01(\x0b\x32<.enterprise_management.PasswordProtectionWarningTriggerProto\x12]\n\x1bSafeBrowsingProtectionLevel\x18\xae\x05 \x01(\x0b\x32\x37.enterprise_management.SafeBrowsingProtectionLevelProto\x12M\n\x13ReportMachineIDData\x18\xda\x03 \x01(\x0b\x32/.enterprise_management.ReportMachineIDDataProto\x12Q\n\x15\x43loudReportingEnabled\x18\xef\x03 \x01(\x0b\x32\x31.enterprise_management.CloudReportingEnabledProto\x12_\n\x1c\x43loudExtensionRequestEnabled\x18\xe2\x04 \x01(\x0b\x32\x38.enterprise_management.CloudExtensionRequestEnabledProto\x12\x63\n\x1eReportExtensionsAndPluginsData\x18\xf5\x03 \x01(\x0b\x32:.enterprise_management.ReportExtensionsAndPluginsDataProto\x12\x61\n\x1d\x43loudReportingUploadFrequency\x18\xc4\x07 \x01(\x0b\x32\x39.enterprise_management.CloudReportingUploadFrequencyProto\x12G\n\x10ReportUserIDData\x18\xdb\x03 \x01(\x0b\x32,.enterprise_management.ReportUserIDDataProto\x12G\n\x10ReportPolicyData\x18\xd9\x03 \x01(\x0b\x32,.enterprise_management.ReportPolicyDataProto\x12S\n\x16ReportSafeBrowsingData\x18\xf6\x03 \x01(\x0b\x32\x32.enterprise_management.ReportSafeBrowsingDataProto\x12I\n\x11ReportVersionData\x18\xd8\x03 \x01(\x0b\x32-.enterprise_management.ReportVersionDataProto\x12N\n\x14HomepageIsNewTabPage\x18\x04 \x01(\x0b\x32\x30.enterprise_management.HomepageIsNewTabPageProto\x12\x46\n\x10RestoreOnStartup\x18\' \x01(\x0b\x32,.enterprise_management.RestoreOnStartupProto\x12N\n\x14RestoreOnStartupURLs\x18( \x01(\x0b\x32\x30.enterprise_management.RestoreOnStartupURLsProto\x12K\n\x12NewTabPageLocation\x18\xea\x02 \x01(\x0b\x32..enterprise_management.NewTabPageLocationProto\x12\x42\n\x0eShowHomeButton\x18% \x01(\x0b\x32*.enterprise_management.ShowHomeButtonProto\x12\x46\n\x10HomepageLocation\x18\x03 \x01(\x0b\x32,.enterprise_management.HomepageLocationProto\x12\x63\n\x1e\x41rcBackupRestoreServiceEnabled\x18\xc3\x03 \x01(\x0b\x32:.enterprise_management.ArcBackupRestoreServiceEnabledProto\x12_\n\x1c\x41rcAppToWebAppSharingEnabled\x18\xf9\x06 \x01(\x0b\x32\x38.enterprise_management.ArcAppToWebAppSharingEnabledProto\x12g\n ArcAppInstallEventLoggingEnabled\x18\xc1\x03 \x01(\x0b\x32<.enterprise_management.ArcAppInstallEventLoggingEnabledProto\x12U\n\x17\x41rcCertificatesSyncMode\x18\xcc\x02 \x01(\x0b\x32\x33.enterprise_management.ArcCertificatesSyncModeProto\x12U\n\x17\x41rcBackupRestoreEnabled\x18\xd3\x02 \x01(\x0b\x32\x33.enterprise_management.ArcBackupRestoreEnabledProto\x12Y\n\x19\x41rcLocationServiceEnabled\x18\xed\x02 \x01(\x0b\x32\x35.enterprise_management.ArcLocationServiceEnabledProto\x12i\n!AppRecommendationZeroStateEnabled\x18\xb5\x04 \x01(\x0b\x32=.enterprise_management.AppRecommendationZeroStateEnabledProto\x12;\n\nArcEnabled\x18\xbf\x02 \x01(\x0b\x32&.enterprise_management.ArcEnabledProto\x12g\n ArcGoogleLocationServicesEnabled\x18\xc4\x03 \x01(\x0b\x32<.enterprise_management.ArcGoogleLocationServicesEnabledProto\x12\x39\n\tArcPolicy\x18\xc0\x02 \x01(\x0b\x32%.enterprise_management.ArcPolicyProto\x12\x41\n\rDriveDisabled\x18\x8d\x01 \x01(\x0b\x32).enterprise_management.DriveDisabledProto\x12Y\n\x19\x44riveDisabledOverCellular\x18\x8e\x01 \x01(\x0b\x32\x35.enterprise_management.DriveDisabledOverCellularProto\x12o\n$SameOriginTabCaptureAllowedByOrigins\x18\xf6\x06 \x01(\x0b\x32@.enterprise_management.SameOriginTabCaptureAllowedByOriginsProto\x12\x61\n\x1dScreenCaptureAllowedByOrigins\x18\xf3\x06 \x01(\x0b\x32\x39.enterprise_management.ScreenCaptureAllowedByOriginsProto\x12O\n\x14ScreenCaptureAllowed\x18\x9c\x05 \x01(\x0b\x32\x30.enterprise_management.ScreenCaptureAllowedProto\x12\x61\n\x1dWindowCaptureAllowedByOrigins\x18\xf4\x06 \x01(\x0b\x32\x39.enterprise_management.WindowCaptureAllowedByOriginsProto\x12[\n\x1aTabCaptureAllowedByOrigins\x18\xf5\x06 \x01(\x0b\x32\x36.enterprise_management.TabCaptureAllowedByOriginsProto\x12S\n\x16PinUnlockMinimumLength\x18\xe4\x02 \x01(\x0b\x32\x32.enterprise_management.PinUnlockMinimumLengthProto\x12W\n\x18PinUnlockWeakPinsAllowed\x18\xe6\x02 \x01(\x0b\x32\x34.enterprise_management.PinUnlockWeakPinsAllowedProto\x12K\n\x12QuickUnlockTimeout\x18\xe3\x02 \x01(\x0b\x32..enterprise_management.QuickUnlockTimeoutProto\x12W\n\x18QuickUnlockModeAllowlist\x18\x92\x06 \x01(\x0b\x32\x34.enterprise_management.QuickUnlockModeAllowlistProto\x12[\n\x1aPinUnlockAutosubmitEnabled\x18\xd0\x05 \x01(\x0b\x32\x36.enterprise_management.PinUnlockAutosubmitEnabledProto\x12S\n\x16PinUnlockMaximumLength\x18\xe5\x02 \x01(\x0b\x32\x32.enterprise_management.PinUnlockMaximumLengthProto\x12o\n$ProjectorDogfoodForFamilyLinkEnabled\x18\xd6\x07 \x01(\x0b\x32@.enterprise_management.ProjectorDogfoodForFamilyLinkEnabledProto\x12G\n\x10ProjectorEnabled\x18\xa9\x07 \x01(\x0b\x32,.enterprise_management.ProjectorEnabledProto\x12I\n\x11\x45nableMediaRouter\x18\xcf\x02 \x01(\x0b\x32-.enterprise_management.EnableMediaRouterProto\x12Q\n\x15ShowCastIconInToolbar\x18\xec\x02 \x01(\x0b\x32\x31.enterprise_management.ShowCastIconInToolbarProto\x12[\n\x1aMediaRouterCastAllowAllIPs\x18\xb7\x03 \x01(\x0b\x32\x36.enterprise_management.MediaRouterCastAllowAllIPsProto\x12[\n\x1a\x43\x61lendarIntegrationEnabled\x18\xf9\x07 \x01(\x0b\x32\x36.enterprise_management.CalendarIntegrationEnabledProto\x12o\n$DnsOverHttpsTemplatesWithIdentifiers\x18\x8d\x08 \x01(\x0b\x32@.enterprise_management.DnsOverHttpsTemplatesWithIdentifiersProto\x12\x93\x01\n6AccessControlAllowMethodsInCORSPreflightSpecConformant\x18\x86\x08 \x01(\x0b\x32R.enterprise_management.AccessControlAllowMethodsInCORSPreflightSpecConformantProto\x12G\n\x10\x44nsOverHttpsSalt\x18\x8c\x08 \x01(\x0b\x32,.enterprise_management.DnsOverHttpsSaltProto\x12S\n\x16ReportArcStatusEnabled\x18\xdf\x02 \x01(\x0b\x32\x32.enterprise_management.ReportArcStatusEnabledProto\x12\x61\n\x1dNativeMessagingUserLevelHosts\x18\xff\x01 \x01(\x0b\x32\x39.enterprise_management.NativeMessagingUserLevelHostsProto\x12W\n\x18NativeMessagingBlocklist\x18\xea\x05 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingBlocklistProto\x12W\n\x18NativeMessagingAllowlist\x18\xeb\x05 \x01(\x0b\x32\x34.enterprise_management.NativeMessagingAllowlistProto\x12\x63\n\x1eGaiaOfflineSigninTimeLimitDays\x18\xb7\x06 \x01(\x0b\x32:.enterprise_management.GaiaOfflineSigninTimeLimitDaysProto\x12M\n\x13UserPluginVmAllowed\x18\xc3\x05 \x01(\x0b\x32/.enterprise_management.UserPluginVmAllowedProto\x12\x61\n\x1dPluginVmDataCollectionAllowed\x18\xca\x05 \x01(\x0b\x32\x39.enterprise_management.PluginVmDataCollectionAllowedProto\x12\x43\n\x0ePluginVmUserId\x18\xbc\x05 \x01(\x0b\x32*.enterprise_management.PluginVmUserIdProto\x12\x41\n\rPluginVmImage\x18\xfa\x03 \x01(\x0b\x32).enterprise_management.PluginVmImageProto\x12\x61\n\x1dPluginVmRequiredFreeDiskSpace\x18\xd6\x05 \x01(\x0b\x32\x39.enterprise_management.PluginVmRequiredFreeDiskSpaceProto\x12O\n\x14PrivacyScreenEnabled\x18\xa7\x05 \x01(\x0b\x32\x30.enterprise_management.PrivacyScreenEnabledProto\x12\x43\n\x0eUsageTimeLimit\x18\xc2\x03 \x01(\x0b\x32*.enterprise_management.UsageTimeLimitProto\x12Y\n\x19PerAppTimeLimitsAllowlist\x18\xfc\x05 \x01(\x0b\x32\x35.enterprise_management.PerAppTimeLimitsAllowlistProto\x12W\n\x18\x45\x64uCoexistenceToSVersion\x18\x98\x06 \x01(\x0b\x32\x34.enterprise_management.EduCoexistenceToSVersionProto\x12G\n\x10PerAppTimeLimits\x18\x83\x05 \x01(\x0b\x32,.enterprise_management.PerAppTimeLimitsProto\x12S\n\x16ParentAccessCodeConfig\x18\xfd\x03 \x01(\x0b\x32\x32.enterprise_management.ParentAccessCodeConfigProto\x12\\\n\x1b\x43hromeFrameRendererSettings\x18; \x01(\x0b\x32\x37.enterprise_management.ChromeFrameRendererSettingsProto\x12[\n\x1a\x41\x64\x64itionalLaunchParameters\x18\x8f\x01 \x01(\x0b\x32\x36.enterprise_management.AdditionalLaunchParametersProto\x12T\n\x17RenderInChromeFrameList\x18< \x01(\x0b\x32\x33.enterprise_management.RenderInChromeFrameListProto\x12\x46\n\x10RenderInHostList\x18= \x01(\x0b\x32,.enterprise_management.RenderInHostListProto\x12I\n\x11SkipMetadataCheck\x18\xf0\x01 \x01(\x0b\x32-.enterprise_management.SkipMetadataCheckProto\x12i\n!QuickAnswersUnitConversionEnabled\x18\x9a\x07 \x01(\x0b\x32=.enterprise_management.QuickAnswersUnitConversionEnabledProto\x12\x61\n\x1dQuickAnswersDefinitionEnabled\x18\x98\x07 \x01(\x0b\x32\x39.enterprise_management.QuickAnswersDefinitionEnabledProto\x12\x63\n\x1eQuickAnswersTranslationEnabled\x18\x99\x07 \x01(\x0b\x32:.enterprise_management.QuickAnswersTranslationEnabledProto\x12M\n\x13QuickAnswersEnabled\x18\x97\x07 \x01(\x0b\x32/.enterprise_management.QuickAnswersEnabledProto\x12\x61\n\x1d\x43rostiniPortForwardingAllowed\x18\xce\x05 \x01(\x0b\x32\x39.enterprise_management.CrostiniPortForwardingAllowedProto\x12U\n\x17\x43rostiniAnsiblePlaybook\x18\x81\x05 \x01(\x0b\x32\x33.enterprise_management.CrostiniAnsiblePlaybookProto\x12Y\n\x19\x43rostiniRootAccessAllowed\x18\xc2\x04 \x01(\x0b\x32\x35.enterprise_management.CrostiniRootAccessAllowedProto\x12g\n CrostiniArcAdbSideloadingAllowed\x18\xb4\x05 \x01(\x0b\x32<.enterprise_management.CrostiniArcAdbSideloadingAllowedProto\x12W\n\x18SystemTerminalSshAllowed\x18\xd0\x07 \x01(\x0b\x32\x34.enterprise_management.SystemTerminalSshAllowedProto\x12\x61\n\x1d\x43rostiniExportImportUIAllowed\x18\x8d\x04 \x01(\x0b\x32\x39.enterprise_management.CrostiniExportImportUIAllowedProto\x12\x45\n\x0f\x43rostiniAllowed\x18\xe3\x03 \x01(\x0b\x32+.enterprise_management.CrostiniAllowedProto\x12G\n\x10IdleDelayBattery\x18\xb5\x01 \x01(\x0b\x32,.enterprise_management.IdleDelayBatteryProto\x12K\n\x12IdleWarningDelayAC\x18\xc7\x01 \x01(\x0b\x32..enterprise_management.IdleWarningDelayACProto\x12\x43\n\x0eLidCloseAction\x18\xb7\x01 \x01(\x0b\x32*.enterprise_management.LidCloseActionProto\x12[\n\x1aPresentationIdleDelayScale\x18\xba\x01 \x01(\x0b\x32\x36.enterprise_management.PresentationIdleDelayScaleProto\x12Q\n\x15ScreenOffDelayBattery\x18\xb3\x01 \x01(\x0b\x32\x31.enterprise_management.ScreenOffDelayBatteryProto\x12;\n\nIdleAction\x18\xb6\x01 \x01(\x0b\x32&.enterprise_management.IdleActionProto\x12O\n\x14\x41llowScreenWakeLocks\x18\xcd\x01 \x01(\x0b\x32\x30.enterprise_management.AllowScreenWakeLocksProto\x12U\n\x17ScreenBrightnessPercent\x18\xee\x03 \x01(\x0b\x32\x33.enterprise_management.ScreenBrightnessPercentProto\x12G\n\x10ScreenLockDelays\x18\x85\x02 \x01(\x0b\x32,.enterprise_management.ScreenLockDelaysProto\x12\x65\n\x1fPresentationScreenDimDelayScale\x18\xde\x01 \x01(\x0b\x32;.enterprise_management.PresentationScreenDimDelayScaleProto\x12U\n\x17IdleWarningDelayBattery\x18\xc8\x01 \x01(\x0b\x32\x33.enterprise_management.IdleWarningDelayBatteryProto\x12I\n\x11ScreenLockDelayAC\x18\xb0\x01 \x01(\x0b\x32-.enterprise_management.ScreenLockDelayACProto\x12Q\n\x15ScreenDimDelayBattery\x18\xb2\x01 \x01(\x0b\x32\x31.enterprise_management.ScreenDimDelayBatteryProto\x12O\n\x14PowerSmartDimEnabled\x18\xd3\x03 \x01(\x0b\x32\x30.enterprise_management.PowerSmartDimEnabledProto\x12I\n\x11IdleActionBattery\x18\xe0\x01 \x01(\x0b\x32-.enterprise_management.IdleActionBatteryProto\x12=\n\x0bIdleDelayAC\x18\xb1\x01 \x01(\x0b\x32\'.enterprise_management.IdleDelayACProto\x12G\n\x10ScreenDimDelayAC\x18\xae\x01 \x01(\x0b\x32,.enterprise_management.ScreenDimDelayACProto\x12g\n PowerManagementUsesAudioActivity\x18\xb8\x01 \x01(\x0b\x32<.enterprise_management.PowerManagementUsesAudioActivityProto\x12[\n\x1aWaitForInitialUserActivity\x18\xf9\x01 \x01(\x0b\x32\x36.enterprise_management.WaitForInitialUserActivityProto\x12]\n\x1bPowerManagementIdleSettings\x18\x84\x02 \x01(\x0b\x32\x37.enterprise_management.PowerManagementIdleSettingsProto\x12\x65\n\x1fUserActivityScreenDimDelayScale\x18\xd4\x01 \x01(\x0b\x32;.enterprise_management.UserActivityScreenDimDelayScaleProto\x12?\n\x0cIdleActionAC\x18\xe4\x01 \x01(\x0b\x32(.enterprise_management.IdleActionACProto\x12\x43\n\x0e\x41llowWakeLocks\x18\xed\x03 \x01(\x0b\x32*.enterprise_management.AllowWakeLocksProto\x12k\n\"DevicePowerAdaptiveChargingEnabled\x18\xcd\x07 \x01(\x0b\x32>.enterprise_management.DevicePowerAdaptiveChargingEnabledProto\x12S\n\x16ScreenLockDelayBattery\x18\xb4\x01 \x01(\x0b\x32\x32.enterprise_management.ScreenLockDelayBatteryProto\x12G\n\x10ScreenOffDelayAC\x18\xaf\x01 \x01(\x0b\x32,.enterprise_management.ScreenOffDelayACProto\x12g\n PowerManagementUsesVideoActivity\x18\xb9\x01 \x01(\x0b\x32<.enterprise_management.PowerManagementUsesVideoActivityProto\x12h\n!RemoteAccessHostFirewallTraversal\x18\x61 \x01(\x0b\x32=.enterprise_management.RemoteAccessHostFirewallTraversalProto\x12W\n\x18RemoteAccessHostTokenUrl\x18\xa0\x02 \x01(\x0b\x32\x34.enterprise_management.RemoteAccessHostTokenUrlProto\x12k\n\"RemoteAccessHostTokenValidationUrl\x18\xa1\x02 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostTokenValidationUrlProto\x12\x61\n\x1dRemoteAccessHostMatchUsername\x18\x9f\x02 \x01(\x0b\x32\x39.enterprise_management.RemoteAccessHostMatchUsernameProto\x12\x81\x01\n-RemoteAccessHostMaximumSessionDurationMinutes\x18\xb0\x06 \x01(\x0b\x32I.enterprise_management.RemoteAccessHostMaximumSessionDurationMinutesProto\x12\x87\x01\n0RemoteAccessHostAllowUiAccessForRemoteAssistance\x18\xda\x02 \x01(\x0b\x32L.enterprise_management.RemoteAccessHostAllowUiAccessForRemoteAssistanceProto\x12\x81\x01\n-RemoteAccessHostAllowRemoteSupportConnections\x18\x9d\x07 \x01(\x0b\x32I.enterprise_management.RemoteAccessHostAllowRemoteSupportConnectionsProto\x12\x7f\n,RemoteAccessHostAllowRemoteAccessConnections\x18\xae\x06 \x01(\x0b\x32H.enterprise_management.RemoteAccessHostAllowRemoteAccessConnectionsProto\x12s\n&RemoteAccessHostAllowRelayedConnection\x18\x89\x02 \x01(\x0b\x32\x42.enterprise_management.RemoteAccessHostAllowRelayedConnectionProto\x12\x65\n\x1fRemoteAccessHostAllowGnubbyAuth\x18\x83\x02 \x01(\x0b\x32;.enterprise_management.RemoteAccessHostAllowGnubbyAuthProto\x12g\n RemoteAccessHostRequireTwoFactor\x18\x9d\x01 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostRequireTwoFactorProto\x12_\n\x1cRemoteAccessHostClientDomain\x18\xbe\x02 \x01(\x0b\x32\x38.enterprise_management.RemoteAccessHostClientDomainProto\x12_\n\x1cRemoteAccessHostUdpPortRange\x18\x8a\x02 \x01(\x0b\x32\x38.enterprise_management.RemoteAccessHostUdpPortRangeProto\x12i\n!RemoteAccessHostAllowFileTransfer\x18\x98\x04 \x01(\x0b\x32=.enterprise_management.RemoteAccessHostAllowFileTransferProto\x12\x87\x01\n0RemoteAccessHostTokenValidationCertificateIssuer\x18\xa2\x02 \x01(\x0b\x32L.enterprise_management.RemoteAccessHostTokenValidationCertificateIssuerProto\x12[\n\x1aRemoteAccessHostDomainList\x18\xf2\x02 \x01(\x0b\x32\x36.enterprise_management.RemoteAccessHostDomainListProto\x12k\n\"RemoteAccessHostAllowClientPairing\x18\xec\x01 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostAllowClientPairingProto\x12m\n#RemoteAccessHostEnableUserInterface\x18\xa5\x06 \x01(\x0b\x32?.enterprise_management.RemoteAccessHostEnableUserInterfaceProto\x12\x63\n\x1eRemoteAccessHostRequireCurtain\x18\x9f\x01 \x01(\x0b\x32:.enterprise_management.RemoteAccessHostRequireCurtainProto\x12l\n#RemoteAccessClientFirewallTraversal\x18` \x01(\x0b\x32?.enterprise_management.RemoteAccessClientFirewallTraversalProto\x12q\n%RemoteAccessHostDebugOverridePolicies\x18\xa3\x02 \x01(\x0b\x32\x41.enterprise_management.RemoteAccessHostDebugOverridePoliciesProto\x12g\n RemoteAccessHostTalkGadgetPrefix\x18\x9e\x01 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostTalkGadgetPrefixProto\x12g\n RemoteAccessHostClientDomainList\x18\xf3\x02 \x01(\x0b\x32<.enterprise_management.RemoteAccessHostClientDomainListProto\x12k\n\"RemoteAccessHostClipboardSizeBytes\x18\x9c\x07 \x01(\x0b\x32>.enterprise_management.RemoteAccessHostClipboardSizeBytesProto\x12S\n\x16RemoteAccessHostDomain\x18\x9c\x01 \x01(\x0b\x32\x32.enterprise_management.RemoteAccessHostDomainProto\x12V\n\x18\x44\x65\x66\x61ultJavaScriptSetting\x18\x34 \x01(\x0b\x32\x34.enterprise_management.DefaultJavaScriptSettingProto\x12Y\n\x19\x46ileSystemWriteAskForUrls\x18\x8b\x06 \x01(\x0b\x32\x35.enterprise_management.FileSystemWriteAskForUrlsProto\x12N\n\x14ImagesBlockedForUrls\x18H \x01(\x0b\x32\x30.enterprise_management.ImagesBlockedForUrlsProto\x12Y\n\x19\x44\x65\x66\x61ultWebUsbGuardSetting\x18\xb4\x03 \x01(\x0b\x32\x35.enterprise_management.DefaultWebUsbGuardSettingProto\x12_\n\x1cSerialAllowUsbDevicesForUrls\x18\xc8\x06 \x01(\x0b\x32\x38.enterprise_management.SerialAllowUsbDevicesForUrlsProto\x12m\n#LegacySameSiteCookieBehaviorEnabled\x18\xf1\x04 \x01(\x0b\x32?.enterprise_management.LegacySameSiteCookieBehaviorEnabledProto\x12O\n\x14KeygenBlockedForUrls\x18\xbd\x02 \x01(\x0b\x32\x30.enterprise_management.KeygenBlockedForUrlsProto\x12P\n\x15\x44\x65\x66\x61ultCookiesSetting\x18\x32 \x01(\x0b\x32\x31.enterprise_management.DefaultCookiesSettingProto\x12\x61\n\x1d\x44\x65\x66\x61ultInsecureContentSetting\x18\xfb\x04 \x01(\x0b\x32\x39.enterprise_management.DefaultInsecureContentSettingProto\x12G\n\x10WebHidAskForUrls\x18\xb2\x07 \x01(\x0b\x32,.enterprise_management.WebHidAskForUrlsProto\x12U\n\x17\x44\x65\x66\x61ultClipboardSetting\x18\xd9\x07 \x01(\x0b\x32\x33.enterprise_management.DefaultClipboardSettingProto\x12k\n\"DefaultFileSystemWriteGuardSetting\x18\x88\x06 \x01(\x0b\x32>.enterprise_management.DefaultFileSystemWriteGuardSettingProto\x12V\n\x18JavaScriptAllowedForUrls\x18I \x01(\x0b\x32\x34.enterprise_management.JavaScriptAllowedForUrlsProto\x12i\n!DefaultFileSystemReadGuardSetting\x18\x87\x06 \x01(\x0b\x32=.enterprise_management.DefaultFileSystemReadGuardSettingProto\x12O\n\x14SerialBlockedForUrls\x18\xf3\x05 \x01(\x0b\x32\x30.enterprise_management.SerialBlockedForUrlsProto\x12_\n\x1c\x46ileSystemReadBlockedForUrls\x18\x8a\x06 \x01(\x0b\x32\x38.enterprise_management.FileSystemReadBlockedForUrlsProto\x12\\\n\x1bNotificationsBlockedForUrls\x18l \x01(\x0b\x32\x37.enterprise_management.NotificationsBlockedForUrlsProto\x12_\n\x1cJavaScriptJitBlockedForSites\x18\xe7\x06 \x01(\x0b\x32\x38.enterprise_management.JavaScriptJitBlockedForSitesProto\x12\x61\n\x1dInsecureContentAllowedForUrls\x18\xfc\x04 \x01(\x0b\x32\x39.enterprise_management.InsecureContentAllowedForUrlsProto\x12G\n\x10SerialAskForUrls\x18\xf2\x05 \x01(\x0b\x32,.enterprise_management.SerialAskForUrlsProto\x12Y\n\x19WebHidAllowDevicesForUrls\x18\xbc\x07 \x01(\x0b\x32\x35.enterprise_management.WebHidAllowDevicesForUrlsProto\x12G\n\x10WebUsbAskForUrls\x18\xb9\x03 \x01(\x0b\x32,.enterprise_management.WebUsbAskForUrlsProto\x12W\n\x18LocalFontsAllowedForUrls\x18\xd4\x07 \x01(\x0b\x32\x34.enterprise_management.LocalFontsAllowedForUrlsProto\x12[\n\x1a\x46ileHandlingBlockedForUrls\x18\xd1\x06 \x01(\x0b\x32\x36.enterprise_management.FileHandlingBlockedForUrlsProto\x12\\\n\x1bNotificationsAllowedForUrls\x18k \x01(\x0b\x32\x37.enterprise_management.NotificationsAllowedForUrlsProto\x12Q\n\x15\x44\x65\x66\x61ultSensorsSetting\x18\xf4\x05 \x01(\x0b\x32\x31.enterprise_management.DefaultSensorsSettingProto\x12Y\n\x19\x44\x65\x66\x61ultMediaStreamSetting\x18\x97\x01 \x01(\x0b\x32\x35.enterprise_management.DefaultMediaStreamSettingProto\x12Y\n\x19\x44\x65\x66\x61ultWebHidGuardSetting\x18\xb1\x07 \x01(\x0b\x32\x35.enterprise_management.DefaultWebHidGuardSettingProto\x12m\n#PdfLocalFileAccessAllowedForDomains\x18\x90\x08 \x01(\x0b\x32?.enterprise_management.PdfLocalFileAccessAllowedForDomainsProto\x12U\n\x17\x43lipboardBlockedForUrls\x18\xdb\x07 \x01(\x0b\x32\x33.enterprise_management.ClipboardBlockedForUrlsProto\x12Y\n\x19WebUsbAllowDevicesForUrls\x18\xe8\x03 \x01(\x0b\x32\x35.enterprise_management.WebUsbAllowDevicesForUrlsProto\x12\x85\x01\n/FileSystemSyncAccessHandleAsyncInterfaceEnabled\x18\xfe\x07 \x01(\x0b\x32K.enterprise_management.FileSystemSyncAccessHandleAsyncInterfaceEnabledProto\x12O\n\x14KeygenAllowedForUrls\x18\xbc\x02 \x01(\x0b\x32\x30.enterprise_management.KeygenAllowedForUrlsProto\x12N\n\x14PopupsBlockedForUrls\x18N \x01(\x0b\x32\x30.enterprise_management.PopupsBlockedForUrlsProto\x12O\n\x14WebHidBlockedForUrls\x18\xb3\x07 \x01(\x0b\x32\x30.enterprise_management.WebHidBlockedForUrlsProto\x12N\n\x14\x44\x65\x66\x61ultImagesSetting\x18\x33 \x01(\x0b\x32\x30.enterprise_management.DefaultImagesSettingProto\x12\x65\n\x1f\x44\x65\x66\x61ultWebBluetoothGuardSetting\x18\xc2\x02 \x01(\x0b\x32;.enterprise_management.DefaultWebBluetoothGuardSettingProto\x12\x61\n\x1dWindowPlacementBlockedForUrls\x18\xc3\x07 \x01(\x0b\x32\x39.enterprise_management.WindowPlacementBlockedForUrlsProto\x12P\n\x15\x44\x65\x66\x61ultPluginsSetting\x18\x35 \x01(\x0b\x32\x31.enterprise_management.DefaultPluginsSettingProto\x12W\n\x18\x46ileSystemReadAskForUrls\x18\x89\x06 \x01(\x0b\x32\x34.enterprise_management.FileSystemReadAskForUrlsProto\x12\x61\n\x1dInsecureContentBlockedForUrls\x18\xfd\x04 \x01(\x0b\x32\x39.enterprise_management.InsecureContentBlockedForUrlsProto\x12\x65\n\x1f\x44\x65\x66\x61ultFileHandlingGuardSetting\x18\xcf\x06 \x01(\x0b\x32;.enterprise_management.DefaultFileHandlingGuardSettingProto\x12Q\n\x15SensorsAllowedForUrls\x18\xf5\x05 \x01(\x0b\x32\x31.enterprise_management.SensorsAllowedForUrlsProto\x12\x87\x01\n0LegacySameSiteCookieBehaviorEnabledForDomainList\x18\xf2\x04 \x01(\x0b\x32L.enterprise_management.LegacySameSiteCookieBehaviorEnabledForDomainListProto\x12_\n\x1cJavaScriptJitAllowedForSites\x18\xe6\x06 \x01(\x0b\x32\x38.enterprise_management.JavaScriptJitAllowedForSitesProto\x12W\n\x18LocalFontsBlockedForUrls\x18\xd5\x07 \x01(\x0b\x32\x34.enterprise_management.LocalFontsBlockedForUrlsProto\x12N\n\x14\x44\x65\x66\x61ultPopupsSetting\x18\x36 \x01(\x0b\x32\x30.enterprise_management.DefaultPopupsSettingProto\x12O\n\x14WebUsbBlockedForUrls\x18\xba\x03 \x01(\x0b\x32\x30.enterprise_management.WebUsbBlockedForUrlsProto\x12P\n\x15PluginsAllowedForUrls\x18K \x01(\x0b\x32\x31.enterprise_management.PluginsAllowedForUrlsProto\x12P\n\x15PluginsBlockedForUrls\x18L \x01(\x0b\x32\x31.enterprise_management.PluginsBlockedForUrlsProto\x12Q\n\x15SensorsBlockedForUrls\x18\xf6\x05 \x01(\x0b\x32\x31.enterprise_management.SensorsBlockedForUrlsProto\x12[\n\x1aSerialAllowAllPortsForUrls\x18\xc7\x06 \x01(\x0b\x32\x36.enterprise_management.SerialAllowAllPortsForUrlsProto\x12O\n\x14\x44\x65\x66\x61ultKeygenSetting\x18\xbb\x02 \x01(\x0b\x32\x30.enterprise_management.DefaultKeygenSettingProto\x12[\n\x1a\x46ileHandlingAllowedForUrls\x18\xd0\x06 \x01(\x0b\x32\x36.enterprise_management.FileHandlingAllowedForUrlsProto\x12s\n&WebHidAllowDevicesWithHidUsagesForUrls\x18\xbd\x07 \x01(\x0b\x32\x42.enterprise_management.WebHidAllowDevicesWithHidUsagesForUrlsProto\x12^\n\x1c\x41utoSelectCertificateForUrls\x18h \x01(\x0b\x32\x38.enterprise_management.AutoSelectCertificateForUrlsProto\x12W\n\x18\x44\x65\x66\x61ultLocalFontsSetting\x18\xd3\x07 \x01(\x0b\x32\x34.enterprise_management.DefaultLocalFontsSettingProto\x12\x61\n\x1dWindowPlacementAllowedForUrls\x18\xc2\x07 \x01(\x0b\x32\x39.enterprise_management.WindowPlacementAllowedForUrlsProto\x12P\n\x15\x43ookiesBlockedForUrls\x18\x45 \x01(\x0b\x32\x31.enterprise_management.CookiesBlockedForUrlsProto\x12\x61\n\x1d\x44\x65\x66\x61ultWindowPlacementSetting\x18\xb9\x07 \x01(\x0b\x32\x39.enterprise_management.DefaultWindowPlacementSettingProto\x12P\n\x15\x43ookiesAllowedForUrls\x18O \x01(\x0b\x32\x31.enterprise_management.CookiesAllowedForUrlsProto\x12]\n\x1b\x44\x65\x66\x61ultJavaScriptJitSetting\x18\xe5\x06 \x01(\x0b\x32\x37.enterprise_management.DefaultJavaScriptJitSettingProto\x12N\n\x14PopupsAllowedForUrls\x18M \x01(\x0b\x32\x30.enterprise_management.PopupsAllowedForUrlsProto\x12[\n\x1aRegisteredProtocolHandlers\x18\x8e\x02 \x01(\x0b\x32\x36.enterprise_management.RegisteredProtocolHandlersProto\x12V\n\x18JavaScriptBlockedForUrls\x18J \x01(\x0b\x32\x34.enterprise_management.JavaScriptBlockedForUrlsProto\x12\x61\n\x1d\x46ileSystemWriteBlockedForUrls\x18\x8c\x06 \x01(\x0b\x32\x39.enterprise_management.FileSystemWriteBlockedForUrlsProto\x12\\\n\x1b\x44\x65\x66\x61ultNotificationsSetting\x18\x37 \x01(\x0b\x32\x37.enterprise_management.DefaultNotificationsSettingProto\x12Y\n\x19\x44\x65\x66\x61ultSerialGuardSetting\x18\xf1\x05 \x01(\x0b\x32\x35.enterprise_management.DefaultSerialGuardSettingProto\x12X\n\x19\x43ookiesSessionOnlyForUrls\x18\x46 \x01(\x0b\x32\x35.enterprise_management.CookiesSessionOnlyForUrlsProto\x12U\n\x17\x43lipboardAllowedForUrls\x18\xda\x07 \x01(\x0b\x32\x33.enterprise_management.ClipboardAllowedForUrlsProto\x12X\n\x19\x44\x65\x66\x61ultGeolocationSetting\x18\x38 \x01(\x0b\x32\x35.enterprise_management.DefaultGeolocationSettingProto\x12_\n\x1cWebHidAllowAllDevicesForUrls\x18\xbb\x07 \x01(\x0b\x32\x38.enterprise_management.WebHidAllowAllDevicesForUrlsProto\x12N\n\x14ImagesAllowedForUrls\x18G \x01(\x0b\x32\x30.enterprise_management.ImagesAllowedForUrlsProto\x12M\n\x13UserBorealisAllowed\x18\xc1\x06 \x01(\x0b\x32/.enterprise_management.UserBorealisAllowedProto\x12=\n\x0bIdleTimeout\x18\xe4\x07 \x01(\x0b\x32\'.enterprise_management.IdleTimeoutProto\x12K\n\x12IdleTimeoutActions\x18\x8e\x08 \x01(\x0b\x32..enterprise_management.IdleTimeoutActionsProto\x12\x42\n\tsubProto1\x18\x93\x08 \x01(\x0b\x32..enterprise_management.ChromeSettingsSubProto1B/H\x03Z+chromium/policy/enterprise_management_proto') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'chrome_settings_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'H\003Z+chromium/policy/enterprise_management_proto' + _GSSAPILIBRARYNAMEPROTO._serialized_start=81 + _GSSAPILIBRARYNAMEPROTO._serialized_end=194 + _NTLMV2ENABLEDPROTO._serialized_start=196 + _NTLMV2ENABLEDPROTO._serialized_end=301 + _DISABLEAUTHNEGOTIATECNAMELOOKUPPROTO._serialized_start=304 + _DISABLEAUTHNEGOTIATECNAMELOOKUPPROTO._serialized_end=445 + _AUTHSERVERALLOWLISTPROTO._serialized_start=447 + _AUTHSERVERALLOWLISTPROTO._serialized_end=564 + _AUTHSCHEMESPROTO._serialized_start=566 + _AUTHSCHEMESPROTO._serialized_end=667 + _ENABLEAUTHNEGOTIATEPORTPROTO._serialized_start=669 + _ENABLEAUTHNEGOTIATEPORTPROTO._serialized_end=794 + _AUTHANDROIDNEGOTIATEACCOUNTTYPEPROTO._serialized_start=797 + _AUTHANDROIDNEGOTIATEACCOUNTTYPEPROTO._serialized_end=938 + _AUTHNEGOTIATEDELEGATEBYKDCPOLICYPROTO._serialized_start=941 + _AUTHNEGOTIATEDELEGATEBYKDCPOLICYPROTO._serialized_end=1084 + _INTEGRATEDWEBAUTHENTICATIONALLOWEDPROTO._serialized_start=1087 + _INTEGRATEDWEBAUTHENTICATIONALLOWEDPROTO._serialized_end=1234 + _BASICAUTHOVERHTTPENABLEDPROTO._serialized_start=1236 + _BASICAUTHOVERHTTPENABLEDPROTO._serialized_end=1363 + _ALLHTTPAUTHSCHEMESALLOWEDFORORIGINSPROTO._serialized_start=1366 + _ALLHTTPAUTHSCHEMESALLOWEDFORORIGINSPROTO._serialized_end=1550 + _ALLOWCROSSORIGINAUTHPROMPTPROTO._serialized_start=1553 + _ALLOWCROSSORIGINAUTHPROMPTPROTO._serialized_end=1684 + _AUTHNEGOTIATEDELEGATEALLOWLISTPROTO._serialized_start=1687 + _AUTHNEGOTIATEDELEGATEALLOWLISTPROTO._serialized_end=1826 + _FIRSTPARTYSETSENABLEDPROTO._serialized_start=1828 + _FIRSTPARTYSETSENABLEDPROTO._serialized_end=1949 + _FIRSTPARTYSETSOVERRIDESPROTO._serialized_start=1951 + _FIRSTPARTYSETSOVERRIDESPROTO._serialized_end=2076 + _VOICEINTERACTIONCONTEXTENABLEDPROTO._serialized_start=2079 + _VOICEINTERACTIONCONTEXTENABLEDPROTO._serialized_end=2218 + _ASSISTANTONBOARDINGMODEPROTO._serialized_start=2220 + _ASSISTANTONBOARDINGMODEPROTO._serialized_end=2345 + _VOICEINTERACTIONQUICKANSWERSENABLEDPROTO._serialized_start=2348 + _VOICEINTERACTIONQUICKANSWERSENABLEDPROTO._serialized_end=2497 + _VOICEINTERACTIONHOTWORDENABLEDPROTO._serialized_start=2500 + _VOICEINTERACTIONHOTWORDENABLEDPROTO._serialized_end=2639 + _ASSISTANTWEBENABLEDPROTO._serialized_start=2641 + _ASSISTANTWEBENABLEDPROTO._serialized_end=2758 + _ASSISTANTVOICEMATCHENABLEDDURINGOOBEPROTO._serialized_start=2761 + _ASSISTANTVOICEMATCHENABLEDDURINGOOBEPROTO._serialized_end=2912 + _SELECTTOSPEAKENABLEDPROTO._serialized_start=2914 + _SELECTTOSPEAKENABLEDPROTO._serialized_end=3033 + _FLOATINGACCESSIBILITYMENUENABLEDPROTO._serialized_start=3036 + _FLOATINGACCESSIBILITYMENUENABLEDPROTO._serialized_end=3179 + _MONOAUDIOENABLEDPROTO._serialized_start=3181 + _MONOAUDIOENABLEDPROTO._serialized_end=3292 + _HIGHCONTRASTENABLEDPROTO._serialized_start=3294 + _HIGHCONTRASTENABLEDPROTO._serialized_end=3411 + _VIRTUALKEYBOARDFEATURESPROTO._serialized_start=3413 + _VIRTUALKEYBOARDFEATURESPROTO._serialized_end=3538 + _DICTATIONENABLEDPROTO._serialized_start=3540 + _DICTATIONENABLEDPROTO._serialized_end=3651 + _LARGECURSORENABLEDPROTO._serialized_start=3653 + _LARGECURSORENABLEDPROTO._serialized_end=3768 + _KEYBOARDDEFAULTTOFUNCTIONKEYSPROTO._serialized_start=3771 + _KEYBOARDDEFAULTTOFUNCTIONKEYSPROTO._serialized_end=3908 + _SHOWACCESSIBILITYOPTIONSINSYSTEMTRAYMENUPROTO._serialized_start=3911 + _SHOWACCESSIBILITYOPTIONSINSYSTEMTRAYMENUPROTO._serialized_end=4070 + _CURSORHIGHLIGHTENABLEDPROTO._serialized_start=4072 + _CURSORHIGHLIGHTENABLEDPROTO._serialized_end=4195 + _AUTOCLICKENABLEDPROTO._serialized_start=4197 + _AUTOCLICKENABLEDPROTO._serialized_end=4308 + _SPOKENFEEDBACKENABLEDPROTO._serialized_start=4310 + _SPOKENFEEDBACKENABLEDPROTO._serialized_end=4431 + _ENHANCEDNETWORKVOICESINSELECTTOSPEAKALLOWEDPROTO._serialized_start=4434 + _ENHANCEDNETWORKVOICESINSELECTTOSPEAKALLOWEDPROTO._serialized_end=4599 + _VIRTUALKEYBOARDENABLEDPROTO._serialized_start=4601 + _VIRTUALKEYBOARDENABLEDPROTO._serialized_end=4724 + _STICKYKEYSENABLEDPROTO._serialized_start=4726 + _STICKYKEYSENABLEDPROTO._serialized_end=4839 + _ACCESSIBILITYSHORTCUTSENABLEDPROTO._serialized_start=4842 + _ACCESSIBILITYSHORTCUTSENABLEDPROTO._serialized_end=4979 + _SCREENMAGNIFIERTYPEPROTO._serialized_start=4981 + _SCREENMAGNIFIERTYPEPROTO._serialized_end=5098 + _KEYBOARDFOCUSHIGHLIGHTENABLEDPROTO._serialized_start=5101 + _KEYBOARDFOCUSHIGHLIGHTENABLEDPROTO._serialized_end=5238 + _CARETHIGHLIGHTENABLEDPROTO._serialized_start=5240 + _CARETHIGHLIGHTENABLEDPROTO._serialized_end=5361 + _SUPERVISEDUSERCREATIONENABLEDPROTO._serialized_start=5364 + _SUPERVISEDUSERCREATIONENABLEDPROTO._serialized_end=5501 + _SUPERVISEDUSERCONTENTPROVIDERENABLEDPROTO._serialized_start=5504 + _SUPERVISEDUSERCONTENTPROVIDERENABLEDPROTO._serialized_end=5655 + _PRINTERSBULKCONFIGURATIONPROTO._serialized_start=5658 + _PRINTERSBULKCONFIGURATIONPROTO._serialized_end=5787 + _PRINTINGALLOWEDPINMODESPROTO._serialized_start=5789 + _PRINTINGALLOWEDPINMODESPROTO._serialized_end=5914 + _PRINTJOBHISTORYEXPIRATIONPERIODPROTO._serialized_start=5917 + _PRINTJOBHISTORYEXPIRATIONPERIODPROTO._serialized_end=6058 + _PRINTINGAPIEXTENSIONSALLOWLISTPROTO._serialized_start=6061 + _PRINTINGAPIEXTENSIONSALLOWLISTPROTO._serialized_end=6235 + _PRINTINGALLOWEDCOLORMODESPROTO._serialized_start=6238 + _PRINTINGALLOWEDCOLORMODESPROTO._serialized_end=6367 + _NATIVEPRINTERSBULKACCESSMODEPROTO._serialized_start=6370 + _NATIVEPRINTERSBULKACCESSMODEPROTO._serialized_end=6505 + _CLOUDPRINTPROXYENABLEDPROTO._serialized_start=6507 + _CLOUDPRINTPROXYENABLEDPROTO._serialized_end=6630 + _PRINTHEADERFOOTERPROTO._serialized_start=6632 + _PRINTHEADERFOOTERPROTO._serialized_end=6745 + _PRINTINGSENDUSERNAMEANDFILENAMEENABLEDPROTO._serialized_start=6748 + _PRINTINGSENDUSERNAMEANDFILENAMEENABLEDPROTO._serialized_end=6903 + _DELETEPRINTJOBHISTORYALLOWEDPROTO._serialized_start=6906 + _DELETEPRINTJOBHISTORYALLOWEDPROTO._serialized_end=7041 + _DISABLEPRINTPREVIEWPROTO._serialized_start=7043 + _DISABLEPRINTPREVIEWPROTO._serialized_end=7160 + _PRINTPOSTSCRIPTMODEPROTO._serialized_start=7162 + _PRINTPOSTSCRIPTMODEPROTO._serialized_end=7279 + _PRINTPDFASIMAGEAVAILABILITYPROTO._serialized_start=7282 + _PRINTPDFASIMAGEAVAILABILITYPROTO._serialized_end=7415 + _EXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_start=7418 + _EXTERNALPRINTSERVERSALLOWLISTPROTO._serialized_end=7590 + _EXTERNALPRINTSERVERSPROTO._serialized_start=7592 + _EXTERNALPRINTSERVERSPROTO._serialized_end=7711 + _PRINTERSBULKBLOCKLISTPROTO._serialized_start=7714 + _PRINTERSBULKBLOCKLISTPROTO._serialized_end=7870 + _PRINTINGPAPERSIZEDEFAULTPROTO._serialized_start=7872 + _PRINTINGPAPERSIZEDEFAULTPROTO._serialized_end=7999 + _NATIVEPRINTERSBULKCONFIGURATIONPROTO._serialized_start=8002 + _NATIVEPRINTERSBULKCONFIGURATIONPROTO._serialized_end=8143 + _PRINTINGALLOWEDBACKGROUNDGRAPHICSMODESPROTO._serialized_start=8146 + _PRINTINGALLOWEDBACKGROUNDGRAPHICSMODESPROTO._serialized_end=8301 + _PRINTERSBULKALLOWLISTPROTO._serialized_start=8304 + _PRINTERSBULKALLOWLISTPROTO._serialized_end=8460 + _PRINTINGALLOWEDDUPLEXMODESPROTO._serialized_start=8463 + _PRINTINGALLOWEDDUPLEXMODESPROTO._serialized_end=8594 + _PRINTINGDUPLEXDEFAULTPROTO._serialized_start=8596 + _PRINTINGDUPLEXDEFAULTPROTO._serialized_end=8717 + _PRINTINGPINDEFAULTPROTO._serialized_start=8719 + _PRINTINGPINDEFAULTPROTO._serialized_end=8834 + _PRINTERSBULKACCESSMODEPROTO._serialized_start=8836 + _PRINTERSBULKACCESSMODEPROTO._serialized_end=8959 + _PRINTRASTERIZEPDFDPIPROTO._serialized_start=8961 + _PRINTRASTERIZEPDFDPIPROTO._serialized_end=9080 + _PRINTPREVIEWUSESYSTEMDEFAULTPRINTERPROTO._serialized_start=9083 + _PRINTPREVIEWUSESYSTEMDEFAULTPRINTERPROTO._serialized_end=9232 + _PRINTINGMAXSHEETSALLOWEDPROTO._serialized_start=9234 + _PRINTINGMAXSHEETSALLOWEDPROTO._serialized_end=9361 + _USERPRINTERSALLOWEDPROTO._serialized_start=9363 + _USERPRINTERSALLOWEDPROTO._serialized_end=9480 + _PRINTINGBACKGROUNDGRAPHICSDEFAULTPROTO._serialized_start=9483 + _PRINTINGBACKGROUNDGRAPHICSDEFAULTPROTO._serialized_end=9628 + _PRINTPDFASIMAGEDEFAULTPROTO._serialized_start=9630 + _PRINTPDFASIMAGEDEFAULTPROTO._serialized_end=9753 + _DEFAULTPRINTERSELECTIONPROTO._serialized_start=9755 + _DEFAULTPRINTERSELECTIONPROTO._serialized_end=9880 + _CLOUDPRINTSUBMITENABLEDPROTO._serialized_start=9882 + _CLOUDPRINTSUBMITENABLEDPROTO._serialized_end=10007 + _PRINTERTYPEDENYLISTPROTO._serialized_start=10010 + _PRINTERTYPEDENYLISTPROTO._serialized_end=10162 + _PRINTINGENABLEDPROTO._serialized_start=10164 + _PRINTINGENABLEDPROTO._serialized_end=10273 + _NATIVEPRINTERSPROTO._serialized_start=10276 + _NATIVEPRINTERSPROTO._serialized_end=10418 + _PRINTINGCOLORDEFAULTPROTO._serialized_start=10420 + _PRINTINGCOLORDEFAULTPROTO._serialized_end=10539 + _PRINTERSPROTO._serialized_start=10542 + _PRINTERSPROTO._serialized_end=10672 + _USERNATIVEPRINTERSALLOWEDPROTO._serialized_start=10675 + _USERNATIVEPRINTERSALLOWEDPROTO._serialized_end=10804 + _CLOUDPRINTWARNINGSSUPPRESSEDPROTO._serialized_start=10807 + _CLOUDPRINTWARNINGSSUPPRESSEDPROTO._serialized_end=10942 + _PRINTRASTERIZATIONMODEPROTO._serialized_start=10944 + _PRINTRASTERIZATIONMODEPROTO._serialized_end=11067 + _PASSWORDDISMISSCOMPROMISEDALERTENABLEDPROTO._serialized_start=11070 + _PASSWORDDISMISSCOMPROMISEDALERTENABLEDPROTO._serialized_end=11225 + _PASSWORDLEAKDETECTIONENABLEDPROTO._serialized_start=11228 + _PASSWORDLEAKDETECTIONENABLEDPROTO._serialized_end=11363 + _PASSWORDMANAGERENABLEDPROTO._serialized_start=11365 + _PASSWORDMANAGERENABLEDPROTO._serialized_end=11488 + _PASSWORDMANAGERALLOWSHOWPASSWORDSPROTO._serialized_start=11491 + _PASSWORDMANAGERALLOWSHOWPASSWORDSPROTO._serialized_end=11636 + _CASTRECEIVERENABLEDPROTO._serialized_start=11638 + _CASTRECEIVERENABLEDPROTO._serialized_end=11755 + _BROWSERSWITCHEREXTERNALSITELISTURLPROTO._serialized_start=11758 + _BROWSERSWITCHEREXTERNALSITELISTURLPROTO._serialized_end=11905 + _BROWSERSWITCHEREXTERNALGREYLISTURLPROTO._serialized_start=11908 + _BROWSERSWITCHEREXTERNALGREYLISTURLPROTO._serialized_end=12055 + _BROWSERSWITCHERCHROMEPARAMETERSPROTO._serialized_start=12058 + _BROWSERSWITCHERCHROMEPARAMETERSPROTO._serialized_end=12234 + _BROWSERSWITCHERUSEIESITELISTPROTO._serialized_start=12237 + _BROWSERSWITCHERUSEIESITELISTPROTO._serialized_end=12372 + _BROWSERSWITCHERDELAYPROTO._serialized_start=12374 + _BROWSERSWITCHERDELAYPROTO._serialized_end=12493 + _BROWSERSWITCHERENABLEDPROTO._serialized_start=12495 + _BROWSERSWITCHERENABLEDPROTO._serialized_end=12618 + _ALTERNATIVEBROWSERPATHPROTO._serialized_start=12620 + _ALTERNATIVEBROWSERPATHPROTO._serialized_end=12743 + _BROWSERSWITCHERURLLISTPROTO._serialized_start=12746 + _BROWSERSWITCHERURLLISTPROTO._serialized_end=12904 + _ALTERNATIVEBROWSERPARAMETERSPROTO._serialized_start=12907 + _ALTERNATIVEBROWSERPARAMETERSPROTO._serialized_end=13077 + _BROWSERSWITCHERURLGREYLISTPROTO._serialized_start=13080 + _BROWSERSWITCHERURLGREYLISTPROTO._serialized_end=13246 + _BROWSERSWITCHERPARSINGMODEPROTO._serialized_start=13249 + _BROWSERSWITCHERPARSINGMODEPROTO._serialized_end=13380 + _BROWSERSWITCHERKEEPLASTCHROMETABPROTO._serialized_start=13383 + _BROWSERSWITCHERKEEPLASTCHROMETABPROTO._serialized_end=13526 + _BROWSERSWITCHERCHROMEPATHPROTO._serialized_start=13529 + _BROWSERSWITCHERCHROMEPATHPROTO._serialized_end=13658 + _ISOLATEORIGINSPROTO._serialized_start=13660 + _ISOLATEORIGINSPROTO._serialized_end=13767 + _FORCEGOOGLESAFESEARCHPROTO._serialized_start=13769 + _FORCEGOOGLESAFESEARCHPROTO._serialized_end=13890 + _LOGINDISPLAYPASSWORDBUTTONENABLEDPROTO._serialized_start=13893 + _LOGINDISPLAYPASSWORDBUTTONENABLEDPROTO._serialized_end=14038 + _SECONDARYGOOGLEACCOUNTUSAGEPROTO._serialized_start=14041 + _SECONDARYGOOGLEACCOUNTUSAGEPROTO._serialized_end=14174 + _ENCRYPTEDCLIENTHELLOENABLEDPROTO._serialized_start=14177 + _ENCRYPTEDCLIENTHELLOENABLEDPROTO._serialized_end=14310 + _SSLVERSIONFALLBACKMINPROTO._serialized_start=14312 + _SSLVERSIONFALLBACKMINPROTO._serialized_end=14433 + _NEARBYSHAREALLOWEDPROTO._serialized_start=14435 + _NEARBYSHAREALLOWEDPROTO._serialized_end=14550 + _DOWNLOADBUBBLEENABLEDPROTO._serialized_start=14552 + _DOWNLOADBUBBLEENABLEDPROTO._serialized_end=14673 + _DEFAULTSEARCHPROVIDERCONTEXTMENUACCESSALLOWEDPROTO._serialized_start=14676 + _DEFAULTSEARCHPROVIDERCONTEXTMENUACCESSALLOWEDPROTO._serialized_end=14845 + _IMPORTSEARCHENGINEPROTO._serialized_start=14847 + _IMPORTSEARCHENGINEPROTO._serialized_end=14962 + _SYSTEMFEATURESDISABLEMODEPROTO._serialized_start=14965 + _SYSTEMFEATURESDISABLEMODEPROTO._serialized_end=15094 + _ADVANCEDPROTECTIONDEEPSCANNINGENABLEDPROTO._serialized_start=15097 + _ADVANCEDPROTECTIONDEEPSCANNINGENABLEDPROTO._serialized_end=15250 + _TOUCHVIRTUALKEYBOARDENABLEDPROTO._serialized_start=15253 + _TOUCHVIRTUALKEYBOARDENABLEDPROTO._serialized_end=15386 + _SAFEBROWSINGWHITELISTDOMAINSPROTO._serialized_start=15389 + _SAFEBROWSINGWHITELISTDOMAINSPROTO._serialized_end=15559 + _ALLOWSYSTEMNOTIFICATIONSPROTO._serialized_start=15561 + _ALLOWSYSTEMNOTIFICATIONSPROTO._serialized_end=15688 + _AUTOOPENFILETYPESPROTO._serialized_start=15691 + _AUTOOPENFILETYPESPROTO._serialized_end=15839 + _POLICYATOMICGROUPSENABLEDPROTO._serialized_start=15842 + _POLICYATOMICGROUPSENABLEDPROTO._serialized_end=15971 + _EXTENSIONINSTALLWHITELISTPROTO._serialized_start=15974 + _EXTENSIONINSTALLWHITELISTPROTO._serialized_end=16138 + _CACERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_start=16141 + _CACERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_end=16280 + _FULLSCREENALLOWEDPROTO._serialized_start=16282 + _FULLSCREENALLOWEDPROTO._serialized_end=16395 + _ENTERPRISEHARDWAREPLATFORMAPIENABLEDPROTO._serialized_start=16398 + _ENTERPRISEHARDWAREPLATFORMAPIENABLEDPROTO._serialized_end=16549 + _LACROSDATABACKWARDMIGRATIONMODEPROTO._serialized_start=16552 + _LACROSDATABACKWARDMIGRATIONMODEPROTO._serialized_end=16693 + _SYNCDISABLEDPROTO._serialized_start=16695 + _SYNCDISABLEDPROTO._serialized_end=16798 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORURLSPROTO._serialized_start=16801 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORURLSPROTO._serialized_end=17013 + _HTTPSONLYMODEPROTO._serialized_start=17015 + _HTTPSONLYMODEPROTO._serialized_end=17120 + _LENSREGIONSEARCHENABLEDPROTO._serialized_start=17122 + _LENSREGIONSEARCHENABLEDPROTO._serialized_end=17247 + _REQUIREONLINEREVOCATIONCHECKSFORLOCALANCHORSPROTO._serialized_start=17250 + _REQUIREONLINEREVOCATIONCHECKSFORLOCALANCHORSPROTO._serialized_end=17417 + _SUPPRESSCHROMEFRAMETURNDOWNPROMPTPROTO._serialized_start=17420 + _SUPPRESSCHROMEFRAMETURNDOWNPROMPTPROTO._serialized_end=17565 + _VMMANAGEMENTCLIALLOWEDPROTO._serialized_start=17567 + _VMMANAGEMENTCLIALLOWEDPROTO._serialized_end=17690 + _DESKTEMPLATESENABLEDPROTO._serialized_start=17692 + _DESKTEMPLATESENABLEDPROTO._serialized_end=17811 + _IMPORTBOOKMARKSPROTO._serialized_start=17813 + _IMPORTBOOKMARKSPROTO._serialized_end=17922 + _ALLOWCHROMEDATAINBACKUPSPROTO._serialized_start=17924 + _ALLOWCHROMEDATAINBACKUPSPROTO._serialized_end=18051 + _ALLOWEDDOMAINSFORAPPSPROTO._serialized_start=18053 + _ALLOWEDDOMAINSFORAPPSPROTO._serialized_end=18174 + _SESSIONLOCALESPROTO._serialized_start=18177 + _SESSIONLOCALESPROTO._serialized_end=18319 + _ALLOWWEBAUTHNWITHBROKENTLSCERTSPROTO._serialized_start=18322 + _ALLOWWEBAUTHNWITHBROKENTLSCERTSPROTO._serialized_end=18463 + _STARTUPBROWSERWINDOWLAUNCHSUPPRESSEDPROTO._serialized_start=18466 + _STARTUPBROWSERWINDOWLAUNCHSUPPRESSEDPROTO._serialized_end=18617 + _SYSTEMFEATURESDISABLELISTPROTO._serialized_start=18620 + _SYSTEMFEATURESDISABLELISTPROTO._serialized_end=18784 + _FORCENETWORKINPROCESSPROTO._serialized_start=18786 + _FORCENETWORKINPROCESSPROTO._serialized_end=18907 + _FORCEBROWSERSIGNINPROTO._serialized_start=18909 + _FORCEBROWSERSIGNINPROTO._serialized_end=19024 + _MEDIARECOMMENDATIONSENABLEDPROTO._serialized_start=19027 + _MEDIARECOMMENDATIONSENABLEDPROTO._serialized_end=19160 + _CLOUDPOLICYOVERRIDESPLATFORMPOLICYPROTO._serialized_start=19163 + _CLOUDPOLICYOVERRIDESPLATFORMPOLICYPROTO._serialized_end=19310 + _PHONEHUBNOTIFICATIONSALLOWEDPROTO._serialized_start=19313 + _PHONEHUBNOTIFICATIONSALLOWEDPROTO._serialized_end=19448 + _MACHINELEVELUSERCLOUDPOLICYENROLLMENTTOKENPROTO._serialized_start=19451 + _MACHINELEVELUSERCLOUDPOLICYENROLLMENTTOKENPROTO._serialized_end=19614 + _CLEARBROWSINGDATAONEXITLISTPROTO._serialized_start=19617 + _CLEARBROWSINGDATAONEXITLISTPROTO._serialized_end=19785 + _VIRTUALKEYBOARDRESIZESLAYOUTBYDEFAULTPROTO._serialized_start=19788 + _VIRTUALKEYBOARDRESIZESLAYOUTBYDEFAULTPROTO._serialized_end=19941 + _SHELFAUTOHIDEBEHAVIORPROTO._serialized_start=19943 + _SHELFAUTOHIDEBEHAVIORPROTO._serialized_end=20064 + _TABDISCARDINGEXCEPTIONSPROTO._serialized_start=20067 + _TABDISCARDINGEXCEPTIONSPROTO._serialized_end=20227 + _INSECUREPRIVATENETWORKREQUESTSALLOWEDPROTO._serialized_start=20230 + _INSECUREPRIVATENETWORKREQUESTSALLOWEDPROTO._serialized_end=20383 + _CLOUDMANAGEMENTENROLLMENTTOKENPROTO._serialized_start=20386 + _CLOUDMANAGEMENTENROLLMENTTOKENPROTO._serialized_end=20525 + _LACROSAVAILABILITYPROTO._serialized_start=20527 + _LACROSAVAILABILITYPROTO._serialized_end=20642 + _PERSISTENTQUOTAENABLEDPROTO._serialized_start=20644 + _PERSISTENTQUOTAENABLEDPROTO._serialized_end=20767 + _DISABLEPLUGINFINDERPROTO._serialized_start=20769 + _DISABLEPLUGINFINDERPROTO._serialized_end=20886 + _ALLOWOUTDATEDPLUGINSPROTO._serialized_start=20888 + _ALLOWOUTDATEDPLUGINSPROTO._serialized_end=21007 + _PRECONFIGUREDDESKTEMPLATESPROTO._serialized_start=21010 + _PRECONFIGUREDDESKTEMPLATESPROTO._serialized_end=21141 + _METRICSREPORTINGENABLEDPROTO._serialized_start=21143 + _METRICSREPORTINGENABLEDPROTO._serialized_end=21268 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORCASPROTO._serialized_start=21271 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORCASPROTO._serialized_end=21481 + _LOCALDISCOVERYENABLEDPROTO._serialized_start=21483 + _LOCALDISCOVERYENABLEDPROTO._serialized_end=21604 + _DISABLESAFEBROWSINGPROCEEDANYWAYPROTO._serialized_start=21607 + _DISABLESAFEBROWSINGPROCEEDANYWAYPROTO._serialized_end=21750 + _ALLOWEDINPUTMETHODSPROTO._serialized_start=21753 + _ALLOWEDINPUTMETHODSPROTO._serialized_end=21905 + _WEBAPPINSTALLFORCELISTPROTO._serialized_start=21907 + _WEBAPPINSTALLFORCELISTPROTO._serialized_end=22030 + _U2FSECURITYKEYAPIENABLEDPROTO._serialized_start=22032 + _U2FSECURITYKEYAPIENABLEDPROTO._serialized_end=22159 + _HIGHEFFICIENCYMODEENABLEDPROTO._serialized_start=22162 + _HIGHEFFICIENCYMODEENABLEDPROTO._serialized_end=22291 + _PRINTINGAPIEXTENSIONSWHITELISTPROTO._serialized_start=22294 + _PRINTINGAPIEXTENSIONSWHITELISTPROTO._serialized_end=22468 + _SMSMESSAGESALLOWEDPROTO._serialized_start=22470 + _SMSMESSAGESALLOWEDPROTO._serialized_end=22585 + _PROFILEPICKERONSTARTUPAVAILABILITYPROTO._serialized_start=22588 + _PROFILEPICKERONSTARTUPAVAILABILITYPROTO._serialized_end=22735 + _RELAUNCHWINDOWPROTO._serialized_start=22737 + _RELAUNCHWINDOWPROTO._serialized_end=22844 + _FORCESAFESEARCHPROTO._serialized_start=22846 + _FORCESAFESEARCHPROTO._serialized_end=22955 + _DISABLESCREENSHOTSPROTO._serialized_start=22957 + _DISABLESCREENSHOTSPROTO._serialized_end=23072 + _DEVELOPERTOOLSDISABLEDPROTO._serialized_start=23074 + _DEVELOPERTOOLSDISABLEDPROTO._serialized_end=23197 + _AUTOPLAYALLOWLISTPROTO._serialized_start=23200 + _AUTOPLAYALLOWLISTPROTO._serialized_end=23348 + _BROWSERLABSENABLEDPROTO._serialized_start=23350 + _BROWSERLABSENABLEDPROTO._serialized_end=23465 + _REPORTCROSTINIUSAGEENABLEDPROTO._serialized_start=23468 + _REPORTCROSTINIUSAGEENABLEDPROTO._serialized_end=23599 + _NATIVEMESSAGINGBLACKLISTPROTO._serialized_start=23602 + _NATIVEMESSAGINGBLACKLISTPROTO._serialized_end=23764 + _AUTOFILLADDRESSENABLEDPROTO._serialized_start=23766 + _AUTOFILLADDRESSENABLEDPROTO._serialized_end=23889 + _FULLSCREENALERTENABLEDPROTO._serialized_start=23891 + _FULLSCREENALERTENABLEDPROTO._serialized_end=24014 + _HIDEWEBSTOREICONPROTO._serialized_start=24016 + _HIDEWEBSTOREICONPROTO._serialized_end=24127 + _SECURITYKEYPERMITATTESTATIONPROTO._serialized_start=24130 + _SECURITYKEYPERMITATTESTATIONPROTO._serialized_end=24300 + _ONFILEDOWNLOADEDENTERPRISECONNECTORPROTO._serialized_start=24303 + _ONFILEDOWNLOADEDENTERPRISECONNECTORPROTO._serialized_end=24452 + _CCTTOSDIALOGENABLEDPROTO._serialized_start=24454 + _CCTTOSDIALOGENABLEDPROTO._serialized_end=24571 + _INTRANETREDIRECTBEHAVIORPROTO._serialized_start=24573 + _INTRANETREDIRECTBEHAVIORPROTO._serialized_end=24700 + _PHONEHUBCAMERAROLLALLOWEDPROTO._serialized_start=24703 + _PHONEHUBCAMERAROLLALLOWEDPROTO._serialized_end=24832 + _MANAGEDCONFIGURATIONPERORIGINPROTO._serialized_start=24835 + _MANAGEDCONFIGURATIONPERORIGINPROTO._serialized_end=24972 + _USERDATASNAPSHOTRETENTIONLIMITPROTO._serialized_start=24975 + _USERDATASNAPSHOTRETENTIONLIMITPROTO._serialized_end=25114 + _DESKAPITHIRDPARTYACCESSENABLEDPROTO._serialized_start=25117 + _DESKAPITHIRDPARTYACCESSENABLEDPROTO._serialized_end=25256 + _CORSNONWILDCARDREQUESTHEADERSSUPPORTPROTO._serialized_start=25259 + _CORSNONWILDCARDREQUESTHEADERSSUPPORTPROTO._serialized_end=25410 + _BROWSERTHEMECOLORPROTO._serialized_start=25412 + _BROWSERTHEMECOLORPROTO._serialized_end=25525 + _NOTETAKINGAPPSLOCKSCREENWHITELISTPROTO._serialized_start=25528 + _NOTETAKINGAPPSLOCKSCREENWHITELISTPROTO._serialized_end=25708 + _LOCKSCREENMEDIAPLAYBACKENABLEDPROTO._serialized_start=25711 + _LOCKSCREENMEDIAPLAYBACKENABLEDPROTO._serialized_end=25850 + _TOTALMEMORYLIMITMBPROTO._serialized_start=25852 + _TOTALMEMORYLIMITMBPROTO._serialized_end=25967 + _ONPRINTENTERPRISECONNECTORPROTO._serialized_start=25970 + _ONPRINTENTERPRISECONNECTORPROTO._serialized_end=26101 + _RELAUNCHHEADSUPPERIODPROTO._serialized_start=26103 + _RELAUNCHHEADSUPPERIODPROTO._serialized_end=26224 + _WEBSQLACCESSPROTO._serialized_start=26226 + _WEBSQLACCESSPROTO._serialized_end=26329 + _MANAGEDBOOKMARKSPROTO._serialized_start=26331 + _MANAGEDBOOKMARKSPROTO._serialized_end=26442 + _DEVELOPERTOOLSAVAILABILITYPROTO._serialized_start=26445 + _DEVELOPERTOOLSAVAILABILITYPROTO._serialized_end=26576 + _SUPPRESSUNSUPPORTEDOSWARNINGPROTO._serialized_start=26579 + _SUPPRESSUNSUPPORTEDOSWARNINGPROTO._serialized_end=26714 + _DEFAULTHANDLERSFORFILEEXTENSIONSPROTO._serialized_start=26717 + _DEFAULTHANDLERSFORFILEEXTENSIONSPROTO._serialized_end=26860 + _WARNBEFOREQUITTINGENABLEDPROTO._serialized_start=26863 + _WARNBEFOREQUITTINGENABLEDPROTO._serialized_end=26992 + _ONSECURITYEVENTENTERPRISECONNECTORPROTO._serialized_start=26995 + _ONSECURITYEVENTENTERPRISECONNECTORPROTO._serialized_end=27142 + _STRICTMIMETYPECHECKFORWORKERSCRIPTSENABLEDPROTO._serialized_start=27145 + _STRICTMIMETYPECHECKFORWORKERSCRIPTSENABLEDPROTO._serialized_end=27308 + _MANAGEDACCOUNTSSIGNINRESTRICTIONPROTO._serialized_start=27311 + _MANAGEDACCOUNTSSIGNINRESTRICTIONPROTO._serialized_end=27454 + _REMOTEDEBUGGINGALLOWEDPROTO._serialized_start=27456 + _REMOTEDEBUGGINGALLOWEDPROTO._serialized_end=27579 + _CONTEXTUALSUGGESTIONSENABLEDPROTO._serialized_start=27582 + _CONTEXTUALSUGGESTIONSENABLEDPROTO._serialized_end=27717 + _VPNCONFIGALLOWEDPROTO._serialized_start=27719 + _VPNCONFIGALLOWEDPROTO._serialized_end=27830 + _WEBRTCUDPPORTRANGEPROTO._serialized_start=27832 + _WEBRTCUDPPORTRANGEPROTO._serialized_end=27947 + _EXTERNALPRINTSERVERSWHITELISTPROTO._serialized_start=27950 + _EXTERNALPRINTSERVERSWHITELISTPROTO._serialized_end=28122 + _DISKCACHESIZEPROTO._serialized_start=28124 + _DISKCACHESIZEPROTO._serialized_end=28229 + _ALLOWFILESELECTIONDIALOGSPROTO._serialized_start=28232 + _ALLOWFILESELECTIONDIALOGSPROTO._serialized_end=28361 + _AUDIOCAPTUREALLOWEDURLSPROTO._serialized_start=28364 + _AUDIOCAPTUREALLOWEDURLSPROTO._serialized_end=28524 + _FORCEYOUTUBERESTRICTPROTO._serialized_start=28526 + _FORCEYOUTUBERESTRICTPROTO._serialized_end=28645 + _ECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_start=28648 + _ECRYPTFSMIGRATIONSTRATEGYPROTO._serialized_end=28777 + _AUTOLAUNCHPROTOCOLSFROMORIGINSPROTO._serialized_start=28780 + _AUTOLAUNCHPROTOCOLSFROMORIGINSPROTO._serialized_end=28919 + _DISKCACHEDIRPROTO._serialized_start=28921 + _DISKCACHEDIRPROTO._serialized_end=29024 + _ADDITIONALDNSQUERYTYPESENABLEDPROTO._serialized_start=29027 + _ADDITIONALDNSQUERYTYPESENABLEDPROTO._serialized_end=29166 + _ATTESTATIONEXTENSIONWHITELISTPROTO._serialized_start=29169 + _ATTESTATIONEXTENSIONWHITELISTPROTO._serialized_end=29341 + _UNIFIEDDESKTOPENABLEDBYDEFAULTPROTO._serialized_start=29344 + _UNIFIEDDESKTOPENABLEDBYDEFAULTPROTO._serialized_end=29483 + _SENDMOUSEEVENTSDISABLEDFORMCONTROLSENABLEDPROTO._serialized_start=29486 + _SENDMOUSEEVENTSDISABLEDFORMCONTROLSENABLEDPROTO._serialized_end=29649 + _SPELLCHECKLANGUAGEPROTO._serialized_start=29652 + _SPELLCHECKLANGUAGEPROTO._serialized_end=29802 + _DNSPREFETCHINGENABLEDPROTO._serialized_start=29804 + _DNSPREFETCHINGENABLEDPROTO._serialized_end=29925 + _IMPORTAUTOFILLFORMDATAPROTO._serialized_start=29927 + _IMPORTAUTOFILLFORMDATAPROTO._serialized_end=30050 + _USERAGENTREDUCTIONPROTO._serialized_start=30052 + _USERAGENTREDUCTIONPROTO._serialized_end=30167 + _NATIVEWINDOWOCCLUSIONENABLEDPROTO._serialized_start=30170 + _NATIVEWINDOWOCCLUSIONENABLEDPROTO._serialized_end=30305 + _EXTERNALSTORAGEDISABLEDPROTO._serialized_start=30307 + _EXTERNALSTORAGEDISABLEDPROTO._serialized_end=30432 + _ALTERNATEERRORPAGESENABLEDPROTO._serialized_start=30435 + _ALTERNATEERRORPAGESENABLEDPROTO._serialized_end=30566 + _DEFAULTDOWNLOADDIRECTORYPROTO._serialized_start=30568 + _DEFAULTDOWNLOADDIRECTORYPROTO._serialized_end=30695 + _AUTOPLAYALLOWEDPROTO._serialized_start=30697 + _AUTOPLAYALLOWEDPROTO._serialized_end=30806 + _WEBSQLINTHIRDPARTYCONTEXTENABLEDPROTO._serialized_start=30809 + _WEBSQLINTHIRDPARTYCONTEXTENABLEDPROTO._serialized_end=30952 + _DATALEAKPREVENTIONRULESLISTPROTO._serialized_start=30955 + _DATALEAKPREVENTIONRULESLISTPROTO._serialized_end=31088 + _BACKFORWARDCACHEENABLEDPROTO._serialized_start=31090 + _BACKFORWARDCACHEENABLEDPROTO._serialized_end=31215 + _SHOWLOGOUTBUTTONINTRAYPROTO._serialized_start=31217 + _SHOWLOGOUTBUTTONINTRAYPROTO._serialized_end=31340 + _HEADLESSMODEPROTO._serialized_start=31342 + _HEADLESSMODEPROTO._serialized_end=31445 + _PREFIXEDSTORAGEINFOENABLEDPROTO._serialized_start=31448 + _PREFIXEDSTORAGEINFOENABLEDPROTO._serialized_end=31579 + _PERAPPTIMELIMITSWHITELISTPROTO._serialized_start=31582 + _PERAPPTIMELIMITSWHITELISTPROTO._serialized_end=31711 + _NTPCUSTOMBACKGROUNDENABLEDPROTO._serialized_start=31714 + _NTPCUSTOMBACKGROUNDENABLEDPROTO._serialized_end=31845 + _TASKMANAGERENDPROCESSENABLEDPROTO._serialized_start=31848 + _TASKMANAGERENDPROCESSENABLEDPROTO._serialized_end=31983 + _KEYPERMISSIONSPROTO._serialized_start=31985 + _KEYPERMISSIONSPROTO._serialized_end=32092 + _BUILTINDNSCLIENTENABLEDPROTO._serialized_start=32094 + _BUILTINDNSCLIENTENABLEDPROTO._serialized_end=32219 + _STRICTERMIXEDCONTENTTREATMENTENABLEDPROTO._serialized_start=32222 + _STRICTERMIXEDCONTENTTREATMENTENABLEDPROTO._serialized_end=32373 + _TRIPLEDESENABLEDPROTO._serialized_start=32375 + _TRIPLEDESENABLEDPROTO._serialized_end=32486 + _BUILTINCERTIFICATEVERIFIERENABLEDPROTO._serialized_start=32489 + _BUILTINCERTIFICATEVERIFIERENABLEDPROTO._serialized_end=32634 + _ENABLEDEPRECATEDWEBPLATFORMFEATURESPROTO._serialized_start=32637 + _ENABLEDEPRECATEDWEBPLATFORMFEATURESPROTO._serialized_end=32821 + _EXTENSIONINSTALLBLACKLISTPROTO._serialized_start=32824 + _EXTENSIONINSTALLBLACKLISTPROTO._serialized_end=32988 + _DISABLEDPLUGINSPROTO._serialized_start=32991 + _DISABLEDPLUGINSPROTO._serialized_end=33135 + _MAXCONNECTIONSPERPROXYPROTO._serialized_start=33137 + _MAXCONNECTIONSPERPROXYPROTO._serialized_end=33260 + _SECURITYTOKENSESSIONNOTIFICATIONSECONDSPROTO._serialized_start=33263 + _SECURITYTOKENSESSIONNOTIFICATIONSECONDSPROTO._serialized_end=33420 + _THROTTLENONVISIBLECROSSORIGINIFRAMESALLOWEDPROTO._serialized_start=33423 + _THROTTLENONVISIBLECROSSORIGINIFRAMESALLOWEDPROTO._serialized_end=33588 + _HTTP09ONNONDEFAULTPORTSENABLEDPROTO._serialized_start=33591 + _HTTP09ONNONDEFAULTPORTSENABLEDPROTO._serialized_end=33730 + _WEBAPPSETTINGSPROTO._serialized_start=33732 + _WEBAPPSETTINGSPROTO._serialized_end=33839 + _AUDIOPROCESSHIGHPRIORITYENABLEDPROTO._serialized_start=33842 + _AUDIOPROCESSHIGHPRIORITYENABLEDPROTO._serialized_end=33983 + _ENABLESYMANTECLEGACYINFRASTRUCTUREPROTO._serialized_start=33986 + _ENABLESYMANTECLEGACYINFRASTRUCTUREPROTO._serialized_end=34133 + _PINNEDLAUNCHERAPPSPROTO._serialized_start=34136 + _PINNEDLAUNCHERAPPSPROTO._serialized_end=34286 + _SETTIMEOUTWITHOUT1MSCLAMPENABLEDPROTO._serialized_start=34289 + _SETTIMEOUTWITHOUT1MSCLAMPENABLEDPROTO._serialized_end=34432 + _CORSLEGACYMODEENABLEDPROTO._serialized_start=34434 + _CORSLEGACYMODEENABLEDPROTO._serialized_end=34555 + _FLOATINGWORKSPACEENABLEDPROTO._serialized_start=34557 + _FLOATINGWORKSPACEENABLEDPROTO._serialized_end=34684 + _RESTRICTACCOUNTSTOPATTERNSPROTO._serialized_start=34687 + _RESTRICTACCOUNTSTOPATTERNSPROTO._serialized_end=34853 + _ROAMINGPROFILELOCATIONPROTO._serialized_start=34855 + _ROAMINGPROFILELOCATIONPROTO._serialized_end=34978 + _SITEPERPROCESSANDROIDPROTO._serialized_start=34980 + _SITEPERPROCESSANDROIDPROTO._serialized_end=35101 + _APPSTORERATINGENABLEDPROTO._serialized_start=35103 + _APPSTORERATINGENABLEDPROTO._serialized_end=35224 + _USERAGENTCLIENTHINTSENABLEDPROTO._serialized_start=35227 + _USERAGENTCLIENTHINTSENABLEDPROTO._serialized_end=35360 + _RESTRICTEDMANAGEDGUESTSESSIONEXTENSIONCLEANUPEXEMPTLISTPROTO._serialized_start=35363 + _RESTRICTEDMANAGEDGUESTSESSIONEXTENSIONCLEANUPEXEMPTLISTPROTO._serialized_end=35587 + _WEBXRIMMERSIVEARENABLEDPROTO._serialized_start=35589 + _WEBXRIMMERSIVEARENABLEDPROTO._serialized_end=35714 + _DEFAULTBROWSERSETTINGENABLEDPROTO._serialized_start=35717 + _DEFAULTBROWSERSETTINGENABLEDPROTO._serialized_end=35852 + _FORCELEGACYDEFAULTREFERRERPOLICYPROTO._serialized_start=35855 + _FORCELEGACYDEFAULTREFERRERPOLICYPROTO._serialized_end=35998 + _OSCOLORMODEPROTO._serialized_start=36000 + _OSCOLORMODEPROTO._serialized_end=36101 + _FORCEEPHEMERALPROFILESPROTO._serialized_start=36103 + _FORCEEPHEMERALPROFILESPROTO._serialized_end=36226 + _WEBAUTHNFACTORSPROTO._serialized_start=36229 + _WEBAUTHNFACTORSPROTO._serialized_end=36373 + _RENDERERAPPCONTAINERENABLEDPROTO._serialized_start=36376 + _RENDERERAPPCONTAINERENABLEDPROTO._serialized_end=36509 + _DHEENABLEDPROTO._serialized_start=36511 + _DHEENABLEDPROTO._serialized_end=36610 + _ISOLATEORIGINSANDROIDPROTO._serialized_start=36612 + _ISOLATEORIGINSANDROIDPROTO._serialized_end=36733 + _AUTHNEGOTIATEDELEGATEWHITELISTPROTO._serialized_start=36736 + _AUTHNEGOTIATEDELEGATEWHITELISTPROTO._serialized_end=36875 + _DOWNLOADRESTRICTIONSPROTO._serialized_start=36877 + _DOWNLOADRESTRICTIONSPROTO._serialized_end=36996 + _CHROMEOSLOCKONIDLESUSPENDPROTO._serialized_start=36999 + _CHROMEOSLOCKONIDLESUSPENDPROTO._serialized_end=37128 + _SCREENTIMEENABLEDPROTO._serialized_start=37130 + _SCREENTIMEENABLEDPROTO._serialized_end=37243 + _OPTIMIZATIONGUIDEFETCHINGENABLEDPROTO._serialized_start=37246 + _OPTIMIZATIONGUIDEFETCHINGENABLEDPROTO._serialized_end=37389 + _NATIVEPRINTERSBULKWHITELISTPROTO._serialized_start=37392 + _NATIVEPRINTERSBULKWHITELISTPROTO._serialized_end=37560 + _INCOGNITOENABLEDPROTO._serialized_start=37562 + _INCOGNITOENABLEDPROTO._serialized_end=37673 + _ENTERPRISEWEBSTOREURLPROTO._serialized_start=37675 + _ENTERPRISEWEBSTOREURLPROTO._serialized_end=37796 + _WEBSQLNONSECURECONTEXTENABLEDPROTO._serialized_start=37799 + _WEBSQLNONSECURECONTEXTENABLEDPROTO._serialized_end=37936 + _AUTOFILLCREDITCARDENABLEDPROTO._serialized_start=37939 + _AUTOFILLCREDITCARDENABLEDPROTO._serialized_end=38068 + _USERAGENTCLIENTHINTSGREASEUPDATEENABLEDPROTO._serialized_start=38071 + _USERAGENTCLIENTHINTSGREASEUPDATEENABLEDPROTO._serialized_end=38228 + _MAXINVALIDATIONFETCHDELAYPROTO._serialized_start=38231 + _MAXINVALIDATIONFETCHDELAYPROTO._serialized_end=38360 + _USERFEEDBACKALLOWEDPROTO._serialized_start=38362 + _USERFEEDBACKALLOWEDPROTO._serialized_end=38479 + _NTPMIDDLESLOTANNOUNCEMENTVISIBLEPROTO._serialized_start=38482 + _NTPMIDDLESLOTANNOUNCEMENTVISIBLEPROTO._serialized_end=38625 + _COMMANDLINEFLAGSECURITYWARNINGSENABLEDPROTO._serialized_start=38628 + _COMMANDLINEFLAGSECURITYWARNINGSENABLEDPROTO._serialized_end=38783 + _USERDATADIRPROTO._serialized_start=38785 + _USERDATADIRPROTO._serialized_end=38886 + _SIGNININTERCEPTIONENABLEDPROTO._serialized_start=38889 + _SIGNININTERCEPTIONENABLEDPROTO._serialized_end=39018 + _TABFREEZINGENABLEDPROTO._serialized_start=39020 + _TABFREEZINGENABLEDPROTO._serialized_end=39135 + _EASYUNLOCKALLOWEDPROTO._serialized_start=39137 + _EASYUNLOCKALLOWEDPROTO._serialized_end=39250 + _WEBRTCLOCALIPSALLOWEDURLSPROTO._serialized_start=39253 + _WEBRTCLOCALIPSALLOWEDURLSPROTO._serialized_end=39417 + _BROWSERGUESTMODEENFORCEDPROTO._serialized_start=39419 + _BROWSERGUESTMODEENFORCEDPROTO._serialized_end=39546 + _HINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_start=39549 + _HINDIINSCRIPTLAYOUTENABLEDPROTO._serialized_end=39680 + _SHOWAPPSSHORTCUTINBOOKMARKBARPROTO._serialized_start=39683 + _SHOWAPPSSHORTCUTINBOOKMARKBARPROTO._serialized_end=39820 + _UNSAFELYTREATINSECUREORIGINASSECUREPROTO._serialized_start=39823 + _UNSAFELYTREATINSECUREORIGINASSECUREPROTO._serialized_end=40007 + _USERAVATARIMAGEPROTO._serialized_start=40009 + _USERAVATARIMAGEPROTO._serialized_end=40118 + _VIDEOCAPTUREALLOWEDPROTO._serialized_start=40120 + _VIDEOCAPTUREALLOWEDPROTO._serialized_end=40237 + _DISABLESPDYPROTO._serialized_start=40239 + _DISABLESPDYPROTO._serialized_end=40340 + _COMPONENTUPDATESENABLEDPROTO._serialized_start=40342 + _COMPONENTUPDATESENABLEDPROTO._serialized_end=40467 + _NEWBASEURLINHERITANCEBEHAVIORALLOWEDPROTO._serialized_start=40470 + _NEWBASEURLINHERITANCEBEHAVIORALLOWEDPROTO._serialized_end=40621 + _PPAPISHAREDIMAGESSWAPCHAINALLOWEDPROTO._serialized_start=40624 + _PPAPISHAREDIMAGESSWAPCHAINALLOWEDPROTO._serialized_end=40769 + _OPENNETWORKCONFIGURATIONPROTO._serialized_start=40771 + _OPENNETWORKCONFIGURATIONPROTO._serialized_end=40898 + _OFFSETPARENTNEWSPECBEHAVIORENABLEDPROTO._serialized_start=40901 + _OFFSETPARENTNEWSPECBEHAVIORENABLEDPROTO._serialized_end=41048 + _BROWSERNETWORKTIMEQUERIESENABLEDPROTO._serialized_start=41051 + _BROWSERNETWORKTIMEQUERIESENABLEDPROTO._serialized_end=41194 + _ENABLEONLINEREVOCATIONCHECKSPROTO._serialized_start=41197 + _ENABLEONLINEREVOCATIONCHECKSPROTO._serialized_end=41332 + _POLICYLISTMULTIPLESOURCEMERGELISTPROTO._serialized_start=41335 + _POLICYLISTMULTIPLESOURCEMERGELISTPROTO._serialized_end=41515 + _TARGETBLANKIMPLIESNOOPENERPROTO._serialized_start=41518 + _TARGETBLANKIMPLIESNOOPENERPROTO._serialized_end=41649 + _ENABLECOMMONNAMEFALLBACKFORLOCALANCHORSPROTO._serialized_start=41652 + _ENABLECOMMONNAMEFALLBACKFORLOCALANCHORSPROTO._serialized_end=41809 + _SCROLLTOTEXTFRAGMENTENABLEDPROTO._serialized_start=41812 + _SCROLLTOTEXTFRAGMENTENABLEDPROTO._serialized_end=41945 + _URLBLACKLISTPROTO._serialized_start=41948 + _URLBLACKLISTPROTO._serialized_end=42086 + _ONFILETRANSFERENTERPRISECONNECTORPROTO._serialized_start=42089 + _ONFILETRANSFERENTERPRISECONNECTORPROTO._serialized_end=42234 + _CLIENTCERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_start=42237 + _CLIENTCERTIFICATEMANAGEMENTALLOWEDPROTO._serialized_end=42384 + _SHAREDCLIPBOARDENABLEDPROTO._serialized_start=42386 + _SHAREDCLIPBOARDENABLEDPROTO._serialized_end=42509 + _CLOUDUSERPOLICYMERGEPROTO._serialized_start=42511 + _CLOUDUSERPOLICYMERGEPROTO._serialized_end=42630 + _PDFANNOTATIONSENABLEDPROTO._serialized_start=42632 + _PDFANNOTATIONSENABLEDPROTO._serialized_end=42753 + _UNTHROTTLEDNESTEDTIMEOUTENABLEDPROTO._serialized_start=42756 + _UNTHROTTLEDNESTEDTIMEOUTENABLEDPROTO._serialized_end=42897 + _ECHEALLOWEDPROTO._serialized_start=42899 + _ECHEALLOWEDPROTO._serialized_end=43000 + _GLOBALLYSCOPEHTTPAUTHCACHEENABLEDPROTO._serialized_start=43003 + _GLOBALLYSCOPEHTTPAUTHCACHEENABLEDPROTO._serialized_end=43148 + _LENSDESKTOPNTPSEARCHENABLEDPROTO._serialized_start=43151 + _LENSDESKTOPNTPSEARCHENABLEDPROTO._serialized_end=43284 + _ENABLEDEPRECATEDPRIVETPRINTINGPROTO._serialized_start=43287 + _ENABLEDEPRECATEDPRIVETPRINTINGPROTO._serialized_end=43426 + _WALLPAPERIMAGEPROTO._serialized_start=43428 + _WALLPAPERIMAGEPROTO._serialized_end=43535 + _RUNALLFLASHINALLOWMODEPROTO._serialized_start=43537 + _RUNALLFLASHINALLOWMODEPROTO._serialized_end=43660 + _INSIGHTSEXTENSIONENABLEDPROTO._serialized_start=43662 + _INSIGHTSEXTENSIONENABLEDPROTO._serialized_end=43789 + _BROWSINGDATALIFETIMEPROTO._serialized_start=43791 + _BROWSINGDATALIFETIMEPROTO._serialized_end=43910 + _INSTANTTETHERINGALLOWEDPROTO._serialized_start=43912 + _INSTANTTETHERINGALLOWEDPROTO._serialized_end=44037 + _AUTOPLAYWHITELISTPROTO._serialized_start=44040 + _AUTOPLAYWHITELISTPROTO._serialized_end=44188 + _ACCESSCODECASTENABLEDPROTO._serialized_start=44190 + _ACCESSCODECASTENABLEDPROTO._serialized_end=44311 + _ISOLATEDAPPSDEVELOPERMODEALLOWEDPROTO._serialized_start=44314 + _ISOLATEDAPPSDEVELOPERMODEALLOWEDPROTO._serialized_end=44457 + _EMOJISUGGESTIONENABLEDPROTO._serialized_start=44459 + _EMOJISUGGESTIONENABLEDPROTO._serialized_end=44582 + _WEBCOMPONENTSV0ENABLEDPROTO._serialized_start=44584 + _WEBCOMPONENTSV0ENABLEDPROTO._serialized_end=44707 + _SHOPPINGLISTENABLEDPROTO._serialized_start=44709 + _SHOPPINGLISTENABLEDPROTO._serialized_end=44826 + _CLOUDMANAGEMENTENROLLMENTMANDATORYPROTO._serialized_start=44829 + _CLOUDMANAGEMENTENROLLMENTMANDATORYPROTO._serialized_end=44976 + _SHELFALIGNMENTPROTO._serialized_start=44978 + _SHELFALIGNMENTPROTO._serialized_end=45085 + _COPYPREVENTIONSETTINGSPROTO._serialized_start=45087 + _COPYPREVENTIONSETTINGSPROTO._serialized_end=45210 + _WINDOWOCCLUSIONENABLEDPROTO._serialized_start=45212 + _WINDOWOCCLUSIONENABLEDPROTO._serialized_end=45335 + _INTENSIVEWAKEUPTHROTTLINGENABLEDPROTO._serialized_start=45338 + _INTENSIVEWAKEUPTHROTTLINGENABLEDPROTO._serialized_end=45481 + _URLPARAMFILTERENABLEDPROTO._serialized_start=45483 + _URLPARAMFILTERENABLEDPROTO._serialized_end=45604 + _WIFISYNCANDROIDALLOWEDPROTO._serialized_start=45606 + _WIFISYNCANDROIDALLOWEDPROTO._serialized_end=45729 + _DATACOMPRESSIONPROXYENABLEDPROTO._serialized_start=45732 + _DATACOMPRESSIONPROXYENABLEDPROTO._serialized_end=45865 + _SYNCTYPESLISTDISABLEDPROTO._serialized_start=45868 + _SYNCTYPESLISTDISABLEDPROTO._serialized_end=46024 + _FORCEYOUTUBESAFETYMODEPROTO._serialized_start=46026 + _FORCEYOUTUBESAFETYMODEPROTO._serialized_end=46149 + _APPLICATIONLOCALEVALUEPROTO._serialized_start=46151 + _APPLICATIONLOCALEVALUEPROTO._serialized_end=46274 + _DEVICELOCALACCOUNTMANAGEDSESSIONENABLEDPROTO._serialized_start=46277 + _DEVICELOCALACCOUNTMANAGEDSESSIONENABLEDPROTO._serialized_end=46434 + _ENTERPRISEPROFILECREATIONKEEPBROWSINGDATAPROTO._serialized_start=46437 + _ENTERPRISEPROFILECREATIONKEEPBROWSINGDATAPROTO._serialized_end=46598 + _RC4ENABLEDPROTO._serialized_start=46600 + _RC4ENABLEDPROTO._serialized_end=46699 + _USBDETECTORNOTIFICATIONENABLEDPROTO._serialized_start=46702 + _USBDETECTORNOTIFICATIONENABLEDPROTO._serialized_end=46841 + _ALLOWEDLANGUAGESPROTO._serialized_start=46844 + _ALLOWEDLANGUAGESPROTO._serialized_end=46990 + _HARDWAREACCELERATIONMODEENABLEDPROTO._serialized_start=46993 + _HARDWAREACCELERATIONMODEENABLEDPROTO._serialized_end=47134 + _AMBIENTAUTHENTICATIONINPRIVATEMODESENABLEDPROTO._serialized_start=47137 + _AMBIENTAUTHENTICATIONINPRIVATEMODESENABLEDPROTO._serialized_end=47300 + _CHROMECLEANUPENABLEDPROTO._serialized_start=47302 + _CHROMECLEANUPENABLEDPROTO._serialized_end=47421 + _CHROMEVARIATIONSPROTO._serialized_start=47423 + _CHROMEVARIATIONSPROTO._serialized_end=47534 + _PAYMENTMETHODQUERYENABLEDPROTO._serialized_start=47537 + _PAYMENTMETHODQUERYENABLEDPROTO._serialized_end=47666 + _PROXYSETTINGSPROTO._serialized_start=47668 + _PROXYSETTINGSPROTO._serialized_end=47773 + _EXEMPTDOMAINFILETYPEPAIRSFROMFILETYPEDOWNLOADWARNINGSPROTO._serialized_start=47776 + _EXEMPTDOMAINFILETYPEPAIRSFROMFILETYPEDOWNLOADWARNINGSPROTO._serialized_end=47961 + _SAFEBROWSINGEXTENDEDREPORTINGOPTINALLOWEDPROTO._serialized_start=47964 + _SAFEBROWSINGEXTENDEDREPORTINGOPTINALLOWEDPROTO._serialized_end=48125 + _ENABLEEXPERIMENTALPOLICIESPROTO._serialized_start=48128 + _ENABLEEXPERIMENTALPOLICIESPROTO._serialized_end=48294 + _ENABLEDEPRECATEDWEBBASEDSIGNINPROTO._serialized_start=48297 + _ENABLEDEPRECATEDWEBBASEDSIGNINPROTO._serialized_end=48436 + _NATIVEMESSAGINGWHITELISTPROTO._serialized_start=48439 + _NATIVEMESSAGINGWHITELISTPROTO._serialized_end=48601 + _AUDIOCAPTUREALLOWEDPROTO._serialized_start=48603 + _AUDIOCAPTUREALLOWEDPROTO._serialized_end=48720 + _EXTERNALSTORAGEREADONLYPROTO._serialized_start=48722 + _EXTERNALSTORAGEREADONLYPROTO._serialized_end=48847 + _LENSCAMERAASSISTEDSEARCHENABLEDPROTO._serialized_start=48850 + _LENSCAMERAASSISTEDSEARCHENABLEDPROTO._serialized_end=48991 + _WEBDRIVEROVERRIDESINCOMPATIBLEPOLICIESPROTO._serialized_start=48994 + _WEBDRIVEROVERRIDESINCOMPATIBLEPOLICIESPROTO._serialized_end=49149 + _SESSIONLENGTHLIMITPROTO._serialized_start=49151 + _SESSIONLENGTHLIMITPROTO._serialized_end=49266 + _PRIMARYMOUSEBUTTONSWITCHPROTO._serialized_start=49268 + _PRIMARYMOUSEBUTTONSWITCHPROTO._serialized_end=49395 + _FORCEDLANGUAGESPROTO._serialized_start=49398 + _FORCEDLANGUAGESPROTO._serialized_end=49542 + _LOCKICONINADDRESSBARENABLEDPROTO._serialized_start=49545 + _LOCKICONINADDRESSBARENABLEDPROTO._serialized_end=49678 + _GETDISPLAYMEDIASETSELECTALLSCREENSALLOWEDFORURLSPROTO._serialized_start=49681 + _GETDISPLAYMEDIASETSELECTALLSCREENSALLOWEDFORURLSPROTO._serialized_end=49891 + _EVENTPATHENABLEDPROTO._serialized_start=49893 + _EVENTPATHENABLEDPROTO._serialized_end=50004 + _DNSOVERHTTPSTEMPLATESPROTO._serialized_start=50006 + _DNSOVERHTTPSTEMPLATESPROTO._serialized_end=50127 + _SMARTLOCKSIGNINALLOWEDPROTO._serialized_start=50129 + _SMARTLOCKSIGNINALLOWEDPROTO._serialized_end=50252 + _AUTOOPENALLOWEDFORURLSPROTO._serialized_start=50255 + _AUTOOPENALLOWEDFORURLSPROTO._serialized_end=50413 + _EXTENSIONINSTALLEVENTLOGGINGENABLEDPROTO._serialized_start=50416 + _EXTENSIONINSTALLEVENTLOGGINGENABLEDPROTO._serialized_end=50565 + _SUGGESTEDCONTENTENABLEDPROTO._serialized_start=50567 + _SUGGESTEDCONTENTENABLEDPROTO._serialized_end=50692 + _POLICYREFRESHRATEPROTO._serialized_start=50694 + _POLICYREFRESHRATEPROTO._serialized_end=50807 + _DESKAPITHIRDPARTYALLOWLISTPROTO._serialized_start=50810 + _DESKAPITHIRDPARTYALLOWLISTPROTO._serialized_end=50976 + _INCOGNITOMODEAVAILABILITYPROTO._serialized_start=50979 + _INCOGNITOMODEAVAILABILITYPROTO._serialized_end=51108 + _RENDERERCODEINTEGRITYENABLEDPROTO._serialized_start=51111 + _RENDERERCODEINTEGRITYENABLEDPROTO._serialized_end=51246 + _NTPCARDSVISIBLEPROTO._serialized_start=51248 + _NTPCARDSVISIBLEPROTO._serialized_end=51357 + _ADSSETTINGFORINTRUSIVEADSSITESPROTO._serialized_start=51360 + _ADSSETTINGFORINTRUSIVEADSSITESPROTO._serialized_end=51499 + _ADVANCEDPROTECTIONALLOWEDPROTO._serialized_start=51502 + _ADVANCEDPROTECTIONALLOWEDPROTO._serialized_end=51631 + _URLKEYEDANONYMIZEDDATACOLLECTIONENABLEDPROTO._serialized_start=51634 + _URLKEYEDANONYMIZEDDATACOLLECTIONENABLEDPROTO._serialized_end=51791 + _ALLOWDINOSAUREASTEREGGPROTO._serialized_start=51793 + _ALLOWDINOSAUREASTEREGGPROTO._serialized_end=51916 + _COALESCEH2CONNECTIONSWITHCLIENTCERTIFICATESFORHOSTSPROTO._serialized_start=51919 + _COALESCEH2CONNECTIONSWITHCLIENTCERTIFICATESFORHOSTSPROTO._serialized_end=52135 + _CLEARSITEDATAONEXITPROTO._serialized_start=52137 + _CLEARSITEDATAONEXITPROTO._serialized_end=52254 + _FORCEMAXIMIZEONFIRSTRUNPROTO._serialized_start=52256 + _FORCEMAXIMIZEONFIRSTRUNPROTO._serialized_end=52381 + _ALWAYSOPENPDFEXTERNALLYPROTO._serialized_start=52383 + _ALWAYSOPENPDFEXTERNALLYPROTO._serialized_end=52508 + _CHROMEAPPSENABLEDPROTO._serialized_start=52510 + _CHROMEAPPSENABLEDPROTO._serialized_end=52623 + _RELAUNCHNOTIFICATIONPROTO._serialized_start=52625 + _RELAUNCHNOTIFICATIONPROTO._serialized_end=52744 + _SAVINGBROWSERHISTORYDISABLEDPROTO._serialized_start=52747 + _SAVINGBROWSERHISTORYDISABLEDPROTO._serialized_end=52882 + _NTPCONTENTSUGGESTIONSENABLEDPROTO._serialized_start=52885 + _NTPCONTENTSUGGESTIONSENABLEDPROTO._serialized_end=53020 + _VARIATIONSRESTRICTPARAMETERPROTO._serialized_start=53023 + _VARIATIONSRESTRICTPARAMETERPROTO._serialized_end=53156 + _FETCHKEEPALIVEDURATIONSECONDSONSHUTDOWNPROTO._serialized_start=53159 + _FETCHKEEPALIVEDURATIONSECONDSONSHUTDOWNPROTO._serialized_end=53316 + _APPCACHEFORCEENABLEDPROTO._serialized_start=53318 + _APPCACHEFORCEENABLEDPROTO._serialized_end=53437 + _SECURITYTOKENSESSIONBEHAVIORPROTO._serialized_start=53440 + _SECURITYTOKENSESSIONBEHAVIORPROTO._serialized_end=53575 + _DISABLEDSCHEMESPROTO._serialized_start=53578 + _DISABLEDSCHEMESPROTO._serialized_end=53722 + _CROSSORIGINWEBASSEMBLYMODULESHARINGENABLEDPROTO._serialized_start=53725 + _CROSSORIGINWEBASSEMBLYMODULESHARINGENABLEDPROTO._serialized_end=53888 + _USEMOJOVIDEODECODERFORPEPPERALLOWEDPROTO._serialized_start=53891 + _USEMOJOVIDEODECODERFORPEPPERALLOWEDPROTO._serialized_end=54040 + _INSTANTENABLEDPROTO._serialized_start=54042 + _INSTANTENABLEDPROTO._serialized_end=54149 + _POLICYDICTIONARYMULTIPLESOURCEMERGELISTPROTO._serialized_start=54152 + _POLICYDICTIONARYMULTIPLESOURCEMERGELISTPROTO._serialized_end=54344 + _PROMPTONMULTIPLEMATCHINGCERTIFICATESPROTO._serialized_start=54347 + _PROMPTONMULTIPLEMATCHINGCERTIFICATESPROTO._serialized_end=54498 + _CHROMEROOTSTOREENABLEDPROTO._serialized_start=54500 + _CHROMEROOTSTOREENABLEDPROTO._serialized_end=54623 + _ALLOWPOPUPSDURINGPAGEUNLOADPROTO._serialized_start=54626 + _ALLOWPOPUPSDURINGPAGEUNLOADPROTO._serialized_end=54759 + _QUICKUNLOCKMODEWHITELISTPROTO._serialized_start=54762 + _QUICKUNLOCKMODEWHITELISTPROTO._serialized_end=54924 + _AUDIOSANDBOXENABLEDPROTO._serialized_start=54926 + _AUDIOSANDBOXENABLEDPROTO._serialized_end=55043 + _URLALLOWLISTPROTO._serialized_start=55046 + _URLALLOWLISTPROTO._serialized_end=55184 + _DISABLEDPLUGINSEXCEPTIONSPROTO._serialized_start=55187 + _DISABLEDPLUGINSEXCEPTIONSPROTO._serialized_end=55351 + _WEBAUTHENTICATIONREMOTEPROXIEDREQUESTSALLOWEDPROTO._serialized_start=55354 + _WEBAUTHENTICATIONREMOTEPROXIEDREQUESTSALLOWEDPROTO._serialized_end=55523 + _NETWORKSERVICESANDBOXENABLEDPROTO._serialized_start=55526 + _NETWORKSERVICESANDBOXENABLEDPROTO._serialized_end=55661 + _SPELLCHECKLANGUAGEBLACKLISTPROTO._serialized_start=55664 + _SPELLCHECKLANGUAGEBLACKLISTPROTO._serialized_end=55832 + _INSECUREPRIVATENETWORKREQUESTSALLOWEDFORURLSPROTO._serialized_start=55835 + _INSECUREPRIVATENETWORKREQUESTSALLOWEDFORURLSPROTO._serialized_end=56037 + _LOADCRYPTOTOKENEXTENSIONPROTO._serialized_start=56039 + _LOADCRYPTOTOKENEXTENSIONPROTO._serialized_end=56166 + _VIDEOCAPTUREALLOWEDURLSPROTO._serialized_start=56169 + _VIDEOCAPTUREALLOWEDURLSPROTO._serialized_end=56329 + _SCHEDULERCONFIGURATIONPROTO._serialized_start=56331 + _SCHEDULERCONFIGURATIONPROTO._serialized_end=56454 + _WPADQUICKCHECKENABLEDPROTO._serialized_start=56456 + _WPADQUICKCHECKENABLEDPROTO._serialized_end=56577 + _SSLERROROVERRIDEALLOWEDPROTO._serialized_start=56579 + _SSLERROROVERRIDEALLOWEDPROTO._serialized_end=56704 + _CHROMECLEANUPREPORTINGENABLEDPROTO._serialized_start=56707 + _CHROMECLEANUPREPORTINGENABLEDPROTO._serialized_end=56844 + _SSLERROROVERRIDEALLOWEDFORORIGINSPROTO._serialized_start=56847 + _SSLERROROVERRIDEALLOWEDFORORIGINSPROTO._serialized_end=57027 + _GCFUSERDATADIRPROTO._serialized_start=57029 + _GCFUSERDATADIRPROTO._serialized_end=57136 + _CONTEXTAWAREACCESSSIGNALSALLOWLISTPROTO._serialized_start=57139 + _CONTEXTAWAREACCESSSIGNALSALLOWLISTPROTO._serialized_end=57321 + _BLOCKTHIRDPARTYCOOKIESPROTO._serialized_start=57323 + _BLOCKTHIRDPARTYCOOKIESPROTO._serialized_end=57446 + _NATIVEPRINTERSBULKBLACKLISTPROTO._serialized_start=57449 + _NATIVEPRINTERSBULKBLACKLISTPROTO._serialized_end=57617 + _UNMANAGEDDEVICESIGNALSCONSENTFLOWENABLEDPROTO._serialized_start=57620 + _UNMANAGEDDEVICESIGNALSCONSENTFLOWENABLEDPROTO._serialized_end=57779 + _POLICYSCOPEDETECTIONPROTO._serialized_start=57781 + _POLICYSCOPEDETECTIONPROTO._serialized_end=57900 + _EDITBOOKMARKSENABLEDPROTO._serialized_start=57902 + _EDITBOOKMARKSENABLEDPROTO._serialized_end=58021 + _TRASHENABLEDPROTO._serialized_start=58023 + _TRASHENABLEDPROTO._serialized_end=58126 + _LACROSSECONDARYPROFILESALLOWEDPROTO._serialized_start=58129 + _LACROSSECONDARYPROFILESALLOWEDPROTO._serialized_end=58268 + _SIDESEARCHENABLEDPROTO._serialized_start=58270 + _SIDESEARCHENABLEDPROTO._serialized_end=58383 + _CECPQ2ENABLEDPROTO._serialized_start=58385 + _CECPQ2ENABLEDPROTO._serialized_end=58490 + _TRANSLATEENABLEDPROTO._serialized_start=58492 + _TRANSLATEENABLEDPROTO._serialized_end=58603 + _HSTSPOLICYBYPASSLISTPROTO._serialized_start=58606 + _HSTSPOLICYBYPASSLISTPROTO._serialized_end=58760 + _SAMLLOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=58763 + _SAMLLOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=58922 + _FORCEMAJORVERSIONTOMINORPOSITIONINUSERAGENTPROTO._serialized_start=58925 + _FORCEMAJORVERSIONTOMINORPOSITIONINUSERAGENTPROTO._serialized_end=59090 + _BROWSERGUESTMODEENABLEDPROTO._serialized_start=59092 + _BROWSERGUESTMODEENABLEDPROTO._serialized_end=59217 + _SHOWFULLURLSINADDRESSBARPROTO._serialized_start=59219 + _SHOWFULLURLSINADDRESSBARPROTO._serialized_end=59346 + _SECONDARYGOOGLEACCOUNTSIGNINALLOWEDPROTO._serialized_start=59349 + _SECONDARYGOOGLEACCOUNTSIGNINALLOWEDPROTO._serialized_end=59498 + _ISOLATEDWEBAPPINSTALLFORCELISTPROTO._serialized_start=59501 + _ISOLATEDWEBAPPINSTALLFORCELISTPROTO._serialized_end=59640 + _SUGGESTLOGOUTAFTERCLOSINGLASTWINDOWPROTO._serialized_start=59643 + _SUGGESTLOGOUTAFTERCLOSINGLASTWINDOWPROTO._serialized_end=59792 + _DATALEAKPREVENTIONCLIPBOARDCHECKSIZELIMITPROTO._serialized_start=59795 + _DATALEAKPREVENTIONCLIPBOARDCHECKSIZELIMITPROTO._serialized_end=59956 + _SSLVERSIONMINPROTO._serialized_start=59958 + _SSLVERSIONMINPROTO._serialized_end=60063 + _SAFEBROWSINGFORTRUSTEDSOURCESENABLEDPROTO._serialized_start=60066 + _SAFEBROWSINGFORTRUSTEDSOURCESENABLEDPROTO._serialized_end=60217 + _BOOKMARKBARENABLEDPROTO._serialized_start=60219 + _BOOKMARKBARENABLEDPROTO._serialized_end=60334 + _ACCESSIBILITYIMAGELABELSENABLEDPROTO._serialized_start=60337 + _ACCESSIBILITYIMAGELABELSENABLEDPROTO._serialized_end=60478 + _JAVASCRIPTENABLEDPROTO._serialized_start=60480 + _JAVASCRIPTENABLEDPROTO._serialized_end=60593 + _FASTPAIRENABLEDPROTO._serialized_start=60595 + _FASTPAIRENABLEDPROTO._serialized_end=60704 + _CAPTIVEPORTALAUTHENTICATIONIGNORESPROXYPROTO._serialized_start=60707 + _CAPTIVEPORTALAUTHENTICATIONIGNORESPROXYPROTO._serialized_end=60864 + _BROWSERSIGNINPROTO._serialized_start=60866 + _BROWSERSIGNINPROTO._serialized_end=60971 + _MEDIACACHESIZEPROTO._serialized_start=60973 + _MEDIACACHESIZEPROTO._serialized_end=61080 + _MANAGEDGUESTSESSIONAUTOLAUNCHNOTIFICATIONREDUCEDPROTO._serialized_start=61083 + _MANAGEDGUESTSESSIONAUTOLAUNCHNOTIFICATIONREDUCEDPROTO._serialized_end=61258 + _SANDBOXEXTERNALPROTOCOLBLOCKEDPROTO._serialized_start=61261 + _SANDBOXEXTERNALPROTOCOLBLOCKEDPROTO._serialized_end=61400 + _THIRDPARTYBLOCKINGENABLEDPROTO._serialized_start=61403 + _THIRDPARTYBLOCKINGENABLEDPROTO._serialized_end=61532 + _DISPLAYCAPTUREPERMISSIONSPOLICYENABLEDPROTO._serialized_start=61535 + _DISPLAYCAPTUREPERMISSIONSPOLICYENABLEDPROTO._serialized_end=61690 + _BROWSERADDPERSONENABLEDPROTO._serialized_start=61692 + _BROWSERADDPERSONENABLEDPROTO._serialized_end=61817 + _PHONEHUBTASKCONTINUATIONALLOWEDPROTO._serialized_start=61820 + _PHONEHUBTASKCONTINUATIONALLOWEDPROTO._serialized_end=61961 + _PHONEHUBALLOWEDPROTO._serialized_start=61963 + _PHONEHUBALLOWEDPROTO._serialized_end=62072 + _DISABLE3DAPISPROTO._serialized_start=62074 + _DISABLE3DAPISPROTO._serialized_end=62179 + _HIDEWEBSTOREPROMOPROTO._serialized_start=62181 + _HIDEWEBSTOREPROMOPROTO._serialized_end=62294 + _LACROSSELECTIONPROTO._serialized_start=62296 + _LACROSSELECTIONPROTO._serialized_end=62405 + _CLOUDUSERPOLICYOVERRIDESCLOUDMACHINEPOLICYPROTO._serialized_start=62408 + _CLOUDUSERPOLICYOVERRIDESCLOUDMACHINEPOLICYPROTO._serialized_end=62571 + _ENABLEDPLUGINSPROTO._serialized_start=62574 + _ENABLEDPLUGINSPROTO._serialized_end=62716 + _ABUSIVEEXPERIENCEINTERVENTIONENFORCEPROTO._serialized_start=62719 + _ABUSIVEEXPERIENCEINTERVENTIONENFORCEPROTO._serialized_end=62870 + _HISTORYCLUSTERSVISIBLEPROTO._serialized_start=62872 + _HISTORYCLUSTERSVISIBLEPROTO._serialized_end=62995 + _SHAREDARRAYBUFFERUNRESTRICTEDACCESSALLOWEDPROTO._serialized_start=62998 + _SHAREDARRAYBUFFERUNRESTRICTEDACCESSALLOWEDPROTO._serialized_end=63161 + _URLBLOCKLISTPROTO._serialized_start=63164 + _URLBLOCKLISTPROTO._serialized_end=63302 + _BACKGROUNDMODEENABLEDPROTO._serialized_start=63304 + _BACKGROUNDMODEENABLEDPROTO._serialized_end=63425 + _FORCELOGOUTUNAUTHENTICATEDUSERENABLEDPROTO._serialized_start=63428 + _FORCELOGOUTUNAUTHENTICATEDUSERENABLEDPROTO._serialized_end=63581 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORLEGACYCASPROTO._serialized_start=63584 + _CERTIFICATETRANSPARENCYENFORCEMENTDISABLEDFORLEGACYCASPROTO._serialized_end=63806 + _ENABLESYNCCONSENTPROTO._serialized_start=63808 + _ENABLESYNCCONSENTPROTO._serialized_end=63921 + _SUPPRESSDIFFERENTORIGINSUBFRAMEDIALOGSPROTO._serialized_start=63924 + _SUPPRESSDIFFERENTORIGINSUBFRAMEDIALOGSPROTO._serialized_end=64079 + _WEBRTCALLOWLEGACYTLSPROTOCOLSPROTO._serialized_start=64082 + _WEBRTCALLOWLEGACYTLSPROTOCOLSPROTO._serialized_end=64219 + _PROMPTFORDOWNLOADLOCATIONPROTO._serialized_start=64222 + _PROMPTFORDOWNLOADLOCATIONPROTO._serialized_end=64351 + _IMPORTSAVEDPASSWORDSPROTO._serialized_start=64353 + _IMPORTSAVEDPASSWORDSPROTO._serialized_end=64472 + _FORCEENABLEPEPPERVIDEODECODERDEVAPIPROTO._serialized_start=64475 + _FORCEENABLEPEPPERVIDEODECODERDEVAPIPROTO._serialized_end=64624 + _INSECUREFORMSWARNINGSENABLEDPROTO._serialized_start=64627 + _INSECUREFORMSWARNINGSENABLEDPROTO._serialized_end=64762 + _PROMOTIONALTABSENABLEDPROTO._serialized_start=64764 + _PROMOTIONALTABSENABLEDPROTO._serialized_end=64887 + _ORIGINAGENTCLUSTERDEFAULTENABLEDPROTO._serialized_start=64890 + _ORIGINAGENTCLUSTERDEFAULTENABLEDPROTO._serialized_end=65033 + _SEARCHSUGGESTENABLEDPROTO._serialized_start=65035 + _SEARCHSUGGESTENABLEDPROTO._serialized_end=65154 + _PACHTTPSURLSTRIPPINGENABLEDPROTO._serialized_start=65157 + _PACHTTPSURLSTRIPPINGENABLEDPROTO._serialized_end=65290 + _EXPLICITLYALLOWEDNETWORKPORTSPROTO._serialized_start=65293 + _EXPLICITLYALLOWEDNETWORKPORTSPROTO._serialized_end=65465 + _RESTRICTSIGNINTOPATTERNPROTO._serialized_start=65467 + _RESTRICTSIGNINTOPATTERNPROTO._serialized_end=65592 + _BROWSERLEGACYEXTENSIONPOINTSBLOCKEDPROTO._serialized_start=65595 + _BROWSERLEGACYEXTENSIONPOINTSBLOCKEDPROTO._serialized_end=65744 + _SPELLCHECKSERVICEENABLEDPROTO._serialized_start=65746 + _SPELLCHECKSERVICEENABLEDPROTO._serialized_end=65873 + _TABUNDERALLOWEDPROTO._serialized_start=65875 + _TABUNDERALLOWEDPROTO._serialized_end=65984 + _BATTERYSAVERMODEAVAILABILITYPROTO._serialized_start=65987 + _BATTERYSAVERMODEAVAILABILITYPROTO._serialized_end=66122 + _ONBULKDATAENTRYENTERPRISECONNECTORPROTO._serialized_start=66125 + _ONBULKDATAENTRYENTERPRISECONNECTORPROTO._serialized_end=66272 + _LACROSALLOWEDPROTO._serialized_start=66274 + _LACROSALLOWEDPROTO._serialized_end=66379 + _DATALEAKPREVENTIONREPORTINGENABLEDPROTO._serialized_start=66382 + _DATALEAKPREVENTIONREPORTINGENABLEDPROTO._serialized_end=66529 + _ALLOWNATIVENOTIFICATIONSPROTO._serialized_start=66531 + _ALLOWNATIVENOTIFICATIONSPROTO._serialized_end=66658 + _URLWHITELISTPROTO._serialized_start=66661 + _URLWHITELISTPROTO._serialized_end=66799 + _EXTERNALPROTOCOLDIALOGSHOWALWAYSOPENCHECKBOXPROTO._serialized_start=66802 + _EXTERNALPROTOCOLDIALOGSHOWALWAYSOPENCHECKBOXPROTO._serialized_end=66969 + _RELAUNCHNOTIFICATIONPERIODPROTO._serialized_start=66972 + _RELAUNCHNOTIFICATIONPERIODPROTO._serialized_end=67103 + _LOOKALIKEWARNINGALLOWLISTDOMAINSPROTO._serialized_start=67106 + _LOOKALIKEWARNINGALLOWLISTDOMAINSPROTO._serialized_end=67284 + _NOTETAKINGAPPSLOCKSCREENALLOWLISTPROTO._serialized_start=67287 + _NOTETAKINGAPPSLOCKSCREENALLOWLISTPROTO._serialized_end=67467 + _SITEPERPROCESSPROTO._serialized_start=67469 + _SITEPERPROCESSPROTO._serialized_end=67576 + _BRUSCHETTAVMCONFIGURATIONPROTO._serialized_start=67579 + _BRUSCHETTAVMCONFIGURATIONPROTO._serialized_end=67708 + _DNSINTERCEPTIONCHECKSENABLEDPROTO._serialized_start=67711 + _DNSINTERCEPTIONCHECKSENABLEDPROTO._serialized_end=67846 + _DESKTOPSHARINGHUBENABLEDPROTO._serialized_start=67848 + _DESKTOPSHARINGHUBENABLEDPROTO._serialized_end=67975 + _ACCESSCODECASTDEVICEDURATIONPROTO._serialized_start=67978 + _ACCESSCODECASTDEVICEDURATIONPROTO._serialized_end=68113 + _DEVICEATTRIBUTESALLOWEDFORORIGINSPROTO._serialized_start=68116 + _DEVICEATTRIBUTESALLOWEDFORORIGINSPROTO._serialized_end=68296 + _ENTERPRISEAUTHENTICATIONAPPLINKPOLICYPROTO._serialized_start=68299 + _ENTERPRISEAUTHENTICATIONAPPLINKPOLICYPROTO._serialized_end=68452 + _USELEGACYFORMCONTROLSPROTO._serialized_start=68454 + _USELEGACYFORMCONTROLSPROTO._serialized_end=68575 + _TLS13HARDENINGFORLOCALANCHORSENABLEDPROTO._serialized_start=68578 + _TLS13HARDENINGFORLOCALANCHORSENABLEDPROTO._serialized_end=68729 + _QUICALLOWEDPROTO._serialized_start=68731 + _QUICALLOWEDPROTO._serialized_end=68832 + _CORSMITIGATIONLISTPROTO._serialized_start=68835 + _CORSMITIGATIONLISTPROTO._serialized_end=68985 + _USERDISPLAYNAMEPROTO._serialized_start=68987 + _USERDISPLAYNAMEPROTO._serialized_end=69096 + _WEBRTCEVENTLOGCOLLECTIONALLOWEDPROTO._serialized_start=69099 + _WEBRTCEVENTLOGCOLLECTIONALLOWEDPROTO._serialized_end=69240 + _WEBRTCIPHANDLINGPROTO._serialized_start=69242 + _WEBRTCIPHANDLINGPROTO._serialized_end=69353 + _KEEPFULLSCREENWITHOUTNOTIFICATIONURLALLOWLISTPROTO._serialized_start=69356 + _KEEPFULLSCREENWITHOUTNOTIFICATIONURLALLOWLISTPROTO._serialized_end=69560 + _FLOATINGWORKSPACEV2ENABLEDPROTO._serialized_start=69563 + _FLOATINGWORKSPACEV2ENABLEDPROTO._serialized_end=69694 + _AUTOFILLENABLEDPROTO._serialized_start=69696 + _AUTOFILLENABLEDPROTO._serialized_end=69805 + _CLICKTOCALLENABLEDPROTO._serialized_start=69807 + _CLICKTOCALLENABLEDPROTO._serialized_end=69922 + _SIGNEDHTTPEXCHANGEENABLEDPROTO._serialized_start=69925 + _SIGNEDHTTPEXCHANGEENABLEDPROTO._serialized_end=70054 + _SSLVERSIONMAXPROTO._serialized_start=70056 + _SSLVERSIONMAXPROTO._serialized_end=70161 + _AUDIOOUTPUTALLOWEDPROTO._serialized_start=70163 + _AUDIOOUTPUTALLOWEDPROTO._serialized_end=70278 + _CONTEXTUALSEARCHENABLEDPROTO._serialized_start=70280 + _CONTEXTUALSEARCHENABLEDPROTO._serialized_end=70405 + _DISABLESSLRECORDSPLITTINGPROTO._serialized_start=70408 + _DISABLESSLRECORDSPLITTINGPROTO._serialized_end=70537 + _NETWORKPREDICTIONOPTIONSPROTO._serialized_start=70539 + _NETWORKPREDICTIONOPTIONSPROTO._serialized_end=70666 + _IMPORTHOMEPAGEPROTO._serialized_start=70668 + _IMPORTHOMEPAGEPROTO._serialized_end=70775 + _ENTERPRISEREALTIMEURLCHECKMODEPROTO._serialized_start=70778 + _ENTERPRISEREALTIMEURLCHECKMODEPROTO._serialized_end=70917 + _SPELLCHECKENABLEDPROTO._serialized_start=70919 + _SPELLCHECKENABLEDPROTO._serialized_end=71032 + _ALLOWSCREENLOCKPROTO._serialized_start=71034 + _ALLOWSCREENLOCKPROTO._serialized_end=71143 + _WELCOMEPAGEONOSUPGRADEENABLEDPROTO._serialized_start=71146 + _WELCOMEPAGEONOSUPGRADEENABLEDPROTO._serialized_end=71283 + _ENABLESHA1FORLOCALANCHORSPROTO._serialized_start=71286 + _ENABLESHA1FORLOCALANCHORSPROTO._serialized_end=71415 + _SIGNINALLOWEDPROTO._serialized_start=71417 + _SIGNINALLOWEDPROTO._serialized_end=71522 + _ALLOWDELETINGBROWSERHISTORYPROTO._serialized_start=71525 + _ALLOWDELETINGBROWSERHISTORYPROTO._serialized_end=71658 + _AUTHSERVERWHITELISTPROTO._serialized_start=71660 + _AUTHSERVERWHITELISTPROTO._serialized_end=71777 + _TERMSOFSERVICEURLPROTO._serialized_start=71779 + _TERMSOFSERVICEURLPROTO._serialized_end=71892 + _ONFILEATTACHEDENTERPRISECONNECTORPROTO._serialized_start=71895 + _ONFILEATTACHEDENTERPRISECONNECTORPROTO._serialized_end=72040 + _CHROMEOSMULTIPROFILEUSERBEHAVIORPROTO._serialized_start=72043 + _CHROMEOSMULTIPROFILEUSERBEHAVIORPROTO._serialized_end=72186 + _SAFESITESFILTERBEHAVIORPROTO._serialized_start=72188 + _SAFESITESFILTERBEHAVIORPROTO._serialized_end=72313 + _SPELLCHECKLANGUAGEBLOCKLISTPROTO._serialized_start=72316 + _SPELLCHECKLANGUAGEBLOCKLISTPROTO._serialized_end=72484 + _ENTERPRISEWEBSTORENAMEPROTO._serialized_start=72486 + _ENTERPRISEWEBSTORENAMEPROTO._serialized_end=72609 + _ALLOWSYNCXHRINPAGEDISMISSALPROTO._serialized_start=72612 + _ALLOWSYNCXHRINPAGEDISMISSALPROTO._serialized_end=72745 + _ALWAYSAUTHORIZEPLUGINSPROTO._serialized_start=72747 + _ALWAYSAUTHORIZEPLUGINSPROTO._serialized_end=72870 + _OVERRIDESECURITYRESTRICTIONSONINSECUREORIGINPROTO._serialized_start=72873 + _OVERRIDESECURITYRESTRICTIONSONINSECUREORIGINPROTO._serialized_end=73075 + _GHOSTWINDOWENABLEDPROTO._serialized_start=73077 + _GHOSTWINDOWENABLEDPROTO._serialized_end=73192 + _TOSDIALOGBEHAVIORPROTO._serialized_start=73194 + _TOSDIALOGBEHAVIORPROTO._serialized_end=73307 + _IMPORTHISTORYPROTO._serialized_start=73309 + _IMPORTHISTORYPROTO._serialized_end=73414 + _ROAMINGPROFILESUPPORTENABLEDPROTO._serialized_start=73417 + _ROAMINGPROFILESUPPORTENABLEDPROTO._serialized_end=73552 + _GAIALOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=73555 + _GAIALOCKSCREENOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=73714 + _CLOUDPROFILEREPORTINGENABLEDPROTO._serialized_start=73717 + _CLOUDPROFILEREPORTINGENABLEDPROTO._serialized_end=73852 + _FULLRESTOREENABLEDPROTO._serialized_start=73854 + _FULLRESTOREENABLEDPROTO._serialized_end=73969 + _DOWNLOADDIRECTORYPROTO._serialized_start=73971 + _DOWNLOADDIRECTORYPROTO._serialized_end=74084 + _DNSOVERHTTPSMODEPROTO._serialized_start=74086 + _DNSOVERHTTPSMODEPROTO._serialized_end=74197 + _DEFAULTSEARCHPROVIDERSUGGESTURLPOSTPARAMSPROTO._serialized_start=74200 + _DEFAULTSEARCHPROVIDERSUGGESTURLPOSTPARAMSPROTO._serialized_end=74361 + _DEFAULTSEARCHPROVIDERICONURLPROTO._serialized_start=74364 + _DEFAULTSEARCHPROVIDERICONURLPROTO._serialized_end=74499 + _DEFAULTSEARCHPROVIDERNEWTABURLPROTO._serialized_start=74502 + _DEFAULTSEARCHPROVIDERNEWTABURLPROTO._serialized_end=74641 + _DEFAULTSEARCHPROVIDERNAMEPROTO._serialized_start=74644 + _DEFAULTSEARCHPROVIDERNAMEPROTO._serialized_end=74773 + _DEFAULTSEARCHPROVIDERKEYWORDPROTO._serialized_start=74776 + _DEFAULTSEARCHPROVIDERKEYWORDPROTO._serialized_end=74911 + _DEFAULTSEARCHPROVIDERINSTANTURLPROTO._serialized_start=74914 + _DEFAULTSEARCHPROVIDERINSTANTURLPROTO._serialized_end=75055 + _DEFAULTSEARCHPROVIDERIMAGEURLPROTO._serialized_start=75058 + _DEFAULTSEARCHPROVIDERIMAGEURLPROTO._serialized_end=75195 + _DEFAULTSEARCHPROVIDERIMAGEURLPOSTPARAMSPROTO._serialized_start=75198 + _DEFAULTSEARCHPROVIDERIMAGEURLPOSTPARAMSPROTO._serialized_end=75355 + _DEFAULTSEARCHPROVIDERSUGGESTURLPROTO._serialized_start=75358 + _DEFAULTSEARCHPROVIDERSUGGESTURLPROTO._serialized_end=75499 + _DEFAULTSEARCHPROVIDERSEARCHTERMSREPLACEMENTKEYPROTO._serialized_start=75502 + _DEFAULTSEARCHPROVIDERSEARCHTERMSREPLACEMENTKEYPROTO._serialized_end=75673 + _DEFAULTSEARCHPROVIDERENABLEDPROTO._serialized_start=75676 + _DEFAULTSEARCHPROVIDERENABLEDPROTO._serialized_end=75811 + _DEFAULTSEARCHPROVIDERINSTANTURLPOSTPARAMSPROTO._serialized_start=75814 + _DEFAULTSEARCHPROVIDERINSTANTURLPOSTPARAMSPROTO._serialized_end=75975 + _DEFAULTSEARCHPROVIDERENCODINGSPROTO._serialized_start=75978 + _DEFAULTSEARCHPROVIDERENCODINGSPROTO._serialized_end=76152 + _DEFAULTSEARCHPROVIDERSEARCHURLPROTO._serialized_start=76155 + _DEFAULTSEARCHPROVIDERSEARCHURLPROTO._serialized_end=76294 + _DEFAULTSEARCHPROVIDERALTERNATEURLSPROTO._serialized_start=76297 + _DEFAULTSEARCHPROVIDERALTERNATEURLSPROTO._serialized_end=76479 + _DEFAULTSEARCHPROVIDERSEARCHURLPOSTPARAMSPROTO._serialized_start=76482 + _DEFAULTSEARCHPROVIDERSEARCHURLPOSTPARAMSPROTO._serialized_end=76641 + _RECOVERYFACTORBEHAVIORPROTO._serialized_start=76643 + _RECOVERYFACTORBEHAVIORPROTO._serialized_end=76766 + _ATTESTATIONENABLEDFORUSERPROTO._serialized_start=76769 + _ATTESTATIONENABLEDFORUSERPROTO._serialized_end=76898 + _ATTESTATIONEXTENSIONALLOWLISTPROTO._serialized_start=76901 + _ATTESTATIONEXTENSIONALLOWLISTPROTO._serialized_end=77073 + _CHROMEFRAMECONTENTTYPESPROTO._serialized_start=77076 + _CHROMEFRAMECONTENTTYPESPROTO._serialized_end=77236 + _NEWWINDOWSINKIOSKALLOWEDPROTO._serialized_start=77238 + _NEWWINDOWSINKIOSKALLOWEDPROTO._serialized_end=77365 + _KIOSKTROUBLESHOOTINGTOOLSENABLEDPROTO._serialized_start=77368 + _KIOSKTROUBLESHOOTINGTOOLSENABLEDPROTO._serialized_end=77511 + _PROXYSERVERMODEPROTO._serialized_start=77513 + _PROXYSERVERMODEPROTO._serialized_end=77622 + _PROXYMODEPROTO._serialized_start=77624 + _PROXYMODEPROTO._serialized_end=77721 + _PROXYBYPASSLISTPROTO._serialized_start=77723 + _PROXYBYPASSLISTPROTO._serialized_end=77832 + _PROXYSERVERPROTO._serialized_start=77834 + _PROXYSERVERPROTO._serialized_end=77935 + _PROXYPACURLPROTO._serialized_start=77937 + _PROXYPACURLPROTO._serialized_end=78038 + _EXTENSIONINSTALLSOURCESPROTO._serialized_start=78041 + _EXTENSIONINSTALLSOURCESPROTO._serialized_end=78201 + _EXTENSIONALLOWEDTYPESPROTO._serialized_start=78204 + _EXTENSIONALLOWEDTYPESPROTO._serialized_end=78360 + _EXTENSIONINSTALLBLOCKLISTPROTO._serialized_start=78363 + _EXTENSIONINSTALLBLOCKLISTPROTO._serialized_end=78527 + _EXTENSIONINSTALLFORCELISTPROTO._serialized_start=78530 + _EXTENSIONINSTALLFORCELISTPROTO._serialized_end=78694 + _EXTENSIONINSTALLALLOWLISTPROTO._serialized_start=78697 + _EXTENSIONINSTALLALLOWLISTPROTO._serialized_end=78861 + _EXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_start=78864 + _EXTENSIONMANIFESTV2AVAILABILITYPROTO._serialized_end=79005 + _EXTENSIONALLOWINSECUREUPDATESPROTO._serialized_start=79008 + _EXTENSIONALLOWINSECUREUPDATESPROTO._serialized_end=79145 + _EXTENSIONSETTINGSPROTO._serialized_start=79147 + _EXTENSIONSETTINGSPROTO._serialized_end=79260 + _BLOCKEXTERNALEXTENSIONSPROTO._serialized_start=79262 + _BLOCKEXTERNALEXTENSIONSPROTO._serialized_end=79387 + _KERBEROSACCOUNTSPROTO._serialized_start=79389 + _KERBEROSACCOUNTSPROTO._serialized_end=79500 + _KERBEROSDOMAINAUTOCOMPLETEPROTO._serialized_start=79503 + _KERBEROSDOMAINAUTOCOMPLETEPROTO._serialized_end=79634 + _KERBEROSREMEMBERPASSWORDENABLEDPROTO._serialized_start=79637 + _KERBEROSREMEMBERPASSWORDENABLEDPROTO._serialized_end=79778 + _KERBEROSADDACCOUNTSALLOWEDPROTO._serialized_start=79781 + _KERBEROSADDACCOUNTSALLOWEDPROTO._serialized_end=79912 + _KERBEROSUSECUSTOMPREFILLEDCONFIGPROTO._serialized_start=79915 + _KERBEROSUSECUSTOMPREFILLEDCONFIGPROTO._serialized_end=80058 + _KERBEROSENABLEDPROTO._serialized_start=80060 + _KERBEROSENABLEDPROTO._serialized_end=80169 + _KERBEROSCUSTOMPREFILLEDCONFIGPROTO._serialized_start=80172 + _KERBEROSCUSTOMPREFILLEDCONFIGPROTO._serialized_end=80309 + _NETBIOSSHAREDISCOVERYENABLEDPROTO._serialized_start=80312 + _NETBIOSSHAREDISCOVERYENABLEDPROTO._serialized_end=80447 + _NTLMSHAREAUTHENTICATIONENABLEDPROTO._serialized_start=80450 + _NTLMSHAREAUTHENTICATIONENABLEDPROTO._serialized_end=80589 + _NETWORKFILESHARESALLOWEDPROTO._serialized_start=80591 + _NETWORKFILESHARESALLOWEDPROTO._serialized_end=80718 + _NETWORKFILESHARESPRECONFIGUREDSHARESPROTO._serialized_start=80721 + _NETWORKFILESHARESPRECONFIGUREDSHARESPROTO._serialized_end=80872 + _REQUIREDCLIENTCERTIFICATEFORUSERPROTO._serialized_start=80875 + _REQUIREDCLIENTCERTIFICATEFORUSERPROTO._serialized_end=81018 + _SAMLPASSWORDEXPIRATIONADVANCEWARNINGDAYSPROTO._serialized_start=81021 + _SAMLPASSWORDEXPIRATIONADVANCEWARNINGDAYSPROTO._serialized_end=81180 + _SAMLINSESSIONPASSWORDCHANGEENABLEDPROTO._serialized_start=81183 + _SAMLINSESSIONPASSWORDCHANGEENABLEDPROTO._serialized_end=81330 + _LOCKSCREENREAUTHENTICATIONENABLEDPROTO._serialized_start=81333 + _LOCKSCREENREAUTHENTICATIONENABLEDPROTO._serialized_end=81478 + _SAMLOFFLINESIGNINTIMELIMITPROTO._serialized_start=81481 + _SAMLOFFLINESIGNINTIMELIMITPROTO._serialized_end=81612 + _PASSWORDPROTECTIONCHANGEPASSWORDURLPROTO._serialized_start=81615 + _PASSWORDPROTECTIONCHANGEPASSWORDURLPROTO._serialized_end=81764 + _SAFEBROWSINGENABLEDPROTO._serialized_start=81766 + _SAFEBROWSINGENABLEDPROTO._serialized_end=81883 + _SAFEBROWSINGEXTENDEDREPORTINGENABLEDPROTO._serialized_start=81886 + _SAFEBROWSINGEXTENDEDREPORTINGENABLEDPROTO._serialized_end=82037 + _SAFEBROWSINGALLOWLISTDOMAINSPROTO._serialized_start=82040 + _SAFEBROWSINGALLOWLISTDOMAINSPROTO._serialized_end=82210 + _PASSWORDPROTECTIONLOGINURLSPROTO._serialized_start=82213 + _PASSWORDPROTECTIONLOGINURLSPROTO._serialized_end=82381 + _PASSWORDPROTECTIONWARNINGTRIGGERPROTO._serialized_start=82384 + _PASSWORDPROTECTIONWARNINGTRIGGERPROTO._serialized_end=82527 + _SAFEBROWSINGPROTECTIONLEVELPROTO._serialized_start=82530 + _SAFEBROWSINGPROTECTIONLEVELPROTO._serialized_end=82663 + _REPORTMACHINEIDDATAPROTO._serialized_start=82665 + _REPORTMACHINEIDDATAPROTO._serialized_end=82782 + _CLOUDREPORTINGENABLEDPROTO._serialized_start=82784 + _CLOUDREPORTINGENABLEDPROTO._serialized_end=82905 + _CLOUDEXTENSIONREQUESTENABLEDPROTO._serialized_start=82908 + _CLOUDEXTENSIONREQUESTENABLEDPROTO._serialized_end=83043 + _REPORTEXTENSIONSANDPLUGINSDATAPROTO._serialized_start=83046 + _REPORTEXTENSIONSANDPLUGINSDATAPROTO._serialized_end=83185 + _CLOUDREPORTINGUPLOADFREQUENCYPROTO._serialized_start=83188 + _CLOUDREPORTINGUPLOADFREQUENCYPROTO._serialized_end=83325 + _REPORTUSERIDDATAPROTO._serialized_start=83327 + _REPORTUSERIDDATAPROTO._serialized_end=83438 + _REPORTPOLICYDATAPROTO._serialized_start=83440 + _REPORTPOLICYDATAPROTO._serialized_end=83551 + _REPORTSAFEBROWSINGDATAPROTO._serialized_start=83553 + _REPORTSAFEBROWSINGDATAPROTO._serialized_end=83676 + _REPORTVERSIONDATAPROTO._serialized_start=83678 + _REPORTVERSIONDATAPROTO._serialized_end=83791 + _HOMEPAGEISNEWTABPAGEPROTO._serialized_start=83793 + _HOMEPAGEISNEWTABPAGEPROTO._serialized_end=83912 + _RESTOREONSTARTUPPROTO._serialized_start=83914 + _RESTOREONSTARTUPPROTO._serialized_end=84025 + _RESTOREONSTARTUPURLSPROTO._serialized_start=84028 + _RESTOREONSTARTUPURLSPROTO._serialized_end=84182 + _NEWTABPAGELOCATIONPROTO._serialized_start=84184 + _NEWTABPAGELOCATIONPROTO._serialized_end=84299 + _SHOWHOMEBUTTONPROTO._serialized_start=84301 + _SHOWHOMEBUTTONPROTO._serialized_end=84408 + _HOMEPAGELOCATIONPROTO._serialized_start=84410 + _HOMEPAGELOCATIONPROTO._serialized_end=84521 + _ARCBACKUPRESTORESERVICEENABLEDPROTO._serialized_start=84524 + _ARCBACKUPRESTORESERVICEENABLEDPROTO._serialized_end=84663 + _ARCAPPTOWEBAPPSHARINGENABLEDPROTO._serialized_start=84666 + _ARCAPPTOWEBAPPSHARINGENABLEDPROTO._serialized_end=84801 + _ARCAPPINSTALLEVENTLOGGINGENABLEDPROTO._serialized_start=84804 + _ARCAPPINSTALLEVENTLOGGINGENABLEDPROTO._serialized_end=84947 + _ARCCERTIFICATESSYNCMODEPROTO._serialized_start=84949 + _ARCCERTIFICATESSYNCMODEPROTO._serialized_end=85074 + _ARCBACKUPRESTOREENABLEDPROTO._serialized_start=85076 + _ARCBACKUPRESTOREENABLEDPROTO._serialized_end=85201 + _ARCLOCATIONSERVICEENABLEDPROTO._serialized_start=85204 + _ARCLOCATIONSERVICEENABLEDPROTO._serialized_end=85333 + _APPRECOMMENDATIONZEROSTATEENABLEDPROTO._serialized_start=85336 + _APPRECOMMENDATIONZEROSTATEENABLEDPROTO._serialized_end=85481 + _ARCENABLEDPROTO._serialized_start=85483 + _ARCENABLEDPROTO._serialized_end=85582 + _ARCGOOGLELOCATIONSERVICESENABLEDPROTO._serialized_start=85585 + _ARCGOOGLELOCATIONSERVICESENABLEDPROTO._serialized_end=85728 + _ARCPOLICYPROTO._serialized_start=85730 + _ARCPOLICYPROTO._serialized_end=85827 + _DRIVEDISABLEDPROTO._serialized_start=85829 + _DRIVEDISABLEDPROTO._serialized_end=85934 + _DRIVEDISABLEDOVERCELLULARPROTO._serialized_start=85937 + _DRIVEDISABLEDOVERCELLULARPROTO._serialized_end=86066 + _SAMEORIGINTABCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=86069 + _SAMEORIGINTABCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=86255 + _SCREENCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=86258 + _SCREENCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=86430 + _SCREENCAPTUREALLOWEDPROTO._serialized_start=86432 + _SCREENCAPTUREALLOWEDPROTO._serialized_end=86551 + _WINDOWCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=86554 + _WINDOWCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=86726 + _TABCAPTUREALLOWEDBYORIGINSPROTO._serialized_start=86729 + _TABCAPTUREALLOWEDBYORIGINSPROTO._serialized_end=86895 + _PINUNLOCKMINIMUMLENGTHPROTO._serialized_start=86897 + _PINUNLOCKMINIMUMLENGTHPROTO._serialized_end=87020 + _PINUNLOCKWEAKPINSALLOWEDPROTO._serialized_start=87022 + _PINUNLOCKWEAKPINSALLOWEDPROTO._serialized_end=87149 + _QUICKUNLOCKTIMEOUTPROTO._serialized_start=87151 + _QUICKUNLOCKTIMEOUTPROTO._serialized_end=87266 + _QUICKUNLOCKMODEALLOWLISTPROTO._serialized_start=87269 + _QUICKUNLOCKMODEALLOWLISTPROTO._serialized_end=87431 + _PINUNLOCKAUTOSUBMITENABLEDPROTO._serialized_start=87434 + _PINUNLOCKAUTOSUBMITENABLEDPROTO._serialized_end=87565 + _PINUNLOCKMAXIMUMLENGTHPROTO._serialized_start=87567 + _PINUNLOCKMAXIMUMLENGTHPROTO._serialized_end=87690 + _PROJECTORDOGFOODFORFAMILYLINKENABLEDPROTO._serialized_start=87693 + _PROJECTORDOGFOODFORFAMILYLINKENABLEDPROTO._serialized_end=87844 + _PROJECTORENABLEDPROTO._serialized_start=87846 + _PROJECTORENABLEDPROTO._serialized_end=87957 + _ENABLEMEDIAROUTERPROTO._serialized_start=87959 + _ENABLEMEDIAROUTERPROTO._serialized_end=88072 + _SHOWCASTICONINTOOLBARPROTO._serialized_start=88074 + _SHOWCASTICONINTOOLBARPROTO._serialized_end=88195 + _SHOWCASTSESSIONSSTARTEDBYOTHERDEVICESPROTO._serialized_start=88198 + _SHOWCASTSESSIONSSTARTEDBYOTHERDEVICESPROTO._serialized_end=88351 + _MEDIAROUTERCASTALLOWALLIPSPROTO._serialized_start=88354 + _MEDIAROUTERCASTALLOWALLIPSPROTO._serialized_end=88485 + _CALENDARINTEGRATIONENABLEDPROTO._serialized_start=88488 + _CALENDARINTEGRATIONENABLEDPROTO._serialized_end=88619 + _PRIVACYSANDBOXADTOPICSENABLEDPROTO._serialized_start=88622 + _PRIVACYSANDBOXADTOPICSENABLEDPROTO._serialized_end=88759 + _PRIVACYSANDBOXSITEENABLEDADSENABLEDPROTO._serialized_start=88762 + _PRIVACYSANDBOXSITEENABLEDADSENABLEDPROTO._serialized_end=88911 + _PRIVACYSANDBOXPROMPTENABLEDPROTO._serialized_start=88914 + _PRIVACYSANDBOXPROMPTENABLEDPROTO._serialized_end=89047 + _PRIVACYSANDBOXADMEASUREMENTENABLEDPROTO._serialized_start=89050 + _PRIVACYSANDBOXADMEASUREMENTENABLEDPROTO._serialized_end=89197 + _DNSOVERHTTPSTEMPLATESWITHIDENTIFIERSPROTO._serialized_start=89200 + _DNSOVERHTTPSTEMPLATESWITHIDENTIFIERSPROTO._serialized_end=89351 + _ACCESSCONTROLALLOWMETHODSINCORSPREFLIGHTSPECCONFORMANTPROTO._serialized_start=89354 + _ACCESSCONTROLALLOWMETHODSINCORSPREFLIGHTSPECCONFORMANTPROTO._serialized_end=89541 + _DNSOVERHTTPSSALTPROTO._serialized_start=89543 + _DNSOVERHTTPSSALTPROTO._serialized_end=89654 + _REPORTARCSTATUSENABLEDPROTO._serialized_start=89656 + _REPORTARCSTATUSENABLEDPROTO._serialized_end=89779 + _NATIVEMESSAGINGUSERLEVELHOSTSPROTO._serialized_start=89782 + _NATIVEMESSAGINGUSERLEVELHOSTSPROTO._serialized_end=89919 + _NATIVEMESSAGINGBLOCKLISTPROTO._serialized_start=89922 + _NATIVEMESSAGINGBLOCKLISTPROTO._serialized_end=90084 + _NATIVEMESSAGINGALLOWLISTPROTO._serialized_start=90087 + _NATIVEMESSAGINGALLOWLISTPROTO._serialized_end=90249 + _GAIAOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_start=90252 + _GAIAOFFLINESIGNINTIMELIMITDAYSPROTO._serialized_end=90391 + _USERPLUGINVMALLOWEDPROTO._serialized_start=90393 + _USERPLUGINVMALLOWEDPROTO._serialized_end=90510 + _PLUGINVMDATACOLLECTIONALLOWEDPROTO._serialized_start=90513 + _PLUGINVMDATACOLLECTIONALLOWEDPROTO._serialized_end=90650 + _PLUGINVMUSERIDPROTO._serialized_start=90652 + _PLUGINVMUSERIDPROTO._serialized_end=90759 + _PLUGINVMIMAGEPROTO._serialized_start=90761 + _PLUGINVMIMAGEPROTO._serialized_end=90866 + _PLUGINVMREQUIREDFREEDISKSPACEPROTO._serialized_start=90869 + _PLUGINVMREQUIREDFREEDISKSPACEPROTO._serialized_end=91006 + _PRIVACYSCREENENABLEDPROTO._serialized_start=91008 + _PRIVACYSCREENENABLEDPROTO._serialized_end=91127 + _USAGETIMELIMITPROTO._serialized_start=91129 + _USAGETIMELIMITPROTO._serialized_end=91236 + _PERAPPTIMELIMITSALLOWLISTPROTO._serialized_start=91239 + _PERAPPTIMELIMITSALLOWLISTPROTO._serialized_end=91368 + _EDUCOEXISTENCETOSVERSIONPROTO._serialized_start=91370 + _EDUCOEXISTENCETOSVERSIONPROTO._serialized_end=91497 + _PERAPPTIMELIMITSPROTO._serialized_start=91499 + _PERAPPTIMELIMITSPROTO._serialized_end=91610 + _PARENTACCESSCODECONFIGPROTO._serialized_start=91612 + _PARENTACCESSCODECONFIGPROTO._serialized_end=91735 + _CHROMEFRAMERENDERERSETTINGSPROTO._serialized_start=91738 + _CHROMEFRAMERENDERERSETTINGSPROTO._serialized_end=91871 + _ADDITIONALLAUNCHPARAMETERSPROTO._serialized_start=91874 + _ADDITIONALLAUNCHPARAMETERSPROTO._serialized_end=92005 + _RENDERINCHROMEFRAMELISTPROTO._serialized_start=92008 + _RENDERINCHROMEFRAMELISTPROTO._serialized_end=92168 + _RENDERINHOSTLISTPROTO._serialized_start=92171 + _RENDERINHOSTLISTPROTO._serialized_end=92317 + _SKIPMETADATACHECKPROTO._serialized_start=92319 + _SKIPMETADATACHECKPROTO._serialized_end=92432 + _QUICKANSWERSUNITCONVERSIONENABLEDPROTO._serialized_start=92435 + _QUICKANSWERSUNITCONVERSIONENABLEDPROTO._serialized_end=92580 + _QUICKANSWERSDEFINITIONENABLEDPROTO._serialized_start=92583 + _QUICKANSWERSDEFINITIONENABLEDPROTO._serialized_end=92720 + _QUICKANSWERSTRANSLATIONENABLEDPROTO._serialized_start=92723 + _QUICKANSWERSTRANSLATIONENABLEDPROTO._serialized_end=92862 + _QUICKANSWERSENABLEDPROTO._serialized_start=92864 + _QUICKANSWERSENABLEDPROTO._serialized_end=92981 + _CROSTINIPORTFORWARDINGALLOWEDPROTO._serialized_start=92984 + _CROSTINIPORTFORWARDINGALLOWEDPROTO._serialized_end=93121 + _CROSTINIANSIBLEPLAYBOOKPROTO._serialized_start=93123 + _CROSTINIANSIBLEPLAYBOOKPROTO._serialized_end=93248 + _CROSTINIROOTACCESSALLOWEDPROTO._serialized_start=93251 + _CROSTINIROOTACCESSALLOWEDPROTO._serialized_end=93380 + _CROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_start=93383 + _CROSTINIARCADBSIDELOADINGALLOWEDPROTO._serialized_end=93526 + _SYSTEMTERMINALSSHALLOWEDPROTO._serialized_start=93528 + _SYSTEMTERMINALSSHALLOWEDPROTO._serialized_end=93655 + _CROSTINIEXPORTIMPORTUIALLOWEDPROTO._serialized_start=93658 + _CROSTINIEXPORTIMPORTUIALLOWEDPROTO._serialized_end=93795 + _CROSTINIALLOWEDPROTO._serialized_start=93797 + _CROSTINIALLOWEDPROTO._serialized_end=93906 + _IDLEDELAYBATTERYPROTO._serialized_start=93908 + _IDLEDELAYBATTERYPROTO._serialized_end=94019 + _IDLEWARNINGDELAYACPROTO._serialized_start=94021 + _IDLEWARNINGDELAYACPROTO._serialized_end=94136 + _LIDCLOSEACTIONPROTO._serialized_start=94138 + _LIDCLOSEACTIONPROTO._serialized_end=94245 + _PRESENTATIONIDLEDELAYSCALEPROTO._serialized_start=94248 + _PRESENTATIONIDLEDELAYSCALEPROTO._serialized_end=94379 + _SCREENOFFDELAYBATTERYPROTO._serialized_start=94381 + _SCREENOFFDELAYBATTERYPROTO._serialized_end=94502 + _IDLEACTIONPROTO._serialized_start=94504 + _IDLEACTIONPROTO._serialized_end=94603 + _ALLOWSCREENWAKELOCKSPROTO._serialized_start=94605 + _ALLOWSCREENWAKELOCKSPROTO._serialized_end=94724 + _SCREENBRIGHTNESSPERCENTPROTO._serialized_start=94726 + _SCREENBRIGHTNESSPERCENTPROTO._serialized_end=94851 + _SCREENLOCKDELAYSPROTO._serialized_start=94853 + _SCREENLOCKDELAYSPROTO._serialized_end=94964 + _PRESENTATIONSCREENDIMDELAYSCALEPROTO._serialized_start=94967 + _PRESENTATIONSCREENDIMDELAYSCALEPROTO._serialized_end=95108 + _IDLEWARNINGDELAYBATTERYPROTO._serialized_start=95110 + _IDLEWARNINGDELAYBATTERYPROTO._serialized_end=95235 + _SCREENLOCKDELAYACPROTO._serialized_start=95237 + _SCREENLOCKDELAYACPROTO._serialized_end=95350 + _SCREENDIMDELAYBATTERYPROTO._serialized_start=95352 + _SCREENDIMDELAYBATTERYPROTO._serialized_end=95473 + _POWERSMARTDIMENABLEDPROTO._serialized_start=95475 + _POWERSMARTDIMENABLEDPROTO._serialized_end=95594 + _IDLEACTIONBATTERYPROTO._serialized_start=95596 + _IDLEACTIONBATTERYPROTO._serialized_end=95709 + _IDLEDELAYACPROTO._serialized_start=95711 + _IDLEDELAYACPROTO._serialized_end=95812 + _SCREENDIMDELAYACPROTO._serialized_start=95814 + _SCREENDIMDELAYACPROTO._serialized_end=95925 + _POWERMANAGEMENTUSESAUDIOACTIVITYPROTO._serialized_start=95928 + _POWERMANAGEMENTUSESAUDIOACTIVITYPROTO._serialized_end=96071 + _WAITFORINITIALUSERACTIVITYPROTO._serialized_start=96074 + _WAITFORINITIALUSERACTIVITYPROTO._serialized_end=96205 + _POWERMANAGEMENTIDLESETTINGSPROTO._serialized_start=96208 + _POWERMANAGEMENTIDLESETTINGSPROTO._serialized_end=96341 + _USERACTIVITYSCREENDIMDELAYSCALEPROTO._serialized_start=96344 + _USERACTIVITYSCREENDIMDELAYSCALEPROTO._serialized_end=96485 + _IDLEACTIONACPROTO._serialized_start=96487 + _IDLEACTIONACPROTO._serialized_end=96590 + _ALLOWWAKELOCKSPROTO._serialized_start=96592 + _ALLOWWAKELOCKSPROTO._serialized_end=96699 + _DEVICEPOWERADAPTIVECHARGINGENABLEDPROTO._serialized_start=96702 + _DEVICEPOWERADAPTIVECHARGINGENABLEDPROTO._serialized_end=96849 + _SCREENLOCKDELAYBATTERYPROTO._serialized_start=96851 + _SCREENLOCKDELAYBATTERYPROTO._serialized_end=96974 + _SCREENOFFDELAYACPROTO._serialized_start=96976 + _SCREENOFFDELAYACPROTO._serialized_end=97087 + _POWERMANAGEMENTUSESVIDEOACTIVITYPROTO._serialized_start=97090 + _POWERMANAGEMENTUSESVIDEOACTIVITYPROTO._serialized_end=97233 + _REMOTEACCESSHOSTFIREWALLTRAVERSALPROTO._serialized_start=97236 + _REMOTEACCESSHOSTFIREWALLTRAVERSALPROTO._serialized_end=97381 + _REMOTEACCESSHOSTTOKENURLPROTO._serialized_start=97383 + _REMOTEACCESSHOSTTOKENURLPROTO._serialized_end=97510 + _REMOTEACCESSHOSTTOKENVALIDATIONURLPROTO._serialized_start=97513 + _REMOTEACCESSHOSTTOKENVALIDATIONURLPROTO._serialized_end=97660 + _REMOTEACCESSHOSTMATCHUSERNAMEPROTO._serialized_start=97663 + _REMOTEACCESSHOSTMATCHUSERNAMEPROTO._serialized_end=97800 + _REMOTEACCESSHOSTMAXIMUMSESSIONDURATIONMINUTESPROTO._serialized_start=97803 + _REMOTEACCESSHOSTMAXIMUMSESSIONDURATIONMINUTESPROTO._serialized_end=97972 + _REMOTEACCESSHOSTALLOWUIACCESSFORREMOTEASSISTANCEPROTO._serialized_start=97975 + _REMOTEACCESSHOSTALLOWUIACCESSFORREMOTEASSISTANCEPROTO._serialized_end=98150 + _REMOTEACCESSHOSTALLOWREMOTESUPPORTCONNECTIONSPROTO._serialized_start=98153 + _REMOTEACCESSHOSTALLOWREMOTESUPPORTCONNECTIONSPROTO._serialized_end=98322 + _REMOTEACCESSHOSTALLOWREMOTEACCESSCONNECTIONSPROTO._serialized_start=98325 + _REMOTEACCESSHOSTALLOWREMOTEACCESSCONNECTIONSPROTO._serialized_end=98492 + _REMOTEACCESSHOSTALLOWRELAYEDCONNECTIONPROTO._serialized_start=98495 + _REMOTEACCESSHOSTALLOWRELAYEDCONNECTIONPROTO._serialized_end=98650 + _REMOTEACCESSHOSTALLOWGNUBBYAUTHPROTO._serialized_start=98653 + _REMOTEACCESSHOSTALLOWGNUBBYAUTHPROTO._serialized_end=98794 + _REMOTEACCESSHOSTREQUIRETWOFACTORPROTO._serialized_start=98797 + _REMOTEACCESSHOSTREQUIRETWOFACTORPROTO._serialized_end=98940 + _REMOTEACCESSHOSTCLIENTDOMAINPROTO._serialized_start=98943 + _REMOTEACCESSHOSTCLIENTDOMAINPROTO._serialized_end=99078 + _REMOTEACCESSHOSTUDPPORTRANGEPROTO._serialized_start=99081 + _REMOTEACCESSHOSTUDPPORTRANGEPROTO._serialized_end=99216 + _REMOTEACCESSHOSTALLOWFILETRANSFERPROTO._serialized_start=99219 + _REMOTEACCESSHOSTALLOWFILETRANSFERPROTO._serialized_end=99364 + _REMOTEACCESSHOSTTOKENVALIDATIONCERTIFICATEISSUERPROTO._serialized_start=99367 + _REMOTEACCESSHOSTTOKENVALIDATIONCERTIFICATEISSUERPROTO._serialized_end=99542 + _REMOTEACCESSHOSTDOMAINLISTPROTO._serialized_start=99545 + _REMOTEACCESSHOSTDOMAINLISTPROTO._serialized_end=99711 + _REMOTEACCESSHOSTALLOWCLIENTPAIRINGPROTO._serialized_start=99714 + _REMOTEACCESSHOSTALLOWCLIENTPAIRINGPROTO._serialized_end=99861 + _REMOTEACCESSHOSTENABLEUSERINTERFACEPROTO._serialized_start=99864 + _REMOTEACCESSHOSTENABLEUSERINTERFACEPROTO._serialized_end=100013 + _REMOTEACCESSHOSTREQUIRECURTAINPROTO._serialized_start=100016 + _REMOTEACCESSHOSTREQUIRECURTAINPROTO._serialized_end=100155 + _REMOTEACCESSCLIENTFIREWALLTRAVERSALPROTO._serialized_start=100158 + _REMOTEACCESSCLIENTFIREWALLTRAVERSALPROTO._serialized_end=100307 + _REMOTEACCESSHOSTDEBUGOVERRIDEPOLICIESPROTO._serialized_start=100310 + _REMOTEACCESSHOSTDEBUGOVERRIDEPOLICIESPROTO._serialized_end=100463 + _REMOTEACCESSHOSTTALKGADGETPREFIXPROTO._serialized_start=100466 + _REMOTEACCESSHOSTTALKGADGETPREFIXPROTO._serialized_end=100609 + _REMOTEACCESSHOSTCLIENTDOMAINLISTPROTO._serialized_start=100612 + _REMOTEACCESSHOSTCLIENTDOMAINLISTPROTO._serialized_end=100790 + _REMOTEACCESSHOSTCLIPBOARDSIZEBYTESPROTO._serialized_start=100793 + _REMOTEACCESSHOSTCLIPBOARDSIZEBYTESPROTO._serialized_end=100940 + _REMOTEACCESSHOSTDOMAINPROTO._serialized_start=100942 + _REMOTEACCESSHOSTDOMAINPROTO._serialized_end=101065 + _DEFAULTJAVASCRIPTSETTINGPROTO._serialized_start=101067 + _DEFAULTJAVASCRIPTSETTINGPROTO._serialized_end=101194 + _FILESYSTEMWRITEASKFORURLSPROTO._serialized_start=101197 + _FILESYSTEMWRITEASKFORURLSPROTO._serialized_end=101361 + _IMAGESBLOCKEDFORURLSPROTO._serialized_start=101364 + _IMAGESBLOCKEDFORURLSPROTO._serialized_end=101518 + _DEFAULTWEBUSBGUARDSETTINGPROTO._serialized_start=101521 + _DEFAULTWEBUSBGUARDSETTINGPROTO._serialized_end=101650 + _SERIALALLOWUSBDEVICESFORURLSPROTO._serialized_start=101653 + _SERIALALLOWUSBDEVICESFORURLSPROTO._serialized_end=101788 + _LEGACYSAMESITECOOKIEBEHAVIORENABLEDPROTO._serialized_start=101791 + _LEGACYSAMESITECOOKIEBEHAVIORENABLEDPROTO._serialized_end=101940 + _KEYGENBLOCKEDFORURLSPROTO._serialized_start=101943 + _KEYGENBLOCKEDFORURLSPROTO._serialized_end=102097 + _DEFAULTCOOKIESSETTINGPROTO._serialized_start=102099 + _DEFAULTCOOKIESSETTINGPROTO._serialized_end=102220 + _DEFAULTINSECURECONTENTSETTINGPROTO._serialized_start=102223 + _DEFAULTINSECURECONTENTSETTINGPROTO._serialized_end=102360 + _WEBHIDASKFORURLSPROTO._serialized_start=102363 + _WEBHIDASKFORURLSPROTO._serialized_end=102509 + _DEFAULTCLIPBOARDSETTINGPROTO._serialized_start=102511 + _DEFAULTCLIPBOARDSETTINGPROTO._serialized_end=102636 + _DEFAULTFILESYSTEMWRITEGUARDSETTINGPROTO._serialized_start=102639 + _DEFAULTFILESYSTEMWRITEGUARDSETTINGPROTO._serialized_end=102786 + _JAVASCRIPTALLOWEDFORURLSPROTO._serialized_start=102789 + _JAVASCRIPTALLOWEDFORURLSPROTO._serialized_end=102951 + _DEFAULTFILESYSTEMREADGUARDSETTINGPROTO._serialized_start=102954 + _DEFAULTFILESYSTEMREADGUARDSETTINGPROTO._serialized_end=103099 + _SERIALBLOCKEDFORURLSPROTO._serialized_start=103102 + _SERIALBLOCKEDFORURLSPROTO._serialized_end=103256 + _FILESYSTEMREADBLOCKEDFORURLSPROTO._serialized_start=103259 + _FILESYSTEMREADBLOCKEDFORURLSPROTO._serialized_end=103429 + _NOTIFICATIONSBLOCKEDFORURLSPROTO._serialized_start=103432 + _NOTIFICATIONSBLOCKEDFORURLSPROTO._serialized_end=103600 + _JAVASCRIPTJITBLOCKEDFORSITESPROTO._serialized_start=103603 + _JAVASCRIPTJITBLOCKEDFORSITESPROTO._serialized_end=103773 + _INSECURECONTENTALLOWEDFORURLSPROTO._serialized_start=103776 + _INSECURECONTENTALLOWEDFORURLSPROTO._serialized_end=103948 + _SERIALASKFORURLSPROTO._serialized_start=103951 + _SERIALASKFORURLSPROTO._serialized_end=104097 + _WEBHIDALLOWDEVICESFORURLSPROTO._serialized_start=104100 + _WEBHIDALLOWDEVICESFORURLSPROTO._serialized_end=104229 + _WEBUSBASKFORURLSPROTO._serialized_start=104232 + _WEBUSBASKFORURLSPROTO._serialized_end=104378 + _LOCALFONTSALLOWEDFORURLSPROTO._serialized_start=104381 + _LOCALFONTSALLOWEDFORURLSPROTO._serialized_end=104543 + _FILEHANDLINGBLOCKEDFORURLSPROTO._serialized_start=104546 + _FILEHANDLINGBLOCKEDFORURLSPROTO._serialized_end=104712 + _NOTIFICATIONSALLOWEDFORURLSPROTO._serialized_start=104715 + _NOTIFICATIONSALLOWEDFORURLSPROTO._serialized_end=104883 + _DEFAULTSENSORSSETTINGPROTO._serialized_start=104885 + _DEFAULTSENSORSSETTINGPROTO._serialized_end=105006 + _DEFAULTMEDIASTREAMSETTINGPROTO._serialized_start=105009 + _DEFAULTMEDIASTREAMSETTINGPROTO._serialized_end=105138 + _DEFAULTWEBHIDGUARDSETTINGPROTO._serialized_start=105141 + _DEFAULTWEBHIDGUARDSETTINGPROTO._serialized_end=105270 + _PDFLOCALFILEACCESSALLOWEDFORDOMAINSPROTO._serialized_start=105273 + _PDFLOCALFILEACCESSALLOWEDFORDOMAINSPROTO._serialized_end=105457 + _CLIPBOARDBLOCKEDFORURLSPROTO._serialized_start=105460 + _CLIPBOARDBLOCKEDFORURLSPROTO._serialized_end=105620 + _WEBUSBALLOWDEVICESFORURLSPROTO._serialized_start=105623 + _WEBUSBALLOWDEVICESFORURLSPROTO._serialized_end=105752 + _FILESYSTEMSYNCACCESSHANDLEASYNCINTERFACEENABLEDPROTO._serialized_start=105755 + _FILESYSTEMSYNCACCESSHANDLEASYNCINTERFACEENABLEDPROTO._serialized_end=105928 + _KEYGENALLOWEDFORURLSPROTO._serialized_start=105931 + _KEYGENALLOWEDFORURLSPROTO._serialized_end=106085 + _POPUPSBLOCKEDFORURLSPROTO._serialized_start=106088 + _POPUPSBLOCKEDFORURLSPROTO._serialized_end=106242 + _WEBHIDBLOCKEDFORURLSPROTO._serialized_start=106245 + _WEBHIDBLOCKEDFORURLSPROTO._serialized_end=106399 + _DEFAULTIMAGESSETTINGPROTO._serialized_start=106401 + _DEFAULTIMAGESSETTINGPROTO._serialized_end=106520 + _DEFAULTWEBBLUETOOTHGUARDSETTINGPROTO._serialized_start=106523 + _DEFAULTWEBBLUETOOTHGUARDSETTINGPROTO._serialized_end=106664 + _WINDOWPLACEMENTBLOCKEDFORURLSPROTO._serialized_start=106667 + _WINDOWPLACEMENTBLOCKEDFORURLSPROTO._serialized_end=106839 + _DEFAULTPLUGINSSETTINGPROTO._serialized_start=106841 + _DEFAULTPLUGINSSETTINGPROTO._serialized_end=106962 + _FILESYSTEMREADASKFORURLSPROTO._serialized_start=106965 + _FILESYSTEMREADASKFORURLSPROTO._serialized_end=107127 + _INSECURECONTENTBLOCKEDFORURLSPROTO._serialized_start=107130 + _INSECURECONTENTBLOCKEDFORURLSPROTO._serialized_end=107302 + _DEFAULTFILEHANDLINGGUARDSETTINGPROTO._serialized_start=107305 + _DEFAULTFILEHANDLINGGUARDSETTINGPROTO._serialized_end=107446 + _SENSORSALLOWEDFORURLSPROTO._serialized_start=107449 + _SENSORSALLOWEDFORURLSPROTO._serialized_end=107605 + _LEGACYSAMESITECOOKIEBEHAVIORENABLEDFORDOMAINLISTPROTO._serialized_start=107608 + _LEGACYSAMESITECOOKIEBEHAVIORENABLEDFORDOMAINLISTPROTO._serialized_end=107818 + _JAVASCRIPTJITALLOWEDFORSITESPROTO._serialized_start=107821 + _JAVASCRIPTJITALLOWEDFORSITESPROTO._serialized_end=107991 + _LOCALFONTSBLOCKEDFORURLSPROTO._serialized_start=107994 + _LOCALFONTSBLOCKEDFORURLSPROTO._serialized_end=108156 + _DEFAULTPOPUPSSETTINGPROTO._serialized_start=108158 + _DEFAULTPOPUPSSETTINGPROTO._serialized_end=108277 + _WEBUSBBLOCKEDFORURLSPROTO._serialized_start=108280 + _WEBUSBBLOCKEDFORURLSPROTO._serialized_end=108434 + _PLUGINSALLOWEDFORURLSPROTO._serialized_start=108437 + _PLUGINSALLOWEDFORURLSPROTO._serialized_end=108593 + _PLUGINSBLOCKEDFORURLSPROTO._serialized_start=108596 + _PLUGINSBLOCKEDFORURLSPROTO._serialized_end=108752 + _SENSORSBLOCKEDFORURLSPROTO._serialized_start=108755 + _SENSORSBLOCKEDFORURLSPROTO._serialized_end=108911 + _SERIALALLOWALLPORTSFORURLSPROTO._serialized_start=108914 + _SERIALALLOWALLPORTSFORURLSPROTO._serialized_end=109080 + _DEFAULTKEYGENSETTINGPROTO._serialized_start=109082 + _DEFAULTKEYGENSETTINGPROTO._serialized_end=109201 + _FILEHANDLINGALLOWEDFORURLSPROTO._serialized_start=109204 + _FILEHANDLINGALLOWEDFORURLSPROTO._serialized_end=109370 + _WEBHIDALLOWDEVICESWITHHIDUSAGESFORURLSPROTO._serialized_start=109373 + _WEBHIDALLOWDEVICESWITHHIDUSAGESFORURLSPROTO._serialized_end=109528 + _AUTOSELECTCERTIFICATEFORURLSPROTO._serialized_start=109531 + _AUTOSELECTCERTIFICATEFORURLSPROTO._serialized_end=109701 + _DEFAULTLOCALFONTSSETTINGPROTO._serialized_start=109703 + _DEFAULTLOCALFONTSSETTINGPROTO._serialized_end=109830 + _WINDOWPLACEMENTALLOWEDFORURLSPROTO._serialized_start=109833 + _WINDOWPLACEMENTALLOWEDFORURLSPROTO._serialized_end=110005 + _COOKIESBLOCKEDFORURLSPROTO._serialized_start=110008 + _COOKIESBLOCKEDFORURLSPROTO._serialized_end=110164 + _DEFAULTWINDOWPLACEMENTSETTINGPROTO._serialized_start=110167 + _DEFAULTWINDOWPLACEMENTSETTINGPROTO._serialized_end=110304 + _COOKIESALLOWEDFORURLSPROTO._serialized_start=110307 + _COOKIESALLOWEDFORURLSPROTO._serialized_end=110463 + _DEFAULTJAVASCRIPTJITSETTINGPROTO._serialized_start=110466 + _DEFAULTJAVASCRIPTJITSETTINGPROTO._serialized_end=110599 + _POPUPSALLOWEDFORURLSPROTO._serialized_start=110602 + _POPUPSALLOWEDFORURLSPROTO._serialized_end=110756 + _REGISTEREDPROTOCOLHANDLERSPROTO._serialized_start=110759 + _REGISTEREDPROTOCOLHANDLERSPROTO._serialized_end=110890 + _JAVASCRIPTBLOCKEDFORURLSPROTO._serialized_start=110893 + _JAVASCRIPTBLOCKEDFORURLSPROTO._serialized_end=111055 + _FILESYSTEMWRITEBLOCKEDFORURLSPROTO._serialized_start=111058 + _FILESYSTEMWRITEBLOCKEDFORURLSPROTO._serialized_end=111230 + _DEFAULTNOTIFICATIONSSETTINGPROTO._serialized_start=111233 + _DEFAULTNOTIFICATIONSSETTINGPROTO._serialized_end=111366 + _DEFAULTSERIALGUARDSETTINGPROTO._serialized_start=111369 + _DEFAULTSERIALGUARDSETTINGPROTO._serialized_end=111498 + _COOKIESSESSIONONLYFORURLSPROTO._serialized_start=111501 + _COOKIESSESSIONONLYFORURLSPROTO._serialized_end=111665 + _CLIPBOARDALLOWEDFORURLSPROTO._serialized_start=111668 + _CLIPBOARDALLOWEDFORURLSPROTO._serialized_end=111828 + _DEFAULTGEOLOCATIONSETTINGPROTO._serialized_start=111831 + _DEFAULTGEOLOCATIONSETTINGPROTO._serialized_end=111960 + _WEBHIDALLOWALLDEVICESFORURLSPROTO._serialized_start=111963 + _WEBHIDALLOWALLDEVICESFORURLSPROTO._serialized_end=112133 + _IMAGESALLOWEDFORURLSPROTO._serialized_start=112136 + _IMAGESALLOWEDFORURLSPROTO._serialized_end=112290 + _USERBOREALISALLOWEDPROTO._serialized_start=112292 + _USERBOREALISALLOWEDPROTO._serialized_end=112409 + _CLOUDAPAUTHENABLEDPROTO._serialized_start=112411 + _CLOUDAPAUTHENABLEDPROTO._serialized_end=112526 + _IDLETIMEOUTPROTO._serialized_start=112528 + _IDLETIMEOUTPROTO._serialized_end=112629 + _IDLETIMEOUTACTIONSPROTO._serialized_start=112632 + _IDLETIMEOUTACTIONSPROTO._serialized_end=112782 + _CHROMESETTINGSSUBPROTO1._serialized_start=112785 + _CHROMESETTINGSSUBPROTO1._serialized_end=114308 + _CHROMESETTINGSPROTO._serialized_start=114312 + _CHROMESETTINGSPROTO._serialized_end=187456 +# @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_full_runtime_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_full_runtime_pb2.py deleted file mode 100644 index 5a8d919..0000000 --- a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_full_runtime_pb2.py +++ /dev/null
@@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: policy_common_definitions_full_runtime.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n,policy_common_definitions_full_runtime.proto\x12\x15\x65nterprise_management\"\x1d\n\nStringList\x12\x0f\n\x07\x65ntries\x18\x01 \x03(\t\"\x92\x01\n\rPolicyOptions\x12H\n\x04mode\x18\x01 \x01(\x0e\x32/.enterprise_management.PolicyOptions.PolicyMode:\tMANDATORY\"7\n\nPolicyMode\x12\r\n\tMANDATORY\x10\x00\x12\x0f\n\x0bRECOMMENDED\x10\x01\x12\t\n\x05UNSET\x10\x02\"a\n\x12\x42ooleanPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\x08\"a\n\x12IntegerPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\x03\"`\n\x11StringPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\t\"\x87\x01\n\x15StringListPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.enterprise_management.StringListB-Z+chromium/policy/enterprise_management_proto') - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'policy_common_definitions_full_runtime_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'Z+chromium/policy/enterprise_management_proto' - _STRINGLIST._serialized_start=71 - _STRINGLIST._serialized_end=100 - _POLICYOPTIONS._serialized_start=103 - _POLICYOPTIONS._serialized_end=249 - _POLICYOPTIONS_POLICYMODE._serialized_start=194 - _POLICYOPTIONS_POLICYMODE._serialized_end=249 - _BOOLEANPOLICYPROTO._serialized_start=251 - _BOOLEANPOLICYPROTO._serialized_end=348 - _INTEGERPOLICYPROTO._serialized_start=350 - _INTEGERPOLICYPROTO._serialized_end=447 - _STRINGPOLICYPROTO._serialized_start=449 - _STRINGPOLICYPROTO._serialized_end=545 - _STRINGLISTPOLICYPROTO._serialized_start=548 - _STRINGLISTPOLICYPROTO._serialized_end=683 -# @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_pb2.py new file mode 100644 index 0000000..d7288dc --- /dev/null +++ b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/policy_common_definitions_pb2.py
@@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: policy_common_definitions.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fpolicy_common_definitions.proto\x12\x15\x65nterprise_management\"\x1d\n\nStringList\x12\x0f\n\x07\x65ntries\x18\x01 \x03(\t\"\x92\x01\n\rPolicyOptions\x12H\n\x04mode\x18\x01 \x01(\x0e\x32/.enterprise_management.PolicyOptions.PolicyMode:\tMANDATORY\"7\n\nPolicyMode\x12\r\n\tMANDATORY\x10\x00\x12\x0f\n\x0bRECOMMENDED\x10\x01\x12\t\n\x05UNSET\x10\x02\"a\n\x12\x42ooleanPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\x08\"a\n\x12IntegerPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\x03\"`\n\x11StringPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\r\n\x05value\x18\x02 \x01(\t\"\x87\x01\n\x15StringListPolicyProto\x12<\n\x0epolicy_options\x18\x01 \x01(\x0b\x32$.enterprise_management.PolicyOptions\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.enterprise_management.StringListB/H\x03Z+chromium/policy/enterprise_management_proto') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'policy_common_definitions_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'H\003Z+chromium/policy/enterprise_management_proto' + _STRINGLIST._serialized_start=58 + _STRINGLIST._serialized_end=87 + _POLICYOPTIONS._serialized_start=90 + _POLICYOPTIONS._serialized_end=236 + _POLICYOPTIONS_POLICYMODE._serialized_start=181 + _POLICYOPTIONS_POLICYMODE._serialized_end=236 + _BOOLEANPOLICYPROTO._serialized_start=238 + _BOOLEANPOLICYPROTO._serialized_end=335 + _INTEGERPOLICYPROTO._serialized_start=337 + _INTEGERPOLICYPROTO._serialized_end=434 + _STRINGPOLICYPROTO._serialized_start=436 + _STRINGPOLICYPROTO._serialized_end=532 + _STRINGLISTPOLICYPROTO._serialized_start=535 + _STRINGLISTPOLICYPROTO._serialized_end=670 +# @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/traffic_annotation_pb2.py b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/traffic_annotation_pb2.py index 86f368f4..76d0c70 100644 --- a/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/traffic_annotation_pb2.py +++ b/tools/traffic_annotation/scripts/test_data/out/Debug/pyproto/chrome/browser/privacy/traffic_annotation_pb2.py
@@ -11,40 +11,42 @@ _sym_db = _symbol_database.Default() -import chrome_settings_full_runtime_pb2 as chrome__settings__full__runtime__pb2 +import chrome_settings_pb2 as chrome__settings__pb2 +import chrome_device_policy_pb2 as chrome__device__policy__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18traffic_annotation.proto\x12\x12traffic_annotation\x1a\"chrome_settings_full_runtime.proto\"\xae\x0f\n\x18NetworkTrafficAnnotation\x12\x11\n\tunique_id\x18\x01 \x01(\t\x12J\n\x06source\x18\x02 \x01(\x0b\x32:.traffic_annotation.NetworkTrafficAnnotation.TrafficSource\x12P\n\tsemantics\x18\x03 \x01(\x0b\x32=.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics\x12J\n\x06policy\x18\x04 \x01(\x0b\x32:.traffic_annotation.NetworkTrafficAnnotation.TrafficPolicy\x12\x10\n\x08\x63omments\x18\x05 \x01(\t\x1a@\n\rTrafficSource\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x0c\n\x04line\x18\x03 \x01(\x05\x12\x13\n\x0b\x63\x61ll_number\x18\x04 \x01(\x05\x1a\xe6\t\n\x10TrafficSemantics\x12\x0e\n\x06sender\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0f\n\x07trigger\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\t\x12^\n\x0b\x64\x65stination\x18\x05 \x01(\x0e\x32I.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Destination\x12\x19\n\x11\x64\x65stination_other\x18\x06 \x01(\t\x12X\n\x08internal\x18\x07 \x01(\x0b\x32\x46.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Internal\x12Y\n\tuser_data\x18\x08 \x01(\x0b\x32\x46.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.UserData\x12\x15\n\rlast_reviewed\x18\t \x01(\t\x1a\x98\x01\n\x08Internal\x12`\n\x08\x63ontacts\x18\x01 \x03(\x0b\x32N.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Internal.Contact\x1a*\n\x07\x43ontact\x12\x0f\n\x05\x65mail\x18\x01 \x01(\tH\x00\x42\x0e\n\x0c\x63ontact_type\x1a\xcd\x04\n\x08UserData\x12\x61\n\x04type\x18\x01 \x03(\x0e\x32S.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.UserData.UserDataType\"\xdd\x03\n\x0cUserDataType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x10\n\x0c\x41\x43\x43\x45SS_TOKEN\x10\x01\x12\x0b\n\x07\x41\x44\x44RESS\x10\x02\x12\x0e\n\nANDROID_ID\x10\x03\x12\x07\n\x03\x41GE\x10\x04\x12\x12\n\x0e\x41RBITRARY_DATA\x10\x05\x12\x0e\n\nBIRTH_DATE\x10\x06\x12\x0f\n\x0b\x43REDENTIALS\x10\x07\x12\x14\n\x10\x43REDIT_CARD_DATA\x10\x08\x12\r\n\tDEVICE_ID\x10\t\x12\t\n\x05\x45MAIL\x10\n\x12\r\n\tFILE_DATA\x10\x0b\x12\x0b\n\x07GAIA_ID\x10\x0c\x12\n\n\x06GENDER\x10\r\x12\x11\n\rGOVERNMENT_ID\x10\x0e\x12\t\n\x05IMAGE\x10\x0f\x12\x0e\n\nIP_ADDRESS\x10\x10\x12\x13\n\x0fLOCATION_COARSE\x10\x11\x12\x14\n\x10LOCATION_PRECISE\x10\x12\x12\x08\n\x04NAME\x10\x13\x12\t\n\x05PHONE\x10\x14\x12\x10\n\x0cPROFILE_DATA\x10\x15\x12\x11\n\rSENSITIVE_URL\x10\x16\x12\x0e\n\nSESSION_ID\x10\x17\x12\r\n\tTIMESTAMP\x10\x18\x12\x0e\n\nUSER_AGENT\x10\x19\x12\x10\n\x0cUSER_CONTENT\x10\x1a\x12\x0c\n\x08USERNAME\x10\x1b\x12\n\n\x05OTHER\x10\xe7\x07\x12\t\n\x04NONE\x10\xe8\x07\"\\\n\x0b\x44\x65stination\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0b\n\x07WEBSITE\x10\x01\x12\x18\n\x14GOOGLE_OWNED_SERVICE\x10\x02\x12\t\n\x05LOCAL\x10\x03\x12\n\n\x05OTHER\x10\xe8\x07\x1a\xd7\x02\n\rTrafficPolicy\x12\x62\n\x0f\x63ookies_allowed\x18\x01 \x01(\x0e\x32I.traffic_annotation.NetworkTrafficAnnotation.TrafficPolicy.CookiesAllowed\x12\x15\n\rcookies_store\x18\x02 \x01(\t\x12\x0f\n\x07setting\x18\x03 \x01(\t\x12\x41\n\rchrome_policy\x18\x04 \x03(\x0b\x32*.enterprise_management.ChromeSettingsProto\x12&\n\x1epolicy_exception_justification\x18\x05 \x01(\t\x12\x1b\n\x13\x64\x65precated_policies\x18\x06 \x03(\t\"2\n\x0e\x43ookiesAllowed\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x06\n\x02NO\x10\x01\x12\x07\n\x03YES\x10\x02\"u\n!ExtractedNetworkTrafficAnnotation\x12P\n\x1anetwork_traffic_annotation\x18\x01 \x03(\x0b\x32,.traffic_annotation.NetworkTrafficAnnotation\"x\n$WhitelistedNetworkTrafficAnnotations\x12P\n\x1anetwork_traffic_annotation\x18\x01 \x03(\x0b\x32,.traffic_annotation.NetworkTrafficAnnotation\"\xec\x01\n\x19NetworkTrafficAnnotations\x12\x64\n%extracted_network_traffic_annotations\x18\x01 \x01(\x0b\x32\x35.traffic_annotation.ExtractedNetworkTrafficAnnotation\x12i\n\'whitelisted_network_traffic_annotations\x18\x02 \x01(\x0b\x32\x38.traffic_annotation.WhitelistedNetworkTrafficAnnotationsb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18traffic_annotation.proto\x12\x12traffic_annotation\x1a\x15\x63hrome_settings.proto\x1a\x1a\x63hrome_device_policy.proto\"\xfe\x0f\n\x18NetworkTrafficAnnotation\x12\x11\n\tunique_id\x18\x01 \x01(\t\x12J\n\x06source\x18\x02 \x01(\x0b\x32:.traffic_annotation.NetworkTrafficAnnotation.TrafficSource\x12P\n\tsemantics\x18\x03 \x01(\x0b\x32=.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics\x12J\n\x06policy\x18\x04 \x01(\x0b\x32:.traffic_annotation.NetworkTrafficAnnotation.TrafficPolicy\x12\x10\n\x08\x63omments\x18\x05 \x01(\t\x1a@\n\rTrafficSource\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x0c\n\x04line\x18\x03 \x01(\x05\x12\x13\n\x0b\x63\x61ll_number\x18\x04 \x01(\x05\x1a\xe6\t\n\x10TrafficSemantics\x12\x0e\n\x06sender\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0f\n\x07trigger\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\t\x12^\n\x0b\x64\x65stination\x18\x05 \x01(\x0e\x32I.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Destination\x12\x19\n\x11\x64\x65stination_other\x18\x06 \x01(\t\x12X\n\x08internal\x18\x07 \x01(\x0b\x32\x46.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Internal\x12Y\n\tuser_data\x18\x08 \x01(\x0b\x32\x46.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.UserData\x12\x15\n\rlast_reviewed\x18\t \x01(\t\x1a\x98\x01\n\x08Internal\x12`\n\x08\x63ontacts\x18\x01 \x03(\x0b\x32N.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.Internal.Contact\x1a*\n\x07\x43ontact\x12\x0f\n\x05\x65mail\x18\x01 \x01(\tH\x00\x42\x0e\n\x0c\x63ontact_type\x1a\xcd\x04\n\x08UserData\x12\x61\n\x04type\x18\x01 \x03(\x0e\x32S.traffic_annotation.NetworkTrafficAnnotation.TrafficSemantics.UserData.UserDataType\"\xdd\x03\n\x0cUserDataType\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x10\n\x0c\x41\x43\x43\x45SS_TOKEN\x10\x01\x12\x0b\n\x07\x41\x44\x44RESS\x10\x02\x12\x0e\n\nANDROID_ID\x10\x03\x12\x07\n\x03\x41GE\x10\x04\x12\x12\n\x0e\x41RBITRARY_DATA\x10\x05\x12\x0e\n\nBIRTH_DATE\x10\x06\x12\x0f\n\x0b\x43REDENTIALS\x10\x07\x12\x14\n\x10\x43REDIT_CARD_DATA\x10\x08\x12\r\n\tDEVICE_ID\x10\t\x12\t\n\x05\x45MAIL\x10\n\x12\r\n\tFILE_DATA\x10\x0b\x12\x0b\n\x07GAIA_ID\x10\x0c\x12\n\n\x06GENDER\x10\r\x12\x11\n\rGOVERNMENT_ID\x10\x0e\x12\t\n\x05IMAGE\x10\x0f\x12\x0e\n\nIP_ADDRESS\x10\x10\x12\x13\n\x0fLOCATION_COARSE\x10\x11\x12\x14\n\x10LOCATION_PRECISE\x10\x12\x12\x08\n\x04NAME\x10\x13\x12\t\n\x05PHONE\x10\x14\x12\x10\n\x0cPROFILE_DATA\x10\x15\x12\x11\n\rSENSITIVE_URL\x10\x16\x12\x0e\n\nSESSION_ID\x10\x17\x12\r\n\tTIMESTAMP\x10\x18\x12\x0e\n\nUSER_AGENT\x10\x19\x12\x10\n\x0cUSER_CONTENT\x10\x1a\x12\x0c\n\x08USERNAME\x10\x1b\x12\n\n\x05OTHER\x10\xe7\x07\x12\t\n\x04NONE\x10\xe8\x07\"\\\n\x0b\x44\x65stination\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x0b\n\x07WEBSITE\x10\x01\x12\x18\n\x14GOOGLE_OWNED_SERVICE\x10\x02\x12\t\n\x05LOCAL\x10\x03\x12\n\n\x05OTHER\x10\xe8\x07\x1a\xa7\x03\n\rTrafficPolicy\x12\x62\n\x0f\x63ookies_allowed\x18\x01 \x01(\x0e\x32I.traffic_annotation.NetworkTrafficAnnotation.TrafficPolicy.CookiesAllowed\x12\x15\n\rcookies_store\x18\x02 \x01(\t\x12\x0f\n\x07setting\x18\x03 \x01(\t\x12\x41\n\rchrome_policy\x18\x04 \x03(\x0b\x32*.enterprise_management.ChromeSettingsProto\x12N\n\x14\x63hrome_device_policy\x18\x07 \x03(\x0b\x32\x30.enterprise_management.ChromeDeviceSettingsProto\x12&\n\x1epolicy_exception_justification\x18\x05 \x01(\t\x12\x1b\n\x13\x64\x65precated_policies\x18\x06 \x03(\t\"2\n\x0e\x43ookiesAllowed\x12\x0f\n\x0bUNSPECIFIED\x10\x00\x12\x06\n\x02NO\x10\x01\x12\x07\n\x03YES\x10\x02\"u\n!ExtractedNetworkTrafficAnnotation\x12P\n\x1anetwork_traffic_annotation\x18\x01 \x03(\x0b\x32,.traffic_annotation.NetworkTrafficAnnotation\"x\n$WhitelistedNetworkTrafficAnnotations\x12P\n\x1anetwork_traffic_annotation\x18\x01 \x03(\x0b\x32,.traffic_annotation.NetworkTrafficAnnotation\"\xec\x01\n\x19NetworkTrafficAnnotations\x12\x64\n%extracted_network_traffic_annotations\x18\x01 \x01(\x0b\x32\x35.traffic_annotation.ExtractedNetworkTrafficAnnotation\x12i\n\'whitelisted_network_traffic_annotations\x18\x02 \x01(\x0b\x32\x38.traffic_annotation.WhitelistedNetworkTrafficAnnotationsB\x02H\x03\x62\x06proto3') _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'traffic_annotation_pb2', globals()) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None - _NETWORKTRAFFICANNOTATION._serialized_start=85 - _NETWORKTRAFFICANNOTATION._serialized_end=2051 - _NETWORKTRAFFICANNOTATION_TRAFFICSOURCE._serialized_start=384 - _NETWORKTRAFFICANNOTATION_TRAFFICSOURCE._serialized_end=448 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS._serialized_start=451 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS._serialized_end=1705 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL._serialized_start=867 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL._serialized_end=1019 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL_CONTACT._serialized_start=977 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL_CONTACT._serialized_end=1019 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA._serialized_start=1022 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA._serialized_end=1611 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA_USERDATATYPE._serialized_start=1134 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA_USERDATATYPE._serialized_end=1611 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_DESTINATION._serialized_start=1613 - _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_DESTINATION._serialized_end=1705 - _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY._serialized_start=1708 - _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY._serialized_end=2051 - _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY_COOKIESALLOWED._serialized_start=2001 - _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY_COOKIESALLOWED._serialized_end=2051 - _EXTRACTEDNETWORKTRAFFICANNOTATION._serialized_start=2053 - _EXTRACTEDNETWORKTRAFFICANNOTATION._serialized_end=2170 - _WHITELISTEDNETWORKTRAFFICANNOTATIONS._serialized_start=2172 - _WHITELISTEDNETWORKTRAFFICANNOTATIONS._serialized_end=2292 - _NETWORKTRAFFICANNOTATIONS._serialized_start=2295 - _NETWORKTRAFFICANNOTATIONS._serialized_end=2531 + DESCRIPTOR._serialized_options = b'H\003' + _NETWORKTRAFFICANNOTATION._serialized_start=100 + _NETWORKTRAFFICANNOTATION._serialized_end=2146 + _NETWORKTRAFFICANNOTATION_TRAFFICSOURCE._serialized_start=399 + _NETWORKTRAFFICANNOTATION_TRAFFICSOURCE._serialized_end=463 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS._serialized_start=466 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS._serialized_end=1720 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL._serialized_start=882 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL._serialized_end=1034 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL_CONTACT._serialized_start=992 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_INTERNAL_CONTACT._serialized_end=1034 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA._serialized_start=1037 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA._serialized_end=1626 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA_USERDATATYPE._serialized_start=1149 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_USERDATA_USERDATATYPE._serialized_end=1626 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_DESTINATION._serialized_start=1628 + _NETWORKTRAFFICANNOTATION_TRAFFICSEMANTICS_DESTINATION._serialized_end=1720 + _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY._serialized_start=1723 + _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY._serialized_end=2146 + _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY_COOKIESALLOWED._serialized_start=2096 + _NETWORKTRAFFICANNOTATION_TRAFFICPOLICY_COOKIESALLOWED._serialized_end=2146 + _EXTRACTEDNETWORKTRAFFICANNOTATION._serialized_start=2148 + _EXTRACTEDNETWORKTRAFFICANNOTATION._serialized_end=2265 + _WHITELISTEDNETWORKTRAFFICANNOTATIONS._serialized_start=2267 + _WHITELISTEDNETWORKTRAFFICANNOTATIONS._serialized_end=2387 + _NETWORKTRAFFICANNOTATIONS._serialized_start=2390 + _NETWORKTRAFFICANNOTATIONS._serialized_end=2626 # @@protoc_insertion_point(module_scope)
diff --git a/tools/traffic_annotation/scripts/update_annotations_doc.py.vpython3 b/tools/traffic_annotation/scripts/update_annotations_doc.py.vpython3 index 4cdf1d1..f27b26c 100644 --- a/tools/traffic_annotation/scripts/update_annotations_doc.py.vpython3 +++ b/tools/traffic_annotation/scripts/update_annotations_doc.py.vpython3
@@ -57,7 +57,7 @@ wheel: < name: "infra/python/wheels/infra_libs-py2_py3" - version: "version:2.3.0" + version: "version:2.4.0" > wheel: <
diff --git a/tools/traffic_annotation/scripts/update_annotations_sheet.py.vpython3 b/tools/traffic_annotation/scripts/update_annotations_sheet.py.vpython3 index 4cdf1d1..f27b26c 100644 --- a/tools/traffic_annotation/scripts/update_annotations_sheet.py.vpython3 +++ b/tools/traffic_annotation/scripts/update_annotations_sheet.py.vpython3
@@ -57,7 +57,7 @@ wheel: < name: "infra/python/wheels/infra_libs-py2_py3" - version: "version:2.3.0" + version: "version:2.4.0" > wheel: <
diff --git a/tools/typescript/definitions/quick_unlock_private.d.ts b/tools/typescript/definitions/quick_unlock_private.d.ts index 341f1e2..999414b6 100644 --- a/tools/typescript/definitions/quick_unlock_private.d.ts +++ b/tools/typescript/definitions/quick_unlock_private.d.ts
@@ -12,7 +12,17 @@ lifetimeSeconds: number; } + export enum QuickUnlockMode { + PIN = 'PIN', + } + + // TODO(crbug/1368302) Update to use promises instead of callback export function getAuthToken( accountPassword: string, onComplete: (info: TokenInfo) => void): void; + + // TODO(crbug/1368302) Update to use promises instead of callback + export function setModes( + token: string, modes: QuickUnlockMode[], credentials: string[], + onComplete: (success: boolean) => void): void; } }
diff --git a/tools/win/DebugVisualizers/blink.natvis b/tools/win/DebugVisualizers/blink.natvis index 65efb3f..40620d9 100644 --- a/tools/win/DebugVisualizers/blink.natvis +++ b/tools/win/DebugVisualizers/blink.natvis
@@ -173,7 +173,7 @@ </Type> <!-- Component build version --> <Type Name="blink::WebString"> - <DisplayString>{(wtf.dll!WTF::StringImpl*)(impl_.ptr_)}</DisplayString> + <DisplayString>{(blink_platform_wtf.dll!WTF::StringImpl*)(impl_.ptr_)}</DisplayString> </Type> <!-- Non-component build version --> <Type Name="blink::WebString" Priority="Low">
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc index 03e7c44..c4851e1 100644 --- a/ui/accessibility/accessibility_features.cc +++ b/ui/accessibility/accessibility_features.cc
@@ -326,6 +326,15 @@ return base::FeatureList::IsEnabled(::features::kAccessibilityService); } +BASE_FEATURE(kChromeVoxQ1FastTrackFeatures, + "ChromeVoxQ1FastTrackFeatures", + base::FEATURE_DISABLED_BY_DEFAULT); + +bool IsChromeVoxQ1FastTrackFeaturesEnabled() { + return base::FeatureList::IsEnabled( + ::features::kChromeVoxQ1FastTrackFeatures); +} + #endif // !BUILDFLAG(IS_ANDROID) } // namespace features
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h index 5d1cc6f..e999a47 100644 --- a/ui/accessibility/accessibility_features.h +++ b/ui/accessibility/accessibility_features.h
@@ -254,6 +254,12 @@ // to the accessibility tree. AX_BASE_EXPORT bool IsLayoutExtractionEnabled(); +// Enables ChromeVox Q1 Fast-Track Features. +AX_BASE_EXPORT BASE_DECLARE_FEATURE(kChromeVoxQ1FastTrackFeatures); + +// Returns true if ChromeVox Q1 Fast-Track Features are enabled. +AX_BASE_EXPORT bool IsChromeVoxQ1FastTrackFeaturesEnabled(); + // Enables the experimental Accessibility Service. AX_BASE_EXPORT BASE_DECLARE_FEATURE(kAccessibilityService);
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm index 02fed08..776a2fe 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa.mm +++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -813,11 +813,10 @@ } - (NSString*)descriptionIfFromAriaDescription { - // TODO(crbug.com/1373178): Eventually this should include the DescriptionFrom - // for content from aria-describedby, kRelatedContent. ax::mojom::DescriptionFrom descFrom = static_cast<ax::mojom::DescriptionFrom>( _node->GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom)); - if (descFrom == ax::mojom::DescriptionFrom::kAriaDescription) { + if (descFrom == ax::mojom::DescriptionFrom::kAriaDescription || + descFrom == ax::mojom::DescriptionFrom::kRelatedElement) { return [self getStringAttribute:ax::mojom::StringAttribute::kDescription]; } return nil;
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h index 741148a..9cc608c 100644 --- a/ui/accessibility/platform/ax_platform_node_delegate.h +++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -77,7 +77,7 @@ using AXRange = ui::AXRange<AXPosition::element_type>; AXPlatformNodeDelegate(); - + AXPlatformNodeDelegate(const AXPlatformNodeDelegate&) = delete; AXPlatformNodeDelegate& operator=(const AXPlatformNodeDelegate&) = delete;
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc index cc3f98b..eb169b8 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
@@ -128,6 +128,17 @@ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GETVISIBLERANGES); UIA_VALIDATE_TEXTPROVIDER_CALL(); + // Whether we expose embedded object characters for nodes is managed by the + // |g_ax_embedded_object_behavior| global variable set in ax_node_position.cc. + // When on Windows, this variable is always set to kExposeCharacter... which + // is incorrect if we run UIA-specific code relating to computing text content + // of nodes that themselves do not have text, such as `<p>` elements. To avoid + // problems caused by that, we use the following + // ScopedAXEmbeddedObjectBehaviorSetter to modify the value of the global + // variable to what is really expected on UIA. + + ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior( + AXEmbeddedObjectBehavior::kSuppressCharacter); const AXPlatformNodeDelegate* delegate = owner()->GetDelegate(); // Get the Clipped Frame Bounds of the current node, not from the root,
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc index ed5619b..ea16860 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
@@ -901,6 +901,103 @@ EXPECT_EQ(*GetEnd(actual_range.Get()), *expected_end); } +TEST_F(AXPlatformNodeTextProviderTest, + ITextProviderWinGetVisibleRangesInContentEditable) { + // ++1 kRootWebArea + // ++++2 kGenericContainer + // ++++++3 kParagraph + // ++++++++4 kStaticText + // ++++++++++5 kInlineTextBox + + ui::AXNodeData root_1; + ui::AXNodeData generic_container_2; + ui::AXNodeData paragraph_3; + ui::AXNodeData static_text_4; + ui::AXNodeData inline_box_5; + + root_1.id = 1; + generic_container_2.id = 2; + paragraph_3.id = 3; + static_text_4.id = 4; + inline_box_5.id = 5; + + root_1.role = ax::mojom::Role::kRootWebArea; + root_1.child_ids = {generic_container_2.id}; + + generic_container_2.role = ax::mojom::Role::kGenericContainer; + generic_container_2.child_ids = {paragraph_3.id}; + generic_container_2.AddState(ax::mojom::State::kRichlyEditable); + generic_container_2.AddState(ax::mojom::State::kEditable); + generic_container_2.AddBoolAttribute( + ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot, true); + + paragraph_3.role = ax::mojom::Role::kParagraph; + paragraph_3.child_ids = {static_text_4.id}; + + static_text_4.role = ax::mojom::Role::kStaticText; + static_text_4.SetName("hello"); + static_text_4.child_ids = {inline_box_5.id}; + + inline_box_5.role = ax::mojom::Role::kInlineTextBox; + inline_box_5.SetName("hello"); + + ui::AXTreeUpdate update; + ui::AXTreeData tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_1.id; + update.nodes = {root_1, generic_container_2, paragraph_3, static_text_4, + inline_box_5}; + + Init(update); + + AXNode* div_node = GetRoot()->children()[0]; + + ComPtr<IRawElementProviderSimple> div_com = + QueryInterfaceFromNode<IRawElementProviderSimple>(div_node); + + ComPtr<ITextProvider> text_provider; + EXPECT_HRESULT_SUCCEEDED( + div_com->GetPatternProvider(UIA_TextPatternId, &text_provider)); + + base::win::ScopedSafearray text_provider_ranges; + EXPECT_HRESULT_SUCCEEDED( + text_provider->GetVisibleRanges(text_provider_ranges.Receive())); + + ITextRangeProvider** array_data; + ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( + text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); + + ComPtr<AXPlatformNodeTextProviderWin> platform_node_text_provider; + text_provider->QueryInterface(IID_PPV_ARGS(&platform_node_text_provider)); + + AXPlatformNodeWin* owner = GetOwner(platform_node_text_provider.Get()); + + ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior( + AXEmbeddedObjectBehavior::kSuppressCharacter); + AXNodePosition::AXPositionInstance expected_start = + owner->GetDelegate()->CreateTextPositionAt(0); + AXNodePosition::AXPositionInstance expected_end = + expected_start->CreatePositionAtEndOfAnchor(); + + ComPtr<AXPlatformNodeTextRangeProviderWin> actual_range; + array_data[0]->QueryInterface(IID_PPV_ARGS(&actual_range)); + + EXPECT_EQ(*GetStart(actual_range.Get()), *expected_start); + EXPECT_EQ(*GetEnd(actual_range.Get()), *expected_end); + + EXPECT_EQ(expected_start->text_offset(), 0); + EXPECT_EQ(GetStart(actual_range.Get())->text_offset(), + expected_start->text_offset()); + EXPECT_EQ(expected_end->text_offset(), 5); + EXPECT_EQ(GetEnd(actual_range.Get())->text_offset(), + expected_end->text_offset()); + + ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); + text_provider_ranges.Reset(); +} + TEST_F(AXPlatformNodeTextProviderTest, ITextProviderGetConversionTarget) { AXNodeData text_data; text_data.id = 2;
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index 28550aa..da0c504 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -468,9 +468,6 @@ BOOL backwards, BOOL ignore_case, ITextRangeProvider** result) { - WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); - WIN_ACCESSIBILITY_API_PERF_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); - UIA_VALIDATE_TEXTRANGEPROVIDER_CALL_1_IN_1_OUT(string, result); // On Windows, there's a dichotomy in the definition of a text offset in a // text position between different APIs: // - on UIA, a text offset translates to the offset in the text itself @@ -494,6 +491,17 @@ ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior( AXEmbeddedObjectBehavior::kSuppressCharacter); + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); + WIN_ACCESSIBILITY_API_PERF_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); + // The following has to be called after setting the + // ax_embedded_object_behavior. This is because it can modify `this`'s `start` + // and `end`, and it will do so assuming + // `AXEmbeddedObjectBehavior::kExposeCharacter` if we do not set it to + // `kSuppressCharacter' above. This would lead to incorrect behavior where the + // `text_range` length = 1, since that is the length of the embedded object + // character. + UIA_VALIDATE_TEXTRANGEPROVIDER_CALL_1_IN_1_OUT(string, result); + std::u16string search_string = base::WideToUTF16(string); if (search_string.length() <= 0) return E_INVALIDARG;
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index 8e86944..886cc2e 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -5327,6 +5327,98 @@ } TEST_F(AXPlatformNodeTextRangeProviderTest, + TestTextRangeProviderWinFindTextInContentEditable) { + // Before the commit that added this test, we had incorrect behavior when + // finding text in the following tree scenario: + // ++1 kRootWebArea + // ++++2 kGenericContainer + // ++++++3 kParagraph + // ++++++++4 kStaticText + // ++++++++++5 kInlineTextBox + // Before, UIA FindText would modify the range's `start` and `end` before + // finding any text in some situations. It would do so according to + // `AXEmbeddedObjectBehavior::kExpose`, which meant that in this case, + // the `<p>` element would be represented by the embedded object character, + // even if inside the `<p>` element we have the text "hello", `FindText` would + // modify the range to just 'h' since the length of the embedded object + // character is 1. + // + // This is an important edge case since we can see this behavior and tree + // structure on comments on apps like Word for the web and Google Docs. + // + // See `AXPLatformNodeTextRangeProvider::FindText` for a more detailed + // explanation of the embedded object character. + + ui::AXNodeData root_1; + ui::AXNodeData generic_container_2; + ui::AXNodeData paragraph_3; + ui::AXNodeData static_text_4; + ui::AXNodeData inline_box_5; + + root_1.id = 1; + generic_container_2.id = 2; + paragraph_3.id = 3; + static_text_4.id = 4; + inline_box_5.id = 5; + + root_1.role = ax::mojom::Role::kRootWebArea; + root_1.child_ids = {generic_container_2.id}; + + generic_container_2.role = ax::mojom::Role::kGenericContainer; + generic_container_2.child_ids = {paragraph_3.id}; + generic_container_2.AddState(ax::mojom::State::kRichlyEditable); + generic_container_2.AddState(ax::mojom::State::kEditable); + generic_container_2.AddBoolAttribute( + ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot, true); + + paragraph_3.role = ax::mojom::Role::kParagraph; + paragraph_3.child_ids = {static_text_4.id}; + + static_text_4.role = ax::mojom::Role::kStaticText; + static_text_4.SetName("foo"); + static_text_4.child_ids = {inline_box_5.id}; + + inline_box_5.role = ax::mojom::Role::kInlineTextBox; + inline_box_5.SetName("foo"); + + ui::AXTreeUpdate update; + ui::AXTreeData tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_1.id; + update.nodes = {root_1, generic_container_2, paragraph_3, static_text_4, + inline_box_5}; + + Init(update); + + AXNode* div_node = GetNodeFromTree(tree_data.tree_id, generic_container_2.id); + + AXPlatformNodeWin* owner = + static_cast<AXPlatformNodeWin*>(AXPlatformNodeFromNode(div_node)); + + // start: TextPosition, anchor_id=3, text_offset=0, annotated_text=<f>oo + // end : TextPosition, anchor_id=3, text_offset=3, annotated_text=foo<> + ComPtr<AXPlatformNodeTextRangeProviderWin> text_range_provider; + { + ScopedAXEmbeddedObjectBehaviorSetter ax_embedded_object_behavior( + AXEmbeddedObjectBehavior::kSuppressCharacter); + CreateTextRangeProviderWin( + text_range_provider, owner, + /*start_anchor=*/div_node, /*start_offset=*/0, + /*start_affinity*/ ax::mojom::TextAffinity::kDownstream, + /*end_anchor=*/div_node, /*end_offset=*/3, + /*end_affinity*/ ax::mojom::TextAffinity::kDownstream); + } + + base::win::ScopedBstr find_string(L"foo"); + Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider_found; + text_range_provider->FindText(find_string.Get(), false, false, + &text_range_provider_found); + ASSERT_TRUE(text_range_provider_found.Get()); +} + +TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderFindTextBackwards) { Init(BuildTextDocument({"text", "some", "text"}, false /* build_word_boundaries_offsets */,
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 9a20af9d..d903d3e 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -2056,8 +2056,9 @@ AXPlatformNodeWin* win_target = static_cast<AXPlatformNodeWin*>(target); (*targets)[index] = static_cast<IAccessible*>(win_target); (*targets)[index]->AddRef(); - if (++index > count) + if (++index >= count) { break; + } } } *n_targets = index;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index a7b69a5..7a22a08 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -2109,11 +2109,70 @@ target.Reset(); } +TEST_F(AXPlatformNodeWinTest, IAccessible2_TestRelationTargetsOfType) { + AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kRootWebArea; + root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2, 3}); + + AXNodeData child1; + child1.id = 2; + child1.role = ax::mojom::Role::kStaticText; + + root.child_ids.push_back(2); + + AXNodeData child2; + child2.id = 3; + child2.role = ax::mojom::Role::kStaticText; + std::vector<AXNodeID> labelledby_ids = {1, 4}; + child2.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds, + labelledby_ids); + + root.child_ids.push_back(3); + + AXNodeData child3; + child3.id = 4; + child3.role = ax::mojom::Role::kStaticText; + child3.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2}); + + root.child_ids.push_back(4); + + Init(root, child1, child2, child3); + ComPtr<IAccessible> root_iaccessible(GetRootIAccessible()); + ComPtr<IAccessible2_2> root_iaccessible2 = ToIAccessible2_2(root_iaccessible); + + ComPtr<IDispatch> result; + EXPECT_EQ(S_OK, root_iaccessible2->get_accChild(ScopedVariant(1), &result)); + ComPtr<IAccessible2_2> ax_child1; + EXPECT_EQ(S_OK, result.As(&ax_child1)); + result.Reset(); + + EXPECT_EQ(S_OK, root_iaccessible2->get_accChild(ScopedVariant(2), &result)); + ComPtr<IAccessible2_2> ax_child2; + EXPECT_EQ(S_OK, result.As(&ax_child2)); + result.Reset(); + + { + ScopedBstr type(L"details"); + IUnknown** targets; + LONG n_targets; + EXPECT_EQ(S_OK, root_iaccessible2->get_relationTargetsOfType( + type.Get(), 0, &targets, &n_targets)); + ASSERT_EQ(2, n_targets); + CoTaskMemFree(targets); + + EXPECT_EQ(S_OK, root_iaccessible2->get_relationTargetsOfType( + type.Get(), 1, &targets, &n_targets)); + ASSERT_EQ(1, n_targets); + CoTaskMemFree(targets); + } +} + TEST_F(AXPlatformNodeWinTest, DISABLED_TestRelationTargetsOfType) { AXNodeData root; root.id = 1; root.role = ax::mojom::Role::kRootWebArea; - root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2}); + root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2, 3}); AXNodeData child1; child1.id = 2; @@ -2162,7 +2221,7 @@ IUnknown** targets; LONG n_targets; EXPECT_EQ(S_OK, root_iaccessible2->get_relationTargetsOfType( - type.Get(), 0, &targets, &n_targets)); + type.Get(), 1, &targets, &n_targets)); ASSERT_EQ(1, n_targets); EXPECT_EQ(ax_child1.Get(), targets[0]); CoTaskMemFree(targets);
diff --git a/ui/accessibility/platform/child_iterator.h b/ui/accessibility/platform/child_iterator.h index ceb02e3..0e2dc35 100644 --- a/ui/accessibility/platform/child_iterator.h +++ b/ui/accessibility/platform/child_iterator.h
@@ -26,10 +26,11 @@ virtual ChildIterator& operator--() = 0; virtual gfx::NativeViewAccessible GetNativeViewAccessible() const = 0; virtual absl::optional<size_t> GetIndexInParent() const = 0; + virtual AXPlatformNodeDelegate* get() const = 0; virtual AXPlatformNodeDelegate& operator*() const = 0; virtual AXPlatformNodeDelegate* operator->() const = 0; }; } // namespace ui -#endif // UI_ACCESSIBILITY_PLATFORM_CHILD_ITERATOR_H_ \ No newline at end of file +#endif // UI_ACCESSIBILITY_PLATFORM_CHILD_ITERATOR_H_
diff --git a/ui/accessibility/platform/child_iterator_base.cc b/ui/accessibility/platform/child_iterator_base.cc index 1febd09..13868802 100644 --- a/ui/accessibility/platform/child_iterator_base.cc +++ b/ui/accessibility/platform/child_iterator_base.cc
@@ -55,6 +55,12 @@ return index_; } +AXPlatformNodeDelegate* ChildIteratorBase::get() const { + AXPlatformNode* platform_node = + AXPlatformNode::FromNativeViewAccessible(GetNativeViewAccessible()); + return platform_node ? platform_node->GetDelegate() : nullptr; +} + AXPlatformNodeDelegate& ChildIteratorBase::operator*() const { AXPlatformNode* platform_node = AXPlatformNode::FromNativeViewAccessible(GetNativeViewAccessible()); @@ -63,9 +69,7 @@ } AXPlatformNodeDelegate* ChildIteratorBase::operator->() const { - AXPlatformNode* platform_node = - AXPlatformNode::FromNativeViewAccessible(GetNativeViewAccessible()); - return platform_node ? platform_node->GetDelegate() : nullptr; + return get(); } } // namespace ui
diff --git a/ui/accessibility/platform/child_iterator_base.h b/ui/accessibility/platform/child_iterator_base.h index 3f5f2fd0..ec0bde4 100644 --- a/ui/accessibility/platform/child_iterator_base.h +++ b/ui/accessibility/platform/child_iterator_base.h
@@ -23,6 +23,7 @@ ChildIteratorBase operator--(int); gfx::NativeViewAccessible GetNativeViewAccessible() const override; absl::optional<size_t> GetIndexInParent() const override; + AXPlatformNodeDelegate* get() const override; AXPlatformNodeDelegate& operator*() const override; AXPlatformNodeDelegate* operator->() const override;
diff --git a/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm b/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm index 546d3ef..c0b0a5a 100644 --- a/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm +++ b/ui/accessibility/platform/inspect/ax_call_statement_invoker_mac.mm
@@ -150,7 +150,10 @@ if (!property_node.key.empty()) (*storage_)[property_node.key] = target; - return AXOptionalNSObject(target); + // When dumping tree, return NULL values as NotApplicable in order to + // easily filter them out of the dump. + return IsDumpingTree() ? AXOptionalNSObject::NotNullOrNotApplicable(target) + : AXOptionalNSObject(target); } AXOptionalNSObject AXCallStatementInvoker::InvokeFor(
diff --git a/ui/accessibility/platform/inspect/ax_transform_mac.h b/ui/accessibility/platform/inspect/ax_transform_mac.h index b3b0437..c7b961a 100644 --- a/ui/accessibility/platform/inspect/ax_transform_mac.h +++ b/ui/accessibility/platform/inspect/ax_transform_mac.h
@@ -5,6 +5,7 @@ #ifndef UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_TRANSFORM_MAC_H_ #define UI_ACCESSIBILITY_PLATFORM_INSPECT_AX_TRANSFORM_MAC_H_ +#import <Accessibility/Accessibility.h> #import <Cocoa/Cocoa.h> #include "base/component_export.h" @@ -18,6 +19,10 @@ COMPONENT_EXPORT(AX_PLATFORM) base::Value AXNSObjectToBaseValue(id, const AXTreeIndexerMac*); +// Returns the base::Value::Dict representation of the given AXCustomContent. +base::Value::Dict AXCustomContentToBaseValue(AXCustomContent*) + API_AVAILABLE(macosx(11.0)); + // Returns the base::Value representation of the given NSAccessibilityElement. COMPONENT_EXPORT(AX_PLATFORM) base::Value AXElementToBaseValue(id, const AXTreeIndexerMac*);
diff --git a/ui/accessibility/platform/inspect/ax_transform_mac.mm b/ui/accessibility/platform/inspect/ax_transform_mac.mm index fe043e6..2b4c110a 100644 --- a/ui/accessibility/platform/inspect/ax_transform_mac.mm +++ b/ui/accessibility/platform/inspect/ax_transform_mac.mm
@@ -34,6 +34,13 @@ return base::Value(AXNSArrayToBaseValue((NSArray*)value, indexer)); } + // AXCustomContent + if (@available(macOS 11.0, *)) { + if ([value isKindOfClass:[AXCustomContent class]]) { + return base::Value(AXCustomContentToBaseValue((AXCustomContent*)value)); + } + } + // NSDictionary if ([value isKindOfClass:[NSDictionary class]]) { return base::Value( @@ -186,6 +193,13 @@ return list; } +base::Value::Dict AXCustomContentToBaseValue(AXCustomContent* content) { + base::Value::Dict value; + value.Set("label", base::SysNSStringToUTF16(content.label)); + value.Set("value", base::SysNSStringToUTF16(content.value)); + return value; +} + base::Value::Dict AXNSDictionaryToBaseValue(NSDictionary* dictionary_value, const AXTreeIndexerMac* indexer) { base::Value::Dict dictionary;
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 194b445f..dc490ab 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -123,7 +123,6 @@ namespace aura { namespace { -static const char* kExo = "Exo"; class ScopedCursorHider { public: @@ -1296,7 +1295,6 @@ Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager(); params.pipes.compositor_frame_sink_remote = std::move(sink_remote); params.pipes.client_receiver = std::move(client_receiver); - params.client_name = kExo; auto frame_sink = std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( nullptr /* context_provider */, nullptr /* worker_context_provider */,
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index e6edbc4..672bea5 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -136,6 +136,15 @@ "PointerLockOptions", base::FEATURE_ENABLED_BY_DEFAULT); +// Uses a stylus-specific tap slop region parameter for gestures. Stylus taps +// tend to slip more than touch taps (presumably because the user doesn't feel +// the movement friction with a stylus). As a result, it is harder to tap with +// a stylus. This feature makes the slop region for stylus input bigger than the +// touch slop. +BASE_FEATURE(kStylusSpecificTapSlop, + "StylusSpecificTapSlop", + base::FEATURE_ENABLED_BY_DEFAULT); + // Allows system caption style for WebVTT Captions. BASE_FEATURE(kSystemCaptionStyle, "SystemCaptionStyle",
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index d643f8c..7963bf8 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -188,6 +188,8 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) double RawDrawTileSizeFactor(); COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsRawDrawUsingMSAA(); +COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kStylusSpecificTapSlop); + COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kEnableVariableRefreshRate); COMPONENT_EXPORT(UI_BASE_FEATURES)
diff --git a/ui/color/color_id.h b/ui/color/color_id.h index c8727dc..3c708e3 100644 --- a/ui/color/color_id.h +++ b/ui/color/color_id.h
@@ -134,6 +134,17 @@ E_CPONLY(kColorSysSurface4) \ E_CPONLY(kColorSysSurface5) \ E_CPONLY(kColorSysDisabledContainer) \ + /* Chrome surfaces */ \ + E_CPONLY(kColorSysHeader) \ + E_CPONLY(kColorSysHeaderInactive) \ + E_CPONLY(kColorSysOnHeaderDivider) \ + E_CPONLY(kColorSysOnHeaderDividerInactive) \ + E_CPONLY(kColorSysOnHeaderPrimary) \ + E_CPONLY(kColorSysOnHeaderPrimaryInactive) \ + E_CPONLY(kColorSysOnHeaderSecondary) \ + E_CPONLY(kColorSysOnHeaderSecondaryInactive) \ + E_CPONLY(kColorSysOnHeaderContainer) \ + E_CPONLY(kColorSysOnHeaderContainerInactive) \ /* On-color tokens for any bases */ \ E_CPONLY(kColorSysOnSurface) \ E_CPONLY(kColorSysOnSurfaceDisabled) \ @@ -145,6 +156,7 @@ E_CPONLY(kColorSysStateFocus) \ E_CPONLY(kColorSysStatePressed) \ E_CPONLY(kColorSysStateDrag) \ + E_CPONLY(kColorSysStateFocusRing) \ /* Core color concepts */ \ /* kColorAccent is used in color_provider_css_colors_test.ts. */ \ /* If changing the variable name, the variable name in the test needs to */ \
diff --git a/ui/color/material_ui_color_mixer.cc b/ui/color/material_ui_color_mixer.cc index 5c5dec97..0b723e1 100644 --- a/ui/color/material_ui_color_mixer.cc +++ b/ui/color/material_ui_color_mixer.cc
@@ -37,6 +37,11 @@ mixer[kColorButtonForegroundDisabled] = {kColorSysOnSurfaceDisabled}; mixer[kColorButtonForegroundProminent] = {kColorSysOnPrimary}; mixer[kColorButtonForegroundUnchecked] = {kColorSysOnSurfaceVariant}; + mixer[kColorFocusableBorderFocused] = {kColorSysStateFocusRing}; + mixer[kColorFocusableBorderUnfocused] = {kColorSysOutline}; + mixer[kColorFrameActive] = {kColorSysHeader}; + mixer[kColorFrameActiveUnthemed] = {kColorSysHeader}; + mixer[kColorFrameInactive] = {kColorSysHeaderInactive}; mixer[kColorSliderThumb] = {kColorSysPrimary}; mixer[kColorSliderThumbMinimal] = {kColorSysSecondary}; mixer[kColorSliderTrack] = {kColorSysOnPrimary};
diff --git a/ui/color/sys_color_mixer.cc b/ui/color/sys_color_mixer.cc index 1315b53..55f14093 100644 --- a/ui/color/sys_color_mixer.cc +++ b/ui/color/sys_color_mixer.cc
@@ -20,6 +20,8 @@ key.color_mode == ColorProviderManager::ColorMode::kDark; ColorMixer& mixer = provider->AddMixer(); + // TODO(tluk): Current sys token recipes are still in flux. Audit and update + // existing definitions once the color spec is final. // Core sys tokens. mixer[kColorSysPrimary] = {dark_mode ? kColorRefPrimary80 : kColorRefPrimary40}; @@ -98,6 +100,28 @@ {kColorRefNeutral99})}; mixer[kColorSysDisabledContainer] = ui::SetAlpha({kColorSysOnSurface}, 0x60); + // Chrome surfaces. + mixer[kColorSysHeader] = {dark_mode ? kColorRefNeutral10 + : kColorRefPrimary90}; + mixer[kColorSysHeaderInactive] = {dark_mode ? kColorSysSurface1 + : kColorSysSurface3}; + mixer[kColorSysOnHeaderDivider] = {dark_mode ? kColorRefNeutral20 + : kColorRefPrimary80}; + mixer[kColorSysOnHeaderDividerInactive] = {dark_mode ? kColorRefSecondary30 + : kColorRefNeutral80}; + mixer[kColorSysOnHeaderPrimary] = {dark_mode ? kColorRefPrimary80 + : kColorRefPrimary40}; + mixer[kColorSysOnHeaderPrimaryInactive] = {dark_mode ? kColorRefSecondary80 + : kColorRefNeutral40}; + mixer[kColorSysOnHeaderSecondary] = {dark_mode ? kColorRefNeutral80 + : kColorRefNeutral40}; + mixer[kColorSysOnHeaderSecondaryInactive] = {dark_mode ? kColorRefNeutral80 + : kColorRefNeutral40}; + mixer[kColorSysOnHeaderContainer] = {dark_mode ? kColorRefSecondary20 + : kColorRefPrimary95}; + mixer[kColorSysOnHeaderContainerInactive] = {dark_mode ? kColorRefSecondary20 + : kColorRefNeutral99}; + // On-color tokens for any bases. mixer[kColorSysOnSurface] = {dark_mode ? kColorRefNeutral90 : kColorRefNeutral10}; @@ -124,6 +148,8 @@ mixer[kColorSysStateDrag] = {dark_mode ? SetAlpha({kColorRefNeutral90}, 0x29) : SetAlpha({kColorRefNeutral10}, 0x29)}; + mixer[kColorSysStateFocusRing] = {dark_mode ? kColorRefPrimary80 + : kColorRefPrimary40}; } } // namespace ui
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc index 659542cb..d07caa0a 100644 --- a/ui/display/manager/display_configurator.cc +++ b/ui/display/manager/display_configurator.cc
@@ -130,6 +130,10 @@ DisplayStateList GetDisplayStates() const override; bool IsMirroring() const override; + void set_configure_displays(bool configure_displays) { + configure_displays_ = configure_displays; + } + private: // Parses the |displays| into a list of DisplayStates. This effectively adds // |mirror_mode| and |selected_mode| to the returned results. @@ -161,6 +165,8 @@ bool preserve_native_aspect_ratio) const; DisplayConfigurator* configurator_; // Not owned. + + bool configure_displays_ = false; }; DisplayConfigurator::DisplayLayoutManagerImpl::DisplayLayoutManagerImpl( @@ -209,8 +215,9 @@ // Hardware mirroring doesn't work on desktop-linux Chrome OS's fake displays. // Skip mirror mode setup in that case to fall back on software mirroring. - if (!chromeos::IsRunningAsSystemCompositor()) + if (!configure_displays_) { return cached_displays; + } if (cached_displays.size() <= 1) return cached_displays; @@ -575,7 +582,7 @@ : state_controller_(nullptr), mirroring_controller_(nullptr), is_panel_fitting_enabled_(false), - configure_display_(chromeos::IsRunningAsSystemCompositor()), + configure_displays_(chromeos::IsRunningAsSystemCompositor()), current_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), current_power_state_(chromeos::DISPLAY_POWER_ALL_ON), requested_display_state_(MULTIPLE_DISPLAY_STATE_INVALID), @@ -610,7 +617,7 @@ DCHECK(!native_display_delegate_); native_display_delegate_ = std::move(display_delegate); - configure_display_ = true; + SetConfigureDisplays(true); } void DisplayConfigurator::SetInitialDisplayPower( @@ -658,6 +665,11 @@ native_display_delegate_.get()); } +void DisplayConfigurator::SetConfigureDisplays(bool configure_displays) { + configure_displays_ = configure_displays; + layout_manager_->set_configure_displays(configure_displays); +} + void DisplayConfigurator::TakeControl(DisplayControlCallback callback) { if (display_control_changing_) { std::move(callback).Run(false); @@ -814,7 +826,7 @@ } void DisplayConfigurator::PrepareForExit() { - configure_display_ = false; + configure_displays_ = false; } void DisplayConfigurator::SetDisplayPowerInternal(
diff --git a/ui/display/manager/display_configurator.h b/ui/display/manager/display_configurator.h index 129800a..c96ed1d0 100644 --- a/ui/display/manager/display_configurator.h +++ b/ui/display/manager/display_configurator.h
@@ -28,7 +28,6 @@ namespace display { class ContentProtectionManager; -class DisplayLayoutManager; class DisplayMode; class DisplaySnapshot; class ManagedDisplayMode; @@ -178,9 +177,7 @@ void set_mirroring_controller(SoftwareMirroringController* controller) { mirroring_controller_ = controller; } - void set_configure_display(bool configure_display) { - configure_display_ = configure_display; - } + void SetConfigureDisplays(bool configure_displays); bool has_unassociated_display() const { return has_unassociated_display_; } chromeos::DisplayPowerState current_power_state() const { return current_power_state_; @@ -303,7 +300,7 @@ class DisplayLayoutManagerImpl; bool configurator_disabled() const { - return !configure_display_ || display_externally_controlled_; + return !configure_displays_ || display_externally_controlled_; } // Updates |pending_*| members and applies the passed-in state. |callback| is @@ -388,7 +385,7 @@ // This is detected by the constructor to determine whether or not we should // be enabled. If this flag is set to false, any attempts to change the // display configuration will immediately fail without changing the state. - bool configure_display_; + bool configure_displays_; // Current configuration state. MultipleDisplayState current_display_state_; @@ -448,7 +445,7 @@ // Whether the displays are currently suspended. bool displays_suspended_; - std::unique_ptr<DisplayLayoutManager> layout_manager_; + std::unique_ptr<DisplayLayoutManagerImpl> layout_manager_; std::unique_ptr<ContentProtectionManager> content_protection_manager_; std::unique_ptr<UpdateDisplayConfigurationTask> configuration_task_;
diff --git a/ui/display/manager/display_configurator_unittest.cc b/ui/display/manager/display_configurator_unittest.cc index 00cdd756f..f08961c2 100644 --- a/ui/display/manager/display_configurator_unittest.cc +++ b/ui/display/manager/display_configurator_unittest.cc
@@ -242,11 +242,9 @@ scoped_feature_list_.InitAndEnableFeature( features::kEnableHardwareMirrorMode); - // Force system compositor mode to simulate on-device configurator behavior. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ::switches::kEnableRunningAsSystemCompositor); - native_display_delegate_ = new TestNativeDisplayDelegate(log_.get()); + // Force configuring displays to simulate on-device configurator behavior. + configurator_.SetConfigureDisplays(true); configurator_.SetDelegateForTesting( std::unique_ptr<NativeDisplayDelegate>(native_display_delegate_));
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index 618877e..f56dd0f 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -333,7 +333,7 @@ DisplayManager::DisplayManager(std::unique_ptr<Screen> screen) : screen_(std::move(screen)), layout_store_(new DisplayLayoutStore) { - configure_displays_ = chromeos::IsRunningAsSystemCompositor(); + SetConfigureDisplays(chromeos::IsRunningAsSystemCompositor()); change_display_upon_host_resize_ = !configure_displays_; unified_desktop_enabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableUnifiedDesktop); @@ -346,6 +346,13 @@ on_display_zoom_modify_timeout_.Cancel(); } +void DisplayManager::SetConfigureDisplays(bool configure_displays) { + configure_displays_ = configure_displays; + if (display_configurator_) { + display_configurator_->SetConfigureDisplays(configure_displays); + } +} + bool DisplayManager::InitFromCommandLine() { DisplayInfoList info_list; base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -1447,6 +1454,7 @@ display_configurator_ = std::make_unique<display::DisplayConfigurator>(); display_configurator_->Init(std::move(delegate), false /* is_panel_fitting_enabled */); + display_configurator_->SetConfigureDisplays(configure_displays_); } void DisplayManager::ForceInitialConfigureWithObservers(
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h index dc8bb34..0a4b5c7 100644 --- a/ui/display/manager/display_manager.h +++ b/ui/display/manager/display_manager.h
@@ -117,10 +117,6 @@ force_bounds_changed_ = force_bounds_changed; } - void set_configure_displays(bool configure_displays) { - configure_displays_ = configure_displays; - } - void set_internal_display_has_accelerometer(bool has_accelerometer) { internal_display_has_accelerometer_ = has_accelerometer; } @@ -138,6 +134,8 @@ return current_unified_desktop_matrix_; } + void SetConfigureDisplays(bool configure_displays); + // Initializes displays using command line flag. Returns false if no command // line flag was provided. bool InitFromCommandLine();
diff --git a/ui/display/manager/update_display_configuration_task.h b/ui/display/manager/update_display_configuration_task.h index e6501b4..7b3f8fc 100644 --- a/ui/display/manager/update_display_configuration_task.h +++ b/ui/display/manager/update_display_configuration_task.h
@@ -20,6 +20,7 @@ namespace display { class DisplaySnapshot; +class DisplayLayoutManager; class NativeDisplayDelegate; class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn index aa0fe2c..4acdd291 100644 --- a/ui/events/BUILD.gn +++ b/ui/events/BUILD.gn
@@ -482,6 +482,7 @@ "//base", "//base/third_party/dynamic_annotations", "//build:chromeos_buildflags", + "//ui/base:features", "//ui/display", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/ui/events/gesture_detection/gesture_configuration.cc b/ui/events/gesture_detection/gesture_configuration.cc index c5b38ae..30839e68 100644 --- a/ui/events/gesture_detection/gesture_configuration.cc +++ b/ui/events/gesture_detection/gesture_configuration.cc
@@ -42,6 +42,7 @@ max_swipe_deviation_angle_(20), max_time_between_double_click_in_ms_(700), max_touch_down_duration_for_click_in_ms_(800), + max_stylus_move_in_pixels_for_click_(20), max_touch_move_in_pixels_for_click_(15), min_distance_for_pinch_scroll_in_pixels_(20), min_fling_velocity_(30.0f),
diff --git a/ui/events/gesture_detection/gesture_configuration.h b/ui/events/gesture_detection/gesture_configuration.h index 0f5969c..e605ec3 100644 --- a/ui/events/gesture_detection/gesture_configuration.h +++ b/ui/events/gesture_detection/gesture_configuration.h
@@ -114,6 +114,12 @@ void set_max_touch_down_duration_for_click_in_ms(int val) { max_touch_down_duration_for_click_in_ms_ = val; } + float max_stylus_move_in_pixels_for_click() const { + return max_stylus_move_in_pixels_for_click_; + } + void set_max_stylus_move_in_pixels_for_click(float val) { + max_stylus_move_in_pixels_for_click_ = val; + } float max_touch_move_in_pixels_for_click() const { return max_touch_move_in_pixels_for_click_; } @@ -237,6 +243,7 @@ float max_swipe_deviation_angle_; int max_time_between_double_click_in_ms_; int max_touch_down_duration_for_click_in_ms_; + float max_stylus_move_in_pixels_for_click_; float max_touch_move_in_pixels_for_click_; float min_distance_for_pinch_scroll_in_pixels_; float min_fling_velocity_;
diff --git a/ui/events/gesture_detection/gesture_configuration_android.cc b/ui/events/gesture_detection/gesture_configuration_android.cc index 3ddda9c..249e060 100644 --- a/ui/events/gesture_detection/gesture_configuration_android.cc +++ b/ui/events/gesture_detection/gesture_configuration_android.cc
@@ -54,6 +54,8 @@ set_max_gesture_bounds_length(kMaxGestureBoundsLengthDips); set_max_touch_move_in_pixels_for_click( ViewConfiguration::GetTouchSlopInDips()); + set_max_stylus_move_in_pixels_for_click( + ViewConfiguration::GetTouchSlopInDips() * 1.5f); set_min_fling_velocity( ViewConfiguration::GetMinimumFlingVelocityInDipsPerSecond()); set_min_gesture_bounds_length(kMinGestureBoundsLengthDips);
diff --git a/ui/events/gesture_detection/gesture_configuration_aura.cc b/ui/events/gesture_detection/gesture_configuration_aura.cc index 85288d4..119eed8 100644 --- a/ui/events/gesture_detection/gesture_configuration_aura.cc +++ b/ui/events/gesture_detection/gesture_configuration_aura.cc
@@ -34,10 +34,13 @@ private: GestureConfigurationAura() : GestureConfiguration() { #if BUILDFLAG(IS_CHROMEOS) - // On ChromeOS, use 6 which is derived from the android's default(8), - // multiplied by base dpi ratio(0.75). See crbug.com/1083120 for more - // details. + // On ChromeOS, the touch slop value of 6 is derived from the android's + // default(8), multiplied by base dpi ratio(0.75). See crbug.com/1083120 + // for more details. set_max_touch_move_in_pixels_for_click(6); + // The default stylus slop value of 10 is derived from the UMA data analysis + // for making stylus clicks easier for users. See crbug.com/1181872. + set_max_stylus_move_in_pixels_for_click(10); #endif double touch_slop_distance; base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/ui/events/gesture_detection/gesture_detector.cc b/ui/events/gesture_detection/gesture_detector.cc index 4feac0a..4a18dd64 100644 --- a/ui/events/gesture_detection/gesture_detector.cc +++ b/ui/events/gesture_detection/gesture_detector.cc
@@ -14,6 +14,7 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/gesture_listeners.h" #include "ui/events/gesture_detection/motion_event.h" @@ -37,15 +38,20 @@ } // namespace -// Note: These constants were taken directly from the default (unscaled) +// Note: Most of these constants were taken directly from the default (unscaled) // versions found in Android's ViewConfiguration. Do not change these default // values without explicitly consulting an OWNER. +// +// Many of these default values get over-ridden by GestureConfiguration +// parameters. We have encountered exceptions to this behavior in certain +// tests, see https://crbug.com/1294244. GestureDetector::Config::Config() : shortpress_timeout(base::Milliseconds(400)), longpress_timeout(base::Milliseconds(500)), showpress_timeout(base::Milliseconds(180)), double_tap_timeout(base::Milliseconds(300)), double_tap_min_time(base::Milliseconds(40)), + stylus_slop(12), touch_slop(8), double_tap_slop(100), minimum_fling_velocity(50), @@ -138,6 +144,7 @@ : timeout_handler_(new TimeoutGestureHandler(config, this)), listener_(listener), double_tap_listener_(optional_double_tap_listener), + stylus_slop_square_(0), touch_slop_square_(0), double_tap_touch_slop_square_(0), double_tap_slop_square_(0), @@ -326,7 +333,7 @@ DCHECK(double_tap_listener_); handled |= double_tap_listener_->OnDoubleTapEvent(ev); } else if (all_pointers_within_slop_regions_) { - if (!IsWithinTouchSlop(ev)) { + if (!IsWithinSlopForTap(ev)) { handled = listener_->OnScroll( *current_down_event_, ev, (maximum_pointer_count_ > 1 && secondary_pointer_down_event_) @@ -385,7 +392,7 @@ // (independent) slop region. // If the event has had more than two pointers down at any time, // two finger tap should be prevented. - if (maximum_pointer_count_ > 2 || !IsWithinTouchSlop(ev)) { + if (maximum_pointer_count_ > 2 || !IsWithinSlopForTap(ev)) { two_finger_tap_allowed_for_gesture_ = false; } } break; @@ -476,9 +483,11 @@ // proportioned). const float kSlopEpsilon = .05f; + const float stylus_slop = config.stylus_slop + kSlopEpsilon; const float touch_slop = config.touch_slop + kSlopEpsilon; const float double_tap_touch_slop = touch_slop; const float double_tap_slop = config.double_tap_slop + kSlopEpsilon; + stylus_slop_square_ = stylus_slop * stylus_slop; touch_slop_square_ = touch_slop * touch_slop; double_tap_touch_slop_square_ = double_tap_touch_slop * double_tap_touch_slop; double_tap_slop_square_ = double_tap_slop * double_tap_slop; @@ -616,7 +625,7 @@ return listener_->OnSwipe(*current_down_event_, up, vx, vy); } -bool GestureDetector::IsWithinTouchSlop(const MotionEvent& ev) { +bool GestureDetector::IsWithinSlopForTap(const MotionEvent& ev) { // If there have been more than two down pointers in the touch sequence, // tapping is not possible. Slop region check is not needed. if (maximum_pointer_count_ > 2) @@ -639,8 +648,14 @@ float dx = source_pointer_down_event->GetX(source_index) - ev.GetX(i); float dy = source_pointer_down_event->GetY(source_index) - ev.GetY(i); - if (dx * dx + dy * dy > touch_slop_square_) + bool is_stylus_slop_effective = + base::FeatureList::IsEnabled(features::kStylusSpecificTapSlop) && + ev.GetToolType(i) == MotionEvent::ToolType::STYLUS; + float slop_square = + is_stylus_slop_effective ? stylus_slop_square_ : touch_slop_square_; + if (dx * dx + dy * dy > slop_square) { return false; + } } return true;
diff --git a/ui/events/gesture_detection/gesture_detector.h b/ui/events/gesture_detection/gesture_detector.h index ad19f923..ad9a20f 100644 --- a/ui/events/gesture_detection/gesture_detector.h +++ b/ui/events/gesture_detection/gesture_detector.h
@@ -39,6 +39,10 @@ // tap's down event for an interaction to be considered a double-tap. base::TimeDelta double_tap_min_time; + // Distance a stylus-contact can wander before a scroll will occur (in + // dips). + float stylus_slop; + // Distance a touch can wander before a scroll will occur (in dips). float touch_slop; @@ -145,13 +149,14 @@ const MotionEvent& second_down, bool should_process_double_tap) const; bool HandleSwipeIfNeeded(const MotionEvent& up, float vx, float vy); - bool IsWithinTouchSlop(const MotionEvent& ev); + bool IsWithinSlopForTap(const MotionEvent& ev); class TimeoutGestureHandler; std::unique_ptr<TimeoutGestureHandler> timeout_handler_; const raw_ptr<GestureListener> listener_; raw_ptr<DoubleTapListener> double_tap_listener_; + float stylus_slop_square_; float touch_slop_square_; float double_tap_touch_slop_square_; float double_tap_slop_square_;
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc index f26af1c..7d8b200 100644 --- a/ui/events/gesture_detection/gesture_provider.cc +++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -8,10 +8,10 @@ #include <cmath> -#include "base/auto_reset.h" #include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/gesture_detection/gesture_event_data.h" @@ -77,6 +77,14 @@ center.x() - width / 2.f, center.y() - height / 2.f, width, height); } +float EffectiveSlopDistance(const MotionEvent& event, + const GestureProvider::Config& config) { + return (base::FeatureList::IsEnabled(features::kStylusSpecificTapSlop) && + event.GetToolType() == MotionEvent::ToolType::STYLUS) + ? config.gesture_detector_config.stylus_slop + : config.gesture_detector_config.touch_slop; +} + } // namespace // GestureProviderClient: @@ -113,8 +121,7 @@ gesture_provider_(gesture_provider), gesture_detector_(config.gesture_detector_config, this, this), scale_gesture_detector_(config.scale_gesture_detector_config, this), - snap_scroll_controller_(config.gesture_detector_config.touch_slop, - gfx::SizeF(config.display.size())), + snap_scroll_controller_(gfx::SizeF(config.display.size())), ignore_multitouch_zoom_events_(false), ignore_single_tap_(false), pinch_event_sent_(false), @@ -127,9 +134,11 @@ void OnTouchEvent(const MotionEvent& event) { const bool in_scale_gesture = IsScaleGestureDetectionInProgress(); - snap_scroll_controller_.SetSnapScrollMode(event, in_scale_gesture); - if (in_scale_gesture) + snap_scroll_controller_.SetSnapScrollMode( + event, in_scale_gesture, EffectiveSlopDistance(event, config_)); + if (in_scale_gesture) { SetIgnoreSingleTap(true); + } const MotionEvent::Action action = event.GetAction(); if (action == MotionEvent::Action::DOWN) { @@ -392,7 +401,8 @@ distance_y = delta.y(); } - snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y); + snap_scroll_controller_.UpdateSnapScrollMode( + distance_x, distance_y, EffectiveSlopDistance(e2, config_)); if (snap_scroll_controller_.IsSnappingScrolls()) { if (snap_scroll_controller_.IsSnapHorizontal()) distance_y = 0;
diff --git a/ui/events/gesture_detection/gesture_provider_config_helper.cc b/ui/events/gesture_detection/gesture_provider_config_helper.cc index 38c9d75..0c89ff4e 100644 --- a/ui/events/gesture_detection/gesture_provider_config_helper.cc +++ b/ui/events/gesture_detection/gesture_provider_config_helper.cc
@@ -30,6 +30,7 @@ base::Milliseconds(gesture_config.show_press_delay_in_ms()); config.double_tap_timeout = base::Milliseconds(gesture_config.double_tap_timeout_in_ms()); + config.stylus_slop = gesture_config.max_stylus_move_in_pixels_for_click(); config.touch_slop = gesture_config.max_touch_move_in_pixels_for_click(); config.double_tap_slop = gesture_config.max_distance_between_taps_for_double_tap();
diff --git a/ui/events/gesture_detection/gesture_provider_unittest.cc b/ui/events/gesture_detection/gesture_provider_unittest.cc index 2c148f2..3db39d2c 100644 --- a/ui/events/gesture_detection/gesture_provider_unittest.cc +++ b/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -13,10 +13,12 @@ #include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ui_base_features.h" #include "ui/events/event_constants.h" #include "ui/events/gesture_detection/gesture_event_data.h" #include "ui/events/gesture_detection/motion_event.h" @@ -69,7 +71,7 @@ GestureProviderTest() : task_environment_( base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {} - ~GestureProviderTest() override {} + ~GestureProviderTest() override = default; static MockMotionEvent ObtainMotionEvent(base::TimeTicks event_time, MotionEvent::Action action, @@ -206,7 +208,8 @@ } const GestureEventData* GetActiveScrollBeginEvent() const { - return active_scroll_begin_event_ ? active_scroll_begin_event_.get() : NULL; + return active_scroll_begin_event_ ? active_scroll_begin_event_.get() + : nullptr; } const GestureProvider::Config& GetDefaultConfig() const { @@ -214,8 +217,11 @@ return sConfig; } - float GetTouchSlop() const { - return GetDefaultConfig().gesture_detector_config.touch_slop; + float GetTapSlop( + MotionEvent::ToolType tool_type = MotionEvent::ToolType::FINGER) const { + return tool_type == MotionEvent::ToolType::FINGER + ? GetDefaultConfig().gesture_detector_config.touch_slop + : GetDefaultConfig().gesture_detector_config.stylus_slop; } float GetMinScalingSpan() const { @@ -390,6 +396,51 @@ GetMostRecentGestureEvent().details.bounding_box_f()); } + void CheckNoScrollWithinTouchSlop(MotionEvent::ToolType tool_type) { + const float tap_slop = GetTapSlop(tool_type); + base::TimeTicks event_time = base::TimeTicks::Now(); + + MockMotionEvent event = + ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX, + kFakeCoordY + tap_slop); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); + + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX + tap_slop, + kFakeCoordY); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); + + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX - tap_slop, + kFakeCoordY); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); + + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX, + kFakeCoordY - tap_slop); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); + + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX, + kFakeCoordY + tap_slop + 1.f); + event.SetToolType(0, tool_type); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); + } + void OneFingerSwipe(float vx, float vy) { std::vector<gfx::Vector2dF> velocities; velocities.push_back(gfx::Vector2dF(vx, vy)); @@ -1189,7 +1240,7 @@ TEST_F(GestureProviderTest, SlopRegionCheckOnOneFingerScroll) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1204,16 +1255,16 @@ // Move within slop region. event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, - scaled_touch_slop / 2); + scaled_tap_slop / 2); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); // Exceed slop region. event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, - 2 * scaled_touch_slop); + 2 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::UP, 0, - 2 * scaled_touch_slop); + 2 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetReceivedGesture(0).type()); @@ -1231,7 +1282,7 @@ TEST_F(GestureProviderTest, SlopRegionCheckOnTwoFingerScroll) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1252,43 +1303,43 @@ GetMostRecentGestureEvent().details.primary_unique_touch_event_id()); // Move within slop region: two-finger tap happens. - event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, - scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 0); + event = + ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP, 0, - scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 0); + event = + ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ( primary_unique_touch_event_id, GetMostRecentGestureEvent().details.primary_unique_touch_event_id()); // Exceed slop region: scroll. - event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_DOWN, 0, - scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 0); + event = + ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_DOWN, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ( primary_unique_touch_event_id, GetMostRecentGestureEvent().details.primary_unique_touch_event_id()); - event = ObtainMotionEvent( - event_time, MotionEvent::Action::MOVE, 0, scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 2 * scaled_touch_slop); + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, + 2 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - event = ObtainMotionEvent( - event_time, MotionEvent::Action::POINTER_UP, 0, scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 2 * scaled_touch_slop); + event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, + 2 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ( primary_unique_touch_event_id, GetMostRecentGestureEvent().details.primary_unique_touch_event_id()); event = ObtainMotionEvent(event_time, MotionEvent::Action::UP, 0, - scaled_touch_slop / 2); + scaled_tap_slop / 2); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ( primary_unique_touch_event_id, @@ -1308,7 +1359,7 @@ // are missing from the event stream. TEST_F(GestureProviderTest, SlopRegionCheckOnMissingSecondaryPointerDownEvent) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1322,7 +1373,7 @@ event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_DOWN, 0, 0, kMaxTwoFingerTapSeparation / 2, 0); - event.MovePoint(1, 0, 3 * scaled_touch_slop); + event.MovePoint(1, 0, 3 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event.ReleasePointAtIndex(0); @@ -1340,7 +1391,7 @@ TEST_F(GestureProviderTest, NoSlopRegionCheckOnThreeFingerScroll) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1358,9 +1409,9 @@ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); // Move within slop region, three-finger scroll always happens. - event = ObtainMotionEvent( - event_time, MotionEvent::Action::MOVE, 0, scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2, 0, 2 * kMaxTwoFingerTapSeparation, 0); + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, + scaled_tap_slop / 2, kMaxTwoFingerTapSeparation / 2, + 0, 2 * kMaxTwoFingerTapSeparation, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetReceivedGesture(0).type()); @@ -1371,7 +1422,7 @@ TEST_F(GestureProviderTest, ScrollStartWithSecondaryPointer) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1389,7 +1440,7 @@ event.ReleasePointAtIndex(0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - event.MovePoint(0, kMaxTwoFingerTapSeparation / 2, 2 * scaled_touch_slop); + event.MovePoint(0, kMaxTwoFingerTapSeparation / 2, 2 * scaled_tap_slop); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event.ReleasePoint(); @@ -1632,7 +1683,7 @@ // Verify that the touch slop region is removed from the first scroll delta to // avoid a jump when starting to scroll. TEST_F(GestureProviderTest, TouchSlopRemovedFromScroll) { - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); const float scroll_delta = 5; base::TimeTicks event_time = base::TimeTicks::Now(); @@ -1643,7 +1694,7 @@ event = ObtainMotionEvent(event_time + kOneMicrosecond * 2, MotionEvent::Action::MOVE, kFakeCoordX, - kFakeCoordY + touch_slop + scroll_delta); + kFakeCoordY + tap_slop + scroll_delta); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetMostRecentGestureEventType()); @@ -1653,46 +1704,49 @@ EXPECT_EQ(1, gesture.details.touch_points()); } -// Verify that movement within the touch slop region does not generate a scroll, -// and that the slop region is correct even when using fractional coordinates. -TEST_F(GestureProviderTest, NoScrollWithinTouchSlop) { - const float touch_slop = GetTouchSlop(); - const float scale_factor = 2.5f; - const int touch_slop_pixels = static_cast<int>(scale_factor * touch_slop); +// Verify that finger movement within the tap slop region does not +// initiate a scroll, and that movement outside the slop region does. +TEST_F(GestureProviderTest, NoTouchScrollWithinSlop) { + CheckNoScrollWithinTouchSlop(MotionEvent::ToolType::FINGER); +} +// Verify that stylus movement within the tap slop region does not +// initiate a scroll, and that movement outside the slop region does. +TEST_F(GestureProviderTest, NoStylusScrollWithinSlop) { + CheckNoScrollWithinTouchSlop(MotionEvent::ToolType::STYLUS); +} + +// Disabled because `SnapScrollController` still can't correctly treat all +// stylus moves within the slop region. If the first move action is within the +// stylus slop but outside the (smaller) touch slop, `SnapScrollController` +// ignores any orthogonal move actions even when they are outside the stylus +// slop. +// +// TODO(mustaq@chromium.org): Refactor SnapScrollController states to fix this. +TEST_F(GestureProviderTest, SnapScrollWithStylusSlop) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kStylusSpecificTapSlop); + + const MotionEvent::ToolType tool_type = MotionEvent::ToolType::STYLUS; + const float tap_slop = GetTapSlop(tool_type); base::TimeTicks event_time = base::TimeTicks::Now(); MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); + event.SetToolType(0, tool_type); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - event = ObtainMotionEvent( - event_time + kOneMicrosecond * 2, MotionEvent::Action::MOVE, - kFakeCoordX + touch_slop_pixels / scale_factor, kFakeCoordY); + event = ObtainMotionEvent(event_time += kOneMicrosecond, + MotionEvent::Action::MOVE, kFakeCoordX + tap_slop, + kFakeCoordY); + event.SetToolType(0, tool_type); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - event = ObtainMotionEvent(event_time + kOneMicrosecond * 2, + event = ObtainMotionEvent(event_time += kOneMicrosecond, MotionEvent::Action::MOVE, kFakeCoordX, - kFakeCoordY + touch_slop_pixels / scale_factor); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - - event = ObtainMotionEvent( - event_time + kOneMicrosecond * 2, MotionEvent::Action::MOVE, - kFakeCoordX - touch_slop_pixels / scale_factor, kFakeCoordY); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - - event = ObtainMotionEvent(event_time + kOneMicrosecond * 2, - MotionEvent::Action::MOVE, kFakeCoordX, - kFakeCoordY - touch_slop_pixels / scale_factor); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - - event = ObtainMotionEvent( - event_time + kOneMicrosecond * 2, MotionEvent::Action::MOVE, kFakeCoordX, - kFakeCoordY + (touch_slop_pixels + 1.f) / scale_factor); + kFakeCoordY + tap_slop + 1.f); + event.SetToolType(0, tool_type); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); } @@ -2056,7 +2110,7 @@ // Verify that pinch zoom sends the proper event sequence. TEST_F(GestureProviderTest, PinchZoom) { base::TimeTicks event_time = base::TimeTicks::Now(); - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); const float raw_offset_x = 3.2f; const float raw_offset_y = 4.3f; int motion_event_id = 6; @@ -2065,8 +2119,8 @@ gesture_provider_->SetDoubleTapSupportForPlatformEnabled(true); gesture_provider_->SetMultiTouchZoomSupportEnabled(true); - int secondary_coord_x = kFakeCoordX + 20 * touch_slop; - int secondary_coord_y = kFakeCoordY + 20 * touch_slop; + int secondary_coord_x = kFakeCoordX + 20 * tap_slop; + int secondary_coord_y = kFakeCoordY + 20 * tap_slop; MockMotionEvent event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN); @@ -2097,8 +2151,8 @@ EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY), GetMostRecentGestureEvent().details.bounding_box_f()); - secondary_coord_x += 5 * touch_slop; - secondary_coord_y += 5 * touch_slop; + secondary_coord_x += 5 * tap_slop; + secondary_coord_y += 5 * tap_slop; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2127,8 +2181,8 @@ secondary_coord_y - kFakeCoordY + kMockTouchRadius * 2), GetMostRecentGestureEvent().details.bounding_box_f()); - secondary_coord_x += 2 * touch_slop; - secondary_coord_y += 2 * touch_slop; + secondary_coord_x += 2 * tap_slop; + secondary_coord_y += 2 * tap_slop; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2646,7 +2700,7 @@ // The time between Action::POINTER_DOWN and Action::POINTER_UP must be <= the // two finger tap delay. EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); @@ -2655,15 +2709,15 @@ EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, 0, - scaled_touch_slop / 2); + scaled_tap_slop / 2); event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_DOWN, 0, 0, kMaxTwoFingerTapSeparation / 2, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent( - event_time, MotionEvent::Action::MOVE, 0, -scaled_touch_slop / 2, - kMaxTwoFingerTapSeparation / 2 + scaled_touch_slop / 2, 0); + event_time, MotionEvent::Action::MOVE, 0, -scaled_tap_slop / 2, + kMaxTwoFingerTapSeparation / 2 + scaled_tap_slop / 2, 0); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP, 0, 0, @@ -2682,7 +2736,7 @@ // Test preventing a two finger tap via finger movement. TEST_F(GestureProviderTest, TwoFingerTapCancelledByFingerMovement) { EnableTwoFingerTap(kMaxTwoFingerTapSeparation, base::TimeDelta()); - const float scaled_touch_slop = GetTouchSlop(); + const float scaled_tap_slop = GetTapSlop(); base::TimeTicks event_time = base::TimeTicks::Now(); MockMotionEvent event = ObtainMotionEvent( @@ -2693,9 +2747,9 @@ kFakeCoordX, kFakeCoordY, kFakeCoordX, kFakeCoordY); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - event = ObtainMotionEvent( - event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, - kFakeCoordX + 2 * scaled_touch_slop + 2, kFakeCoordY); + event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, + kFakeCoordY, kFakeCoordX + 2 * scaled_tap_slop + 2, + kFakeCoordY); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::POINTER_UP, @@ -2705,11 +2759,11 @@ EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetReceivedGesture(0).type()); EXPECT_EQ(ET_GESTURE_SCROLL_BEGIN, GetReceivedGesture(1).type()); EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetReceivedGesture(2).type()); - // d_x = 2 * scaled_touch_slop + 2, - // d_focus_x = scaled_touch_slop + 1, - // touch_slop / event.GetPointerCount() is deducted from first scroll, - // scroll_x = scaled_touch_slop + 1 - scaled_touch_slop / 2 - EXPECT_FLOAT_EQ(scaled_touch_slop / 2 + 1, + // d_x = 2 * scaled_tap_slop + 2, + // d_focus_x = scaled_tap_slop + 1, + // tap_slop / event.GetPointerCount() is deducted from first scroll, + // scroll_x = scaled_tap_slop + 1 - scaled_tap_slop / 2 + EXPECT_FLOAT_EQ(scaled_tap_slop / 2 + 1, GetReceivedGesture(2).details.scroll_x()); EXPECT_EQ(0, GetReceivedGesture(2).details.scroll_y()); EXPECT_EQ(3U, GetReceivedGestureCount()); @@ -2772,7 +2826,7 @@ // also generates an update. TEST_F(GestureProviderTest, PinchExceedingSlopCausesUpdate) { base::TimeTicks event_time = base::TimeTicks::Now(); - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); const float min_scaling_span = GetMinScalingSpan(); const float raw_offset_x = 3.2f; const float raw_offset_y = 4.3f; @@ -2808,7 +2862,7 @@ // Move second finger by exactly the touch slop. This shouldn't yet generate // a Pinch Begin. - secondary_coord_y += touch_slop * 2; + secondary_coord_y += tap_slop * 2; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2837,7 +2891,7 @@ // span also generates an update. TEST_F(GestureProviderTest, PinchBelowMinSpanCausesUpdate) { base::TimeTicks event_time = base::TimeTicks::Now(); - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); const float min_scaling_span = GetMinScalingSpan(); const float raw_offset_x = 3.2f; const float raw_offset_y = 4.3f; @@ -2848,7 +2902,7 @@ gesture_provider_->SetMultiTouchZoomSupportEnabled(true); int secondary_coord_x = kFakeCoordX; - int secondary_coord_y = kFakeCoordY + min_scaling_span + touch_slop * 3; + int secondary_coord_y = kFakeCoordY + min_scaling_span + tap_slop * 3; // First Finger Down MockMotionEvent event = @@ -2872,7 +2926,7 @@ EXPECT_EQ(1U, GetReceivedGestureCount()); // Move second finger enough to exceed the touch slop and start zooming. - secondary_coord_y -= (touch_slop * 2 + 1); + secondary_coord_y -= (tap_slop * 2 + 1); event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2886,7 +2940,7 @@ // Move second finger so that the span becomes smaller than the min scaling // span. The pinch should end but we should receive an update before it does. - secondary_coord_y -= touch_slop * 2; + secondary_coord_y -= tap_slop * 2; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2903,7 +2957,7 @@ // scaling span. TEST_F(GestureProviderTest, PinchExceedingSlopWithinMinScale) { base::TimeTicks event_time = base::TimeTicks::Now(); - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); const float min_scaling_span = GetMinScalingSpan(); const float raw_offset_x = 3.2f; const float raw_offset_y = 4.3f; @@ -2918,7 +2972,7 @@ // This test only makes sense if the min_scaling_span is greater than the // touch slop span. - ASSERT_GT(min_scaling_span, touch_slop * 2); + ASSERT_GT(min_scaling_span, tap_slop * 2); // First Finger Down MockMotionEvent event = @@ -2943,7 +2997,7 @@ // Move second finger to exceed the touch slop. This shouldn't yet generate // a Pinch Begin since we're still within the minimum scaling span. - secondary_coord_y += touch_slop * 2 + 1; + secondary_coord_y += tap_slop * 2 + 1; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); event.SetPrimaryPointerId(motion_event_id); @@ -2967,7 +3021,7 @@ EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetNthMostRecentGestureEventType(0)); // The scale must start from the min scale span threshold, rather than from - // the touch_slop so it should be very small. + // the tap_slop so it should be very small. EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale()); EXPECT_GT(1.01f, GetMostRecentGestureEvent().details.scale()); } @@ -2978,15 +3032,15 @@ const float kMinPinchUpdateDistance = 5; base::TimeTicks event_time = base::TimeTicks::Now(); - const float touch_slop = GetTouchSlop(); + const float tap_slop = GetTapSlop(); SetMinPinchUpdateSpanDelta(kMinPinchUpdateDistance); gesture_provider_->SetDoubleTapSupportForPageEnabled(false); gesture_provider_->SetDoubleTapSupportForPlatformEnabled(true); gesture_provider_->SetMultiTouchZoomSupportEnabled(true); - int secondary_coord_x = kFakeCoordX + 20 * touch_slop; - int secondary_coord_y = kFakeCoordY + 20 * touch_slop; + int secondary_coord_x = kFakeCoordX + 20 * tap_slop; + int secondary_coord_y = kFakeCoordY + 20 * tap_slop; // First finger down. MockMotionEvent event = @@ -3005,8 +3059,8 @@ EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points()); // Move second finger. - secondary_coord_x += 5 * touch_slop; - secondary_coord_y += 5 * touch_slop; + secondary_coord_x += 5 * tap_slop; + secondary_coord_y += 5 * tap_slop; event = ObtainMotionEvent(event_time, MotionEvent::Action::MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); @@ -3269,7 +3323,7 @@ // the tap count. event_time += GetValidDoubleTapDelay(); event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN, kFakeCoordX, - kFakeCoordY + GetTouchSlop() / 2); + kFakeCoordY + GetTapSlop() / 2); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); @@ -3333,7 +3387,7 @@ event_time += GetValidDoubleTapDelay(); event = ObtainMotionEvent(event_time, MotionEvent::Action::DOWN, kFakeCoordX, - kFakeCoordY + GetTouchSlop() / 2); + kFakeCoordY + GetTapSlop() / 2); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); event = ObtainMotionEvent(event_time, MotionEvent::Action::UP); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
diff --git a/ui/events/gesture_detection/snap_scroll_controller.cc b/ui/events/gesture_detection/snap_scroll_controller.cc index 7310249..7d2e81a 100644 --- a/ui/events/gesture_detection/snap_scroll_controller.cc +++ b/ui/events/gesture_detection/snap_scroll_controller.cc
@@ -37,19 +37,13 @@ } // namespace -SnapScrollController::SnapScrollController(float snap_bound, - const gfx::SizeF& display_size) - : snap_bound_(snap_bound), - channel_distance_(CalculateChannelDistance(snap_bound, display_size)), - mode_(SNAP_NONE) { -} - -SnapScrollController::~SnapScrollController() { -} +SnapScrollController::SnapScrollController(const gfx::SizeF& display_size) + : display_size_(display_size) {} void SnapScrollController::SetSnapScrollMode( const MotionEvent& event, - bool is_scale_gesture_detection_in_progress) { + bool is_scale_gesture_detection_in_progress, + float slop_distance) { switch (event.GetAction()) { case MotionEvent::Action::DOWN: mode_ = SNAP_PENDING; @@ -63,13 +57,13 @@ if (mode_ != SNAP_PENDING) break; - // Set scrolling mode to SNAP_X if scroll exceeds |snap_bound_| and the + // Set scrolling mode to SNAP_X if scroll exceeds |slop_distance| and the // ratio of x movement to y movement is sufficiently large. Similarly for // SNAP_Y and y movement. float dx = std::abs(event.GetX() - down_position_.x()); float dy = std::abs(event.GetY() - down_position_.y()); - float kMinSnapBound = snap_bound_; - float kMaxSnapBound = snap_bound_ * 2.f; + float kMinSnapBound = slop_distance; + float kMaxSnapBound = slop_distance * 2.f; if (dx * dx + dy * dy > kMinSnapBound * kMinSnapBound) { if (!dy || (dx / dy > kMinSnapRatio && dy < kMaxSnapBound)) mode_ = SNAP_HORIZ; @@ -91,22 +85,27 @@ } void SnapScrollController::UpdateSnapScrollMode(float distance_x, - float distance_y) { + float distance_y, + float slop_distance) { if (!IsSnappingScrolls()) return; + float channel_distance = + CalculateChannelDistance(slop_distance, display_size_); accumulated_distance_ += gfx::Vector2dF(std::abs(distance_x), std::abs(distance_y)); if (mode_ == SNAP_HORIZ) { - if (accumulated_distance_.y() > channel_distance_) + if (accumulated_distance_.y() > channel_distance) { mode_ = SNAP_NONE; - else if (accumulated_distance_.x() > channel_distance_) + } else if (accumulated_distance_.x() > channel_distance) { accumulated_distance_ = gfx::Vector2dF(); + } } else if (mode_ == SNAP_VERT) { - if (accumulated_distance_.x() > channel_distance_) + if (accumulated_distance_.x() > channel_distance) { mode_ = SNAP_NONE; - else if (accumulated_distance_.y() > channel_distance_) + } else if (accumulated_distance_.y() > channel_distance) { accumulated_distance_ = gfx::Vector2dF(); + } } }
diff --git a/ui/events/gesture_detection/snap_scroll_controller.h b/ui/events/gesture_detection/snap_scroll_controller.h index 19526f7..a14f134 100644 --- a/ui/events/gesture_detection/snap_scroll_controller.h +++ b/ui/events/gesture_detection/snap_scroll_controller.h
@@ -6,33 +6,35 @@ #define UI_EVENTS_GESTURE_DETECTION_SNAP_SCROLL_CONTROLLER_H_ #include "ui/events/gesture_detection/gesture_detection_export.h" +#include "ui/events/gesture_detection/motion_event.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace ui { -class MotionEvent; - // Port of SnapScrollController.java from Chromium // Controls the scroll snapping behavior based on scroll updates. class GESTURE_DETECTION_EXPORT SnapScrollController { public: - SnapScrollController(float snap_bound, const gfx::SizeF& display_size); + explicit SnapScrollController(const gfx::SizeF& display_size); SnapScrollController(const SnapScrollController&) = delete; SnapScrollController& operator=(const SnapScrollController&) = delete; - ~SnapScrollController(); + ~SnapScrollController() = default; // Sets the snap scroll mode based on the event type. void SetSnapScrollMode(const MotionEvent& event, - bool is_scale_gesture_detection_in_progress); + bool is_scale_gesture_detection_in_progress, + float slop_distance); // Updates the snap scroll mode based on the given X and Y distance to be // moved on scroll. If the scroll update is above a threshold, the snapping // behavior is reset. - void UpdateSnapScrollMode(float distance_x, float distance_y); + void UpdateSnapScrollMode(float distance_x, + float distance_y, + float slop_distance); bool IsSnapVertical() const; bool IsSnapHorizontal() const; @@ -41,9 +43,8 @@ private: enum SnapMode { SNAP_NONE, SNAP_PENDING, SNAP_HORIZ, SNAP_VERT }; - const float snap_bound_; - const float channel_distance_; - SnapMode mode_; + gfx::SizeF display_size_; + SnapMode mode_ = SNAP_NONE; gfx::PointF down_position_; gfx::Vector2dF accumulated_distance_; };
diff --git a/ui/events/gesture_detection/snap_scroll_controller_unittest.cc b/ui/events/gesture_detection/snap_scroll_controller_unittest.cc index 8b453ce..928840a 100644 --- a/ui/events/gesture_detection/snap_scroll_controller_unittest.cc +++ b/ui/events/gesture_detection/snap_scroll_controller_unittest.cc
@@ -22,7 +22,7 @@ } // namespace TEST(SnapScrollControllerTest, Basic) { - SnapScrollController controller(kSnapBound, GetDisplayBounds()); + SnapScrollController controller(GetDisplayBounds()); EXPECT_FALSE(controller.IsSnappingScrolls()); EXPECT_FALSE(controller.IsSnapHorizontal()); EXPECT_FALSE(controller.IsSnapVertical()); @@ -30,137 +30,137 @@ // Test basic horizontal snapping. MockMotionEvent event; event.PressPoint(0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, kSnapBound * 2, 0.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_TRUE(controller.IsSnappingScrolls()); EXPECT_TRUE(controller.IsSnapHorizontal()); EXPECT_FALSE(controller.IsSnapVertical()); event.ReleasePoint(); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); // Test basic vertical snapping. event.PressPoint(0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, 0.f, kSnapBound * 2); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_TRUE(controller.IsSnappingScrolls()); EXPECT_TRUE(controller.IsSnapVertical()); EXPECT_FALSE(controller.IsSnapHorizontal()); } TEST(SnapScrollControllerTest, VerticalScroll) { - SnapScrollController controller(kSnapBound, GetDisplayBounds()); + SnapScrollController controller(GetDisplayBounds()); EXPECT_FALSE(controller.IsSnappingScrolls()); MockMotionEvent event; event.PressPoint(0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, 0.f, -kSnapBound / 2.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, kSnapBound / 2.f, -kSnapBound * 2.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_TRUE(controller.IsSnapVertical()); EXPECT_FALSE(controller.IsSnapHorizontal()); // Initial scrolling should be snapped. float delta_x = event.GetX(0); float delta_y = event.GetY(0); - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_TRUE(controller.IsSnapVertical()); EXPECT_FALSE(controller.IsSnapHorizontal()); // Subsequent scrolling should be snapped as long as it's within the rails. delta_x = 5; delta_y = 10; - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_TRUE(controller.IsSnapVertical()); EXPECT_FALSE(controller.IsSnapHorizontal()); // Large horizontal movement should end snapping. delta_x = 100; delta_y = 10; - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); } TEST(SnapScrollControllerTest, HorizontalScroll) { - SnapScrollController controller(kSnapBound, GetDisplayBounds()); + SnapScrollController controller(GetDisplayBounds()); EXPECT_FALSE(controller.IsSnappingScrolls()); MockMotionEvent event; event.PressPoint(0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, -kSnapBound / 2.f, 0.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, kSnapBound * 2.f, kSnapBound / 2.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_TRUE(controller.IsSnapHorizontal()); EXPECT_FALSE(controller.IsSnapVertical()); // Initial scrolling should be snapped. float delta_x = event.GetX(0); float delta_y = event.GetY(0); - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_TRUE(controller.IsSnapHorizontal()); EXPECT_FALSE(controller.IsSnapVertical()); // Subsequent scrolling should be snapped as long as it's within the rails. delta_x = 10; delta_y = 5; - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_TRUE(controller.IsSnapHorizontal()); EXPECT_FALSE(controller.IsSnapVertical()); // Large vertical movement should end snapping. delta_x = 10; delta_y = 100; - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); } TEST(SnapScrollControllerTest, Diagonal) { - SnapScrollController controller(kSnapBound, GetDisplayBounds()); + SnapScrollController controller(GetDisplayBounds()); EXPECT_FALSE(controller.IsSnappingScrolls()); MockMotionEvent event; event.PressPoint(0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); // Sufficient initial diagonal motion will prevent any future snapping. event.MovePoint(0, kSnapBound * 3.f, -kSnapBound * 3.f); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); float delta_x = event.GetX(0); float delta_y = event.GetY(0); - controller.UpdateSnapScrollMode(delta_x, delta_y); + controller.UpdateSnapScrollMode(delta_x, delta_y, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, 0, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, kSnapBound * 5, 0); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); event.MovePoint(0, 0, -kSnapBound * 5); - controller.SetSnapScrollMode(event, false); + controller.SetSnapScrollMode(event, false, kSnapBound); EXPECT_FALSE(controller.IsSnappingScrolls()); }
diff --git a/ui/gfx/linux/gbm_wrapper.cc b/ui/gfx/linux/gbm_wrapper.cc index 973a93ac..40ebcc3 100644 --- a/ui/gfx/linux/gbm_wrapper.cc +++ b/ui/gfx/linux/gbm_wrapper.cc
@@ -318,7 +318,16 @@ uint32_t format, const gfx::Size& size, gfx::NativePixmapHandle handle) override { - DCHECK_EQ(handle.planes[0].offset, 0u); + if (handle.planes.empty()) { + LOG(ERROR) << "Importing handle with no planes"; + return nullptr; + } + if (handle.planes[0].offset != 0u) { + LOG(ERROR) << "Unsupported handle: expected an offset of 0 for the first " + "plane; got " + << handle.planes[0].offset; + return nullptr; + } int gbm_flags = 0; if ((gbm_flags = GetSupportedGbmFlags(format)) == 0) {
diff --git a/ui/gl/features.gni b/ui/gl/features.gni index 411fa479..5d62ba59 100644 --- a/ui/gl/features.gni +++ b/ui/gl/features.gni
@@ -18,9 +18,9 @@ # Should Dawn support be compiled to back the WebGPU implementation? # Also controls linking Dawn dependencies in such as SPIRV-Tools/SPIRV-Cross. - # TODO(crbug.com/1361532): Enable non-component builds on Android use_dawn = is_mac || is_win || is_chromeos_ash || (is_linux && !is_castos) || - is_chromeos_lacros || (is_android && is_component_build) + is_chromeos_lacros || + (is_android && target_cpu != "x86" && target_cpu != "x64") # Should Dawn test binaries (unittests, end2end_tests, perf_tests) be built? # Independent of use_dawn, which controls whether Dawn is used in Chromium.
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index d1ea8eb0..5fa8e00 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -64,8 +64,9 @@ void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (base::Contains(blockers_, blocker)) + if (base::Contains(blockers_, blocker)) { return; + } blocker->AddObserver(this); blockers_.push_back(blocker); @@ -75,8 +76,9 @@ NotificationBlocker* blocker) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto iter = base::ranges::find(blockers_, blocker); - if (iter == blockers_.end()) + if (iter == blockers_.end()) { return; + } blocker->RemoveObserver(this); blockers_.erase(iter); } @@ -91,11 +93,13 @@ notification_list_->GetVisibleNotifications(blockers_); for (const std::string& notification_id : blocked) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationUpdated(notification_id); + } } - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnBlockingStateChanged(blocker); + } } void MessageCenterImpl::SetVisibility(Visibility visibility) { @@ -107,16 +111,19 @@ notification_list_->SetNotificationsShown(blockers_, &updated_ids); for (const auto& id : updated_ids) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationUpdated(id); + } } - for (Notification* notification : GetPopupNotifications()) + for (Notification* notification : GetPopupNotifications()) { MarkSinglePopupAsShown(notification->id(), false); + } } - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnCenterVisibilityChanged(visibility); + } } bool MessageCenterImpl::IsMessageCenterVisible() const { @@ -126,8 +133,6 @@ ExpandState MessageCenterImpl::GetNotificationExpandState( const std::string& id) { - DCHECK(FindVisibleNotificationById(id)); - return notification_list_->GetNotificationExpandState(id); } @@ -216,8 +221,9 @@ const auto& notifications = GetVisibleNotifications(); for (Notification* notification : notifications) { - if (notification->id() == id) + if (notification->id() == id) { return notification; + } } return nullptr; @@ -264,8 +270,9 @@ notification->set_allow_group(notifications_grouping_enabled_); const std::string id = notification->id(); - for (NotificationBlocker* blocker : blockers_) + for (NotificationBlocker* blocker : blockers_) { blocker->CheckState(); + } // Sometimes the notification can be added with the same id and the // |notification_list| will replace the notification instead of adding new. @@ -285,26 +292,30 @@ notification_list_->AddNotification(std::move(notification)); visible_notifications_ = notification_list_->GetVisibleNotifications(blockers_); - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationAdded(id); + } } void MessageCenterImpl::UpdateNotification( const std::string& old_id, std::unique_ptr<Notification> new_notification) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - for (NotificationBlocker* blocker : blockers_) + for (NotificationBlocker* blocker : blockers_) { blocker->CheckState(); + } auto* old_notification = notification_list_->GetNotificationById(old_id); if (old_notification) { DCHECK(old_notification->notifier_id() == new_notification->notifier_id()); // Copy grouping metadata to the new notification. - if (old_notification->group_parent()) + if (old_notification->group_parent()) { new_notification->SetGroupParent(); - if (old_notification->group_child()) + } + if (old_notification->group_child()) { new_notification->SetGroupChild(); + } } std::string new_id = new_notification->id(); @@ -327,8 +338,9 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); Notification* notification = notification_list_->GetNotificationById(id); - if (!notification) + if (!notification) { return; + } if (by_user && notification->pinned()) { // When pinned, a popup will not be removed completely but moved into the @@ -349,13 +361,15 @@ // RemoveNotification reentrantly. notification_list_->RemoveNotification(copied_id); - if (delegate.get()) + if (delegate.get()) { delegate->Close(by_user); + } visible_notifications_ = notification_list_->GetVisibleNotifications(blockers_); - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationRemoved(copied_id, by_user); + } } void MessageCenterImpl::RemoveNotificationsForNotifierId( @@ -363,8 +377,9 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NotificationList::Notifications notifications = notification_list_->GetNotificationsByNotifierId(notifier_id); - for (Notification* notification : notifications) + for (Notification* notification : notifications) { RemoveNotification(notification->id(), false); + } if (!notifications.empty()) { visible_notifications_ = notification_list_->GetVisibleNotifications(blockers_); @@ -383,8 +398,9 @@ notification_list_->GetVisibleNotifications(blockers); std::set<std::string> ids; for (Notification* notification : notifications) { - if (!remove_pinned && notification->pinned()) + if (!remove_pinned && notification->pinned()) { continue; + } ids.insert(notification->id()); scoped_refptr<NotificationDelegate> delegate = notification->delegate(); @@ -393,8 +409,9 @@ // RemoveNotification reentrantly. notification_list_->RemoveNotification(notification->id()); - if (delegate.get()) + if (delegate.get()) { delegate->Close(by_user); + } } if (!ids.empty()) { @@ -402,8 +419,9 @@ notification_list_->GetVisibleNotifications(blockers_); } for (const auto& id : ids) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationRemoved(id, by_user); + } } } @@ -412,8 +430,9 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (notification_list_->SetNotificationIcon(notification_id, image)) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationUpdated(notification_id); + } } } @@ -421,15 +440,17 @@ const gfx::Image& image) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (notification_list_->SetNotificationImage(notification_id, image)) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationUpdated(notification_id); + } } } void MessageCenterImpl::ClickOnNotification(const std::string& id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } lock_screen_controller_->DismissLockScreenThenExecute( base::BindOnce(&MessageCenterImpl::ClickOnNotificationUnlocked, @@ -440,8 +461,9 @@ void MessageCenterImpl::ClickOnNotificationButton(const std::string& id, int button_index) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } lock_screen_controller_->DismissLockScreenThenExecute( base::BindOnce(&MessageCenterImpl::ClickOnNotificationUnlocked, @@ -454,8 +476,9 @@ int button_index, const std::u16string& reply) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } lock_screen_controller_->DismissLockScreenThenExecute( base::BindOnce(&MessageCenterImpl::ClickOnNotificationUnlocked, @@ -473,18 +496,22 @@ DCHECK(!lock_screen_controller_->IsScreenLocked()); // Ensure the notification is still visible. - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } - if (HasMessageCenterView() && HasPopupNotifications()) + if (HasMessageCenterView() && HasPopupNotifications()) { MarkSinglePopupAsShown(id, true); - for (MessageCenterObserver& observer : observer_list_) + } + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationClicked(id, button_index, reply); + } scoped_refptr<NotificationDelegate> delegate = notification_list_->GetNotificationDelegate(id); - if (delegate) + if (delegate) { delegate->Click(button_index, reply); + } if (const Notification* notification = notification_list_->GetNotificationById(id); @@ -501,11 +528,13 @@ notification && (notification->rich_notification_data().settings_button_handler == SettingsButtonHandler::DELEGATE); - if (handled_by_delegate) + if (handled_by_delegate) { notification->delegate()->SettingsClick(); + } - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationSettingsClicked(handled_by_delegate); + } } void MessageCenterImpl::DisableNotification(const std::string& id) { @@ -521,8 +550,9 @@ void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id, bool mark_notification_as_read) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } if (HasMessageCenterView()) { notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read); @@ -558,23 +588,27 @@ // This method may be called from the handlers, so we shouldn't manipulate // notifications in this method. - if (!FindVisibleNotificationById(id)) + if (!FindVisibleNotificationById(id)) { return; + } - if (HasPopupNotifications()) + if (HasPopupNotifications()) { notification_list_->MarkSinglePopupAsDisplayed(id); + } scoped_refptr<NotificationDelegate> delegate = notification_list_->GetNotificationDelegate(id); - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnNotificationDisplayed(id, source); + } } void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (in_quiet_mode != notification_list_->quiet_mode()) { notification_list_->SetQuietMode(in_quiet_mode); - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnQuietModeChanged(in_quiet_mode); + } } quiet_mode_timer_.Stop(); } @@ -589,8 +623,9 @@ if (!quiet_mode_timer_.IsRunning()) { notification_list_->SetQuietMode(true); - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnQuietModeChanged(true); + } } // This will restart the timer if it is already running. @@ -601,14 +636,16 @@ void MessageCenterImpl::RestartPopupTimers() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (popup_timers_controller_) + if (popup_timers_controller_) { popup_timers_controller_->StartAll(); + } } void MessageCenterImpl::PausePopupTimers() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (popup_timers_controller_) + if (popup_timers_controller_) { popup_timers_controller_->PauseAll(); + } } const std::u16string& MessageCenterImpl::GetSystemNotificationAppName() const { @@ -622,8 +659,9 @@ void MessageCenterImpl::OnMessageViewHovered( const std::string& notification_id) { - for (MessageCenterObserver& observer : observer_list_) + for (MessageCenterObserver& observer : observer_list_) { observer.OnMessageViewHovered(notification_id); + } } void MessageCenterImpl::DisableTimersForTest() {
diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h index 80719f0..9f2ba43 100644 --- a/ui/message_center/public/cpp/notification.h +++ b/ui/message_center/public/cpp/notification.h
@@ -52,6 +52,21 @@ enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING }; +enum class NotificationScenario { + DEFAULT = 0, + INCOMING_CALL = 1, // When created by an installed origin, the notification + // should have increased priority, colored buttons, a + // ringtone, and a default "close" button. If the origin + // is not installed, it should behave like `DEFAULT`, but + // with the added "Close" button. +}; + +enum class ButtonType { + DEFAULT = 0, // Default notification button. + ACKNOWLEDGE = 1, // Incoming call acknowledge button. + DISMISS = 2, // Incoming call dismiss button. +}; + // Represents a button to be shown as part of a notification. struct MESSAGE_CENTER_PUBLIC_EXPORT ButtonInfo { explicit ButtonInfo(const std::u16string& title); @@ -73,6 +88,10 @@ // text input type buttons until the user has entered a response themselves. // If the value is null, there is no input field associated with the button. absl::optional<std::u16string> placeholder; + + // Describes the button intended usage. This is used by the underlying + // platform to take behavioral and stylistic decisions. + ButtonType type = ButtonType::DEFAULT; }; enum class FullscreenVisibility { @@ -214,6 +233,10 @@ // Whether the notification should be removed from the MessageCenter when it's // clicked after the delegate has been executed (if any). bool remove_on_click = false; + + // Changes notification behavior and look depending on the selected scenario + // and on whether the notification was created by an installed origin. + NotificationScenario scenario = NotificationScenario::DEFAULT; }; class MESSAGE_CENTER_PUBLIC_EXPORT Notification { @@ -491,6 +514,11 @@ optional_fields_.fullscreen_visibility = visibility; } + NotificationScenario scenario() const { return optional_fields_.scenario; } + void set_scenario(NotificationScenario scenario) { + optional_fields_.scenario = scenario; + } + NotificationDelegate* delegate() const { return delegate_.get(); } const RichNotificationData& rich_notification_data() const {
diff --git a/ui/message_center/views/notification_view_base.cc b/ui/message_center/views/notification_view_base.cc index 8a3e960..5135e7a 100644 --- a/ui/message_center/views/notification_view_base.cc +++ b/ui/message_center/views/notification_view_base.cc
@@ -185,7 +185,9 @@ // LargeImageView ////////////////////////////////////////////////////////////// LargeImageView::LargeImageView(const gfx::Size& max_size) - : max_size_(max_size), min_size_(max_size_.width(), /*height=*/0) {} + : max_size_(max_size), min_size_(max_size_.width(), /*height=*/0) { + SetID(NotificationViewBase::kLargeImageView); +} LargeImageView::~LargeImageView() = default;
diff --git a/ui/message_center/views/notification_view_base.h b/ui/message_center/views/notification_view_base.h index e29e688d..f689bac 100644 --- a/ui/message_center/views/notification_view_base.h +++ b/ui/message_center/views/notification_view_base.h
@@ -107,6 +107,7 @@ kHeaderLeftContent, kCollapsedSummaryView, kAppIconViewContainer, + kLargeImageView, }; NotificationViewBase(const NotificationViewBase&) = delete;
diff --git a/ui/ozone/common/native_pixmap_egl_binding.cc b/ui/ozone/common/native_pixmap_egl_binding.cc index 0b1e0f63..3e0625ef 100644 --- a/ui/ozone/common/native_pixmap_egl_binding.cc +++ b/ui/ozone/common/native_pixmap_egl_binding.cc
@@ -89,11 +89,6 @@ return gl_image_->GetInternalFormat(); } -GLenum NativePixmapEGLBinding::GetDataFormat() { - return NativePixmapGLBinding::GetDataFormatFromInternalFormat( - GetInternalFormat()); -} - GLenum NativePixmapEGLBinding::GetDataType() { return BufferFormatToGLDataType(format_); }
diff --git a/ui/ozone/common/native_pixmap_egl_binding.h b/ui/ozone/common/native_pixmap_egl_binding.h index 132fd6d..c0a0fb21 100644 --- a/ui/ozone/common/native_pixmap_egl_binding.h +++ b/ui/ozone/common/native_pixmap_egl_binding.h
@@ -38,7 +38,6 @@ // NativePixmapGLBinding: GLuint GetInternalFormat() override; - GLenum GetDataFormat() override; GLenum GetDataType() override; private:
diff --git a/ui/ozone/platform/flatland/flatland_connection.cc b/ui/ozone/platform/flatland/flatland_connection.cc index d15dbcb..ac23b52 100644 --- a/ui/ozone/platform/flatland/flatland_connection.cc +++ b/ui/ozone/platform/flatland/flatland_connection.cc
@@ -46,7 +46,8 @@ present_args.set_acquire_fences({}); present_args.set_release_fences({}); present_args.set_unsquashable(false); - Present(std::move(present_args), base::BindOnce([](zx_time_t) {})); + Present(std::move(present_args), + base::BindOnce([](base::TimeTicks, base::TimeDelta) {})); } void FlatlandConnection::Present( @@ -71,6 +72,16 @@ void FlatlandConnection::OnNextFrameBegin( fuchsia::ui::composition::OnNextFrameBeginValues values) { + // Calculate the presentation interval by looking at the 2 closest + // presentation times. + if (values.has_future_presentation_infos() && + values.future_presentation_infos().size() > 1) { + presentation_interval_ = + base::TimeTicks::FromZxTime( + values.future_presentation_infos()[1].presentation_time()) - + base::TimeTicks::FromZxTime( + values.future_presentation_infos()[0].presentation_time()); + } present_credits_ += values.additional_present_credits(); if (present_credits_ && !pending_presents_.empty()) { // Only iterate over the elements once, because they may be added back to @@ -86,7 +97,9 @@ void FlatlandConnection::OnFramePresented( fuchsia::scenic::scheduling::FramePresentedInfo info) { for (size_t i = 0; i < info.presentation_infos.size(); ++i) { - std::move(presented_callbacks_.front()).Run(info.actual_presentation_time); + std::move(presented_callbacks_.front()) + .Run(base::TimeTicks::FromZxTime(info.actual_presentation_time), + presentation_interval_); presented_callbacks_.pop(); } }
diff --git a/ui/ozone/platform/flatland/flatland_connection.h b/ui/ozone/platform/flatland/flatland_connection.h index 46d52815..817a1136 100644 --- a/ui/ozone/platform/flatland/flatland_connection.h +++ b/ui/ozone/platform/flatland/flatland_connection.h
@@ -12,17 +12,19 @@ #include "base/containers/queue.h" #include "base/functional/callback.h" #include "base/strings/string_piece.h" +#include "base/time/time.h" namespace ui { // Helper class used to own fuchsia.ui.composition.Flatland to safely call -// Present. By limiting the number of Present calls, FlatlandConnection ensures -// that the Flatland will not be shut down, thus, users of FlatlandConnection -// should not call Flatland::Present on their own. +// Present. By limiting the number of Present calls, FlatlandConnection +// ensures that the Flatland will not be shut down, thus, users of +// FlatlandConnection should not call Flatland::Present on their own. class FlatlandConnection final { public: using OnFramePresentedCallback = - base::OnceCallback<void(zx_time_t actual_presentation_time)>; + base::OnceCallback<void(base::TimeTicks actual_presentation_time, + base::TimeDelta future_presentation_interval)>; using OnErrorCallback = base::OnceCallback<void(fuchsia::ui::composition::FlatlandError error)>; @@ -50,6 +52,10 @@ OnFramePresentedCallback callback); private: + // Initial fps value to calculate the future presentation interval, that is + // used until Flatland's OnNextFrameBegin() callback is received. + static constexpr int kInitialFramesPerSecondEstimate = 60; + // Method that is listening to Flatland's OnNextFrameBegin() callback. // Returns one or more present credits. void OnNextFrameBegin( @@ -63,6 +69,10 @@ uint64_t next_content_id_ = 0; uint32_t present_credits_ = 1; + // Stores the presentation interval for the future frames. + base::TimeDelta presentation_interval_ = + base::Hertz(kInitialFramesPerSecondEstimate); + struct PendingPresent { PendingPresent(fuchsia::ui::composition::PresentArgs present_args, OnFramePresentedCallback callback); @@ -78,10 +88,10 @@ // Keeps track of pending Presents that cannot be committed in the situation // when we don't have enough present credits. base::queue<PendingPresent> pending_presents_; - // Keeps track of release fences for the previous frame, indicating when it is - // safe to reuse the resources. Ozone defines and sends release fences for - // the current frame, whereas Flatland expects the release fences for the - // previous frame resources. + // Keeps track of release fences for the previous frame, indicating when it + // is safe to reuse the resources. Ozone defines and sends release fences + // for the current frame, whereas Flatland expects the release fences for + // the previous frame resources. std::vector<zx::event> previous_present_release_fences_; // Keeps track of Presents that are committed, but Flatland hasn't indicated // that have taken effect by calling OnFramePresented().
diff --git a/ui/ozone/platform/flatland/flatland_connection_unittest.cc b/ui/ozone/platform/flatland/flatland_connection_unittest.cc index 7236c0a..5648b1b 100644 --- a/ui/ozone/platform/flatland/flatland_connection_unittest.cc +++ b/ui/ozone/platform/flatland/flatland_connection_unittest.cc
@@ -109,7 +109,7 @@ flatland_connection.Present( std::move(present_args), base::BindLambdaForTesting( - [&on_presented_called](zx_time_t actual_presentation_time) { + [&on_presented_called](base::TimeTicks, base::TimeDelta) { on_presented_called = true; })); task_environment_.RunUntilIdle(); @@ -141,6 +141,66 @@ EXPECT_TRUE(on_presented_called); } +TEST_F(FlatlandConnectionTest, CalculatesPresentationInterval) { + // Set up callbacks which allow sensing of how many presents were handled. + size_t presents_called = 0u; + fake_flatland_.SetPresentHandler( + [&presents_called](fuchsia::ui::composition::PresentArgs present_args) { + presents_called++; + }); + + // Create the FlatlandConnection but don't pump the loop. No FIDL calls are + // completed yet. + FlatlandConnection flatland_connection( + GetCurrentTestName(), + base::BindLambdaForTesting( + [](fuchsia::ui::composition::FlatlandError) { FAIL(); })); + EXPECT_EQ(presents_called, 0u); + + fuchsia::ui::composition::PresentArgs present_args; + present_args.set_requested_presentation_time(0); + present_args.set_acquire_fences({}); + present_args.set_release_fences({}); + present_args.set_unsquashable(false); + bool on_presented_called = false; + base::TimeDelta presentation_interval; + flatland_connection.Present( + std::move(present_args), + base::BindLambdaForTesting( + [&on_presented_called, &presentation_interval]( + base::TimeTicks, base::TimeDelta interval) { + on_presented_called = true; + presentation_interval = interval; + })); + task_environment_.RunUntilIdle(); + EXPECT_EQ(presents_called, 1u); + + // Fire OnNextFrameBegin() followed by FramePresented() to trigger + // OnFramePresentedCallback. + const zx_time_t kStartTime = 123; + fuchsia::scenic::scheduling::PresentationInfo info_1; + info_1.set_presentation_time(kStartTime); + const zx_duration_t kInterval = 345; + fuchsia::scenic::scheduling::PresentationInfo info_2; + info_2.set_presentation_time(kStartTime + kInterval); + std::vector<fuchsia::scenic::scheduling::PresentationInfo> infos; + infos.push_back(std::move(info_1)); + infos.push_back(std::move(info_2)); + fuchsia::ui::composition::OnNextFrameBeginValues on_next_frame_begin_values; + on_next_frame_begin_values.set_future_presentation_infos(std::move(infos)); + on_next_frame_begin_values.set_additional_present_credits(1); + fake_flatland_.FireOnNextFrameBeginEvent( + std::move(on_next_frame_begin_values)); + + fuchsia::scenic::scheduling::FramePresentedInfo frame_presented_info_1; + frame_presented_info_1.presentation_infos.resize(1); + fake_flatland_.FireOnFramePresentedEvent(std::move(frame_presented_info_1)); + + task_environment_.RunUntilIdle(); + EXPECT_TRUE(on_presented_called); + EXPECT_EQ(base::TimeDelta::FromZxDuration(kInterval), presentation_interval); +} + TEST_F(FlatlandConnectionTest, ReleaseFences) { // Set up callbacks which allow sensing of how many presents were handled. size_t presents_called = 0u;
diff --git a/ui/ozone/platform/flatland/flatland_surface.cc b/ui/ozone/platform/flatland/flatland_surface.cc index d1f1dce..c166126 100644 --- a/ui/ozone/platform/flatland/flatland_surface.cc +++ b/ui/ozone/platform/flatland/flatland_surface.cc
@@ -26,17 +26,13 @@ namespace { -// Default interval used for vsync callback. -// TODO(fxbug.dev/93998): Remove the usage of this by calculating fps through -// Display API and present callbacks. -constexpr base::TimeDelta kDefaultVsyncInterval = base::Seconds(1) / 60; - std::vector<zx::event> GpuFenceHandlesToZxEvents( std::vector<gfx::GpuFenceHandle> handles) { std::vector<zx::event> events; events.reserve(handles.size()); - for (auto& handle : handles) + for (auto& handle : handles) { events.push_back(std::move(handle.owned_event)); + } return events; } @@ -208,8 +204,9 @@ const auto overlay_plane_transform = overlay.overlay_plane_data.plane_transform; - if (overlay.gpu_fence) + if (overlay.gpu_fence) { acquire_fences.push_back(overlay.gpu_fence->GetGpuFenceHandle().Clone()); + } child_transforms_[overlay.overlay_plane_data.z_order] = transform_id; const auto rounded_bounds = @@ -225,15 +222,14 @@ image_id, GfxSizeToFuchsiaSize(rounded_bounds.size(), overlay_plane_transform)); - gfx::RectF crop_rect = overlay.overlay_plane_data.crop_rect; - crop_rect.Scale(rounded_bounds.width(), rounded_bounds.height()); - const auto rounded_crop_rect = gfx::ToRoundedRect(crop_rect); - fuchsia::math::Rect clip_rect = { - rounded_crop_rect.x(), rounded_crop_rect.y(), rounded_crop_rect.width(), - rounded_crop_rect.height()}; - flatland_.flatland()->SetClipBoundary( - transform_id, - std::make_unique<fuchsia::math::Rect>(std::move(clip_rect))); + // `crop_rect` is in normalized coordinates, but Flatland expects it to be + // given in image coordinates. + gfx::RectF sample_region = overlay.overlay_plane_data.crop_rect; + const gfx::Size& buffer_size = overlay.pixmap->GetBufferSize(); + sample_region.Scale(buffer_size.width(), buffer_size.height()); + flatland_.flatland()->SetImageSampleRegion( + image_id, {sample_region.x(), sample_region.y(), sample_region.width(), + sample_region.height()}); flatland_.flatland()->SetImageBlendingFunction( image_id, overlay.overlay_plane_data.enable_blend ? fuchsia::ui::composition::BlendMode::SRC_OVER @@ -344,12 +340,15 @@ auto iter = pixmap_ids_to_flatland_ids_.find(ids); DCHECK(iter != pixmap_ids_to_flatland_ids_.end()); flatland_.flatland()->ReleaseImage(iter->second.image_id); - if (iter->second.transform_id.value) + if (iter->second.transform_id.value) { flatland_.flatland()->ReleaseTransform(iter->second.transform_id); + } pixmap_ids_to_flatland_ids_.erase(iter); } -void FlatlandSurface::OnPresentComplete(zx_time_t actual_presentation_time) { +void FlatlandSurface::OnPresentComplete( + base::TimeTicks actual_presentation_time, + base::TimeDelta presentation_interval) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); TRACE_EVENT_NESTABLE_ASYNC_END1("viz", "FlatlandSurface::PresentFrame", TRACE_ID_LOCAL(this), "image_id", @@ -360,9 +359,9 @@ std::move(frame.completion_callback) .Run(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_ACK)); std::move(frame.presentation_callback) - .Run(gfx::PresentationFeedback( - base::TimeTicks::FromZxTime(actual_presentation_time), - kDefaultVsyncInterval, gfx::PresentationFeedback::kVSync)); + .Run(gfx::PresentationFeedback(actual_presentation_time, + presentation_interval, + gfx::PresentationFeedback::kVSync)); pending_frames_.pop_front(); }
diff --git a/ui/ozone/platform/flatland/flatland_surface.h b/ui/ozone/platform/flatland/flatland_surface.h index 04a77263..6308b0e 100644 --- a/ui/ozone/platform/flatland/flatland_surface.h +++ b/ui/ozone/platform/flatland/flatland_surface.h
@@ -104,7 +104,8 @@ void RemovePixmapResources(FlatlandPixmapId pixmap_id); - void OnPresentComplete(zx_time_t actual_presentation_time); + void OnPresentComplete(base::TimeTicks actual_presentation_time, + base::TimeDelta presentation_interval); FlatlandIds CreateOrGetFlatlandIds(gfx::NativePixmap* pixmap, bool is_primary_plane);
diff --git a/ui/ozone/platform/flatland/flatland_surface_unittest.cc b/ui/ozone/platform/flatland/flatland_surface_unittest.cc index 61a548c1..2effb145 100644 --- a/ui/ozone/platform/flatland/flatland_surface_unittest.cc +++ b/ui/ozone/platform/flatland/flatland_surface_unittest.cc
@@ -90,6 +90,7 @@ fuchsia::ui::composition::BlendMode blend_mode, const fuchsia::math::Vec& translation = FakeTransform::kDefaultTranslation, Orientation orientation = FakeTransform::kDefaultOrientation, + const fuchsia::math::RectF& sample_region = FakeImage::kDefaultSampleRegion, const fuchsia::math::SizeU& destination_size = FakeImage::kDefaultDestinationSize, float image_opacity = FakeImage::kDefaultOpacity, @@ -100,15 +101,17 @@ Field("scale", &FakeTransform::scale, FakeTransform::kDefaultScale), Field("opacity", &FakeTransform::opacity, FakeTransform::kDefaultOpacity), Field("children", &FakeTransform::children, IsEmpty()), - Field("content", &FakeTransform::content, - Pointee(VariantWith<FakeImage>( - AllOf(Field("image_properties", &FakeImage::image_properties, - IsImageProperties(size)), - Field("destination_size", &FakeImage::destination_size, - destination_size), - Field("blend_mode", &FakeImage::blend_mode, blend_mode), - Field("opacity", &FakeImage::opacity, image_opacity), - Field("flip", &FakeImage::flip, image_flip))))))); + Field( + "content", &FakeTransform::content, + Pointee(VariantWith<FakeImage>(AllOf( + Field("image_properties", &FakeImage::image_properties, + IsImageProperties(size)), + Field("sample_region", &FakeImage::sample_region, sample_region), + Field("destination_size", &FakeImage::destination_size, + destination_size), + Field("blend_mode", &FakeImage::blend_mode, blend_mode), + Field("opacity", &FakeImage::opacity, image_opacity), + Field("flip", &FakeImage::flip, image_flip))))))); } scoped_refptr<FlatlandSysmemNativePixmap> CreateFlatlandSysmemNativePixmap( @@ -368,9 +371,13 @@ const float kOverlayOpacity = .7f; const gfx::RectF kOverlayBounds(kOverlayX, kOverlayY, kOverlayWidth, kOverlayHeight); + const float kCropX = 2.2f; + const float kCropY = 6.6f; + const float kCropWidth = 14.4f; + const float kCropHeight = 16.6f; gfx::OverlayPlaneData overlay_data( /*z_order=*/1, input_transform, kOverlayBounds, - /*crop_rect=*/gfx::RectF(), + gfx::RectF(kCropX, kCropY, kCropWidth, kCropHeight), /*enable_blend=*/true, /*damage_rect=*/gfx::Rect(), kOverlayOpacity, gfx::OverlayPriorityHint::kNone, @@ -398,11 +405,15 @@ {expected_scale, expected_scale}, {IsImageTransform({kExpectedImageSize, kExpectedImageSize}, fuchsia::ui::composition::BlendMode::SRC_OVER), - IsImageTransform({kExpectedImageSize, kExpectedImageSize}, - fuchsia::ui::composition::BlendMode::SRC_OVER, - expected_translation, expected_orientation, - expected_image_destination_size, kOverlayOpacity, - expected_image_flip)})); + IsImageTransform( + {kExpectedImageSize, kExpectedImageSize}, + fuchsia::ui::composition::BlendMode::SRC_OVER, + expected_translation, expected_orientation, + {kCropX * kExpectedImageSize, kCropY * kExpectedImageSize, + kCropWidth * kExpectedImageSize, + kCropHeight * kExpectedImageSize}, + expected_image_destination_size, kOverlayOpacity, + expected_image_flip)})); } } // namespace ui
diff --git a/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc b/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc index d760e88..ce3d36c7 100644 --- a/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc +++ b/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc
@@ -121,11 +121,6 @@ return gl::BufferFormatToGLInternalFormat(format_); } -GLenum NativePixmapEGLX11Binding::GetDataFormat() { - return NativePixmapGLBinding::GetDataFormatFromInternalFormat( - GetInternalFormat()); -} - GLenum NativePixmapEGLX11Binding::GetDataType() { return GL_UNSIGNED_BYTE; }
diff --git a/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h b/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h index cf4fbf4..c3d04b4 100644 --- a/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h +++ b/ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h
@@ -34,7 +34,6 @@ // NativePixmapGLBinding: GLuint GetInternalFormat() override; - GLenum GetDataFormat() override; GLenum GetDataType() override; private:
diff --git a/ui/ozone/public/native_pixmap_gl_binding.cc b/ui/ozone/public/native_pixmap_gl_binding.cc index 83e4eae7..3c2c86c 100644 --- a/ui/ozone/public/native_pixmap_gl_binding.cc +++ b/ui/ozone/public/native_pixmap_gl_binding.cc
@@ -36,33 +36,4 @@ return true; } -// static -unsigned NativePixmapGLBinding::GetDataFormatFromInternalFormat( - unsigned internalformat) { - // |internalformat| is mostly an unsized format that can be used both - // as internal format and data format. However, GL_EXT_texture_norm16 - // follows ES3 semantics and only exposes a sized internalformat. - switch (internalformat) { - case GL_R16_EXT: - return GL_RED_EXT; - case GL_RG16_EXT: - return GL_RG_EXT; - case GL_RGB10_A2_EXT: - return GL_RGBA; - case GL_RGB_YCRCB_420_CHROMIUM: - case GL_RGB_YCBCR_420V_CHROMIUM: - case GL_RGB_YCBCR_P010_CHROMIUM: - return GL_RGB; - case GL_RED: - case GL_RG: - case GL_RGB: - case GL_RGBA: - case GL_BGRA_EXT: - return internalformat; - default: - NOTREACHED(); - return GL_NONE; - } -} - } // namespace ui
diff --git a/ui/ozone/public/native_pixmap_gl_binding.h b/ui/ozone/public/native_pixmap_gl_binding.h index b938bc5..04933b04 100644 --- a/ui/ozone/public/native_pixmap_gl_binding.h +++ b/ui/ozone/public/native_pixmap_gl_binding.h
@@ -23,7 +23,6 @@ virtual ~NativePixmapGLBinding(); virtual GLuint GetInternalFormat() = 0; - virtual GLenum GetDataFormat() = 0; virtual GLenum GetDataType() = 0; protected: @@ -34,12 +33,6 @@ // and corresponding code for GLImageEGLPixmap will move to // NativePixmapEGLX11Binding leading to the deletion of BindTexture here. static bool BindTexture(gl::GLImage* image, GLenum target, GLuint texture_id); - - // Converts a value that is aligned with glTexImage{2|3}D's |internalformat| - // parameter to the value that is correspondingly aligned with - // glTexImage{2|3}D's |format| parameter. The returned enum is based on ES2 - // contexts and is mostly ES3 compatible, except for GL_HALF_FLOAT_OES. - static unsigned GetDataFormatFromInternalFormat(unsigned internalformat); }; } // namespace ui
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 36bc22a..accb869 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -27,6 +27,8 @@ "checkbox_normal.icon", "close.icon", "drag_general_selection.icon", + "eye.icon", + "eye_crossed.icon", "ic_close.icon", "info.icon", "launch.icon", @@ -129,6 +131,7 @@ "controls/combobox/combobox_util.h", "controls/dot_indicator.h", "controls/editable_combobox/editable_combobox.h", + "controls/editable_combobox/editable_password_combobox.h", "controls/focus_ring.h", "controls/focusable_border.h", "controls/highlight_path_generator.h", @@ -360,6 +363,7 @@ "controls/combobox/empty_combobox_model.h", "controls/dot_indicator.cc", "controls/editable_combobox/editable_combobox.cc", + "controls/editable_combobox/editable_password_combobox.cc", "controls/focus_ring.cc", "controls/focusable_border.cc", "controls/highlight_path_generator.cc", @@ -1171,6 +1175,7 @@ "controls/button/toggle_button_unittest.cc", "controls/combobox/combobox_unittest.cc", "controls/editable_combobox/editable_combobox_unittest.cc", + "controls/editable_combobox/editable_password_combobox_unittest.cc", "controls/image_view_unittest.cc", "controls/label_unittest.cc", "controls/link_fragment_unittest.cc",
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.h b/ui/views/cocoa/native_widget_mac_ns_window_host.h index 1c30148..6651147 100644 --- a/ui/views/cocoa/native_widget_mac_ns_window_host.h +++ b/ui/views/cocoa/native_widget_mac_ns_window_host.h
@@ -241,15 +241,6 @@ // Used by NativeWidgetPrivate::GetGlobalCapture. static NSView* GetGlobalCaptureView(); - // Add, update and remove the remote window controls overlay view for a PWA. - void AddRemoteWindowControlsOverlayView( - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type); - void UpdateRemoteWindowControlsOverlayView( - const gfx::Rect& bounds, - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type); - void RemoveRemoteWindowControlsOverlayView( - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type); - // Notify PWA whether can GoBack/GoForward. void CanGoBack(bool can_go_back); void CanGoForward(bool can_go_forward);
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm index 0cb9bea..ddd7410 100644 --- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm +++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -819,22 +819,6 @@ [remote_cocoa::CocoaMouseCapture::GetGlobalCaptureWindow() contentView]; } -void NativeWidgetMacNSWindowHost::AddRemoteWindowControlsOverlayView( - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) { - GetNSWindowMojo()->CreateWindowControlsOverlayNSView(overlay_type); -} - -void NativeWidgetMacNSWindowHost::UpdateRemoteWindowControlsOverlayView( - const gfx::Rect& bounds, - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) { - GetNSWindowMojo()->UpdateWindowControlsOverlayNSView(bounds, overlay_type); -} - -void NativeWidgetMacNSWindowHost::RemoveRemoteWindowControlsOverlayView( - remote_cocoa::mojom::WindowControlsOverlayNSViewType overlay_type) { - GetNSWindowMojo()->RemoveWindowControlsOverlayNSView(overlay_type); -} - void NativeWidgetMacNSWindowHost::CanGoBack(bool can_go_back) { GetNSWindowMojo()->SetCanGoBack(can_go_back); }
diff --git a/ui/views/controls/button/image_button_factory.cc b/ui/views/controls/button/image_button_factory.cc index 24cb335..3af6185 100644 --- a/ui/views/controls/button/image_button_factory.cc +++ b/ui/views/controls/button/image_button_factory.cc
@@ -141,4 +141,19 @@ InkDrop::Get(button)->SetBaseColorId(icon_color_id); } +void SetToggledImageFromVectorIconWithColorId( + ToggleImageButton* button, + const gfx::VectorIcon& icon, + ui::ColorId icon_color_id, + ui::ColorId icon_disabled_color_id) { + int dip_size = GetDefaultSizeOfVectorIcon(icon); + const ui::ImageModel& normal_image = + ui::ImageModel::FromVectorIcon(icon, icon_color_id, dip_size); + const ui::ImageModel& disabled_image = + ui::ImageModel::FromVectorIcon(icon, icon_disabled_color_id, dip_size); + + button->SetToggledImageModel(Button::STATE_NORMAL, normal_image); + button->SetToggledImageModel(Button::STATE_DISABLED, disabled_image); +} + } // namespace views
diff --git a/ui/views/controls/button/image_button_factory.h b/ui/views/controls/button/image_button_factory.h index 31d29b56..5d1a412 100644 --- a/ui/views/controls/button/image_button_factory.h +++ b/ui/views/controls/button/image_button_factory.h
@@ -75,6 +75,14 @@ ui::ColorId icon_color_id, ui::ColorId icon_disabled_color_id); +// Sets images on a `ToggleImageButton` |button| for STATE_NORMAL and +// STATE_DISABLED with the default size from the given vector icon and colors. +VIEWS_EXPORT void SetToggledImageFromVectorIconWithColorId( + ToggleImageButton* button, + const gfx::VectorIcon& icon, + ui::ColorId icon_color_id, + ui::ColorId icon_disabled_color_id); + } // namespace views #endif // UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_FACTORY_H_
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc index 583b72fc..3b3df954 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.cc +++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -4,6 +4,7 @@ #include "ui/views/controls/editable_combobox/editable_combobox.h" +#include <algorithm> #include <memory> #include <string> #include <vector> @@ -18,7 +19,6 @@ #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/ime/text_input_type.h" #include "ui/base/menu_source_utils.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -38,7 +38,6 @@ #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" #include "ui/gfx/range/range.h" -#include "ui/gfx/render_text.h" #include "ui/gfx/scoped_canvas.h" #include "ui/views/animation/flood_fill_ink_drop_ripple.h" #include "ui/views/animation/ink_drop.h" @@ -53,11 +52,14 @@ #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/menu/menu_types.h" #include "ui/views/controls/textfield/textfield.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/box_layout_view.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/layout_manager.h" #include "ui/views/layout/layout_provider.h" #include "ui/views/style/platform_style.h" #include "ui/views/style/typography.h" +#include "ui/views/vector_icons.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -70,6 +72,8 @@ METADATA_HEADER(Arrow); explicit Arrow(PressedCallback callback) : Button(std::move(callback)) { + SetPreferredSize(gfx::Size(GetComboboxArrowContainerWidthAndMargins(), + ComboboxArrowSize().height())); // Similar to Combobox's TransparentButton. SetFocusBehavior(FocusBehavior::NEVER); button_controller()->set_notify_action( @@ -102,7 +106,6 @@ } private: - // Button: void PaintButtonContents(gfx::Canvas* canvas) override { gfx::ScopedCanvas scoped_canvas(canvas); canvas->ClipRect(GetContentsBounds()); @@ -119,8 +122,9 @@ node_data->role = ax::mojom::Role::kButton; node_data->SetName(GetAccessibleName()); node_data->SetHasPopup(ax::mojom::HasPopup::kMenu); - if (GetEnabled()) + if (GetEnabled()) { node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kOpen); + } } }; @@ -129,6 +133,11 @@ } // namespace +std::u16string EditableCombobox::MenuDecorationStrategy::DecorateItemText( + std::u16string text) const { + return text; +} + // Adapts a ui::ComboboxModel to a ui::MenuModel to be used by EditableCombobox. // Also provides a filtering capability. class EditableCombobox::EditableComboboxMenuModel @@ -136,11 +145,12 @@ public ui::ComboboxModelObserver { public: EditableComboboxMenuModel(EditableCombobox* owner, - ui::ComboboxModel* combobox_model, + std::unique_ptr<ui::ComboboxModel> combobox_model, const bool filter_on_edit, const bool show_on_empty) - : owner_(owner), - combobox_model_(combobox_model), + : decoration_strategy_(std::make_unique<MenuDecorationStrategy>()), + owner_(owner), + combobox_model_(std::move(combobox_model)), filter_on_edit_(filter_on_edit), show_on_empty_(show_on_empty) { UpdateItemsShown(); @@ -154,8 +164,9 @@ ~EditableComboboxMenuModel() override = default; void UpdateItemsShown() { - if (!update_items_shown_enabled_) + if (!update_items_shown_enabled_) { return; + } items_shown_.clear(); if (show_on_empty_ || !owner_->GetText().empty()) { for (size_t i = 0; i < combobox_model_->GetItemCount(); ++i) { @@ -166,8 +177,16 @@ } } } - if (menu_model_delegate()) + if (menu_model_delegate()) { menu_model_delegate()->OnMenuStructureChanged(); + } + } + + void SetDecorationStrategy( + std::unique_ptr<EditableCombobox::MenuDecorationStrategy> strategy) { + DCHECK(strategy); + decoration_strategy_ = std::move(strategy); + UpdateItemsShown(); } void DisableUpdateItemsShown() { update_items_shown_enabled_ = false; } @@ -178,13 +197,12 @@ return MenuConfig::instance().check_selected_combobox_item; } - std::u16string GetItemTextAt(size_t index, bool showing_password_text) const { - size_t index_in_model = items_shown_[index].index; - std::u16string text = combobox_model_->GetItemAt(index_in_model); - return showing_password_text - ? text - : std::u16string(text.length(), - gfx::RenderText::kPasswordReplacementChar); + std::u16string GetItemTextAt(size_t index) const { + return combobox_model_->GetItemAt(items_shown_[index].index); + } + + const ui::ComboboxModel* GetComboboxModel() const { + return combobox_model_.get(); } ui::ImageModel GetIconAt(size_t index) const override { @@ -202,6 +220,14 @@ size_t GetItemCount() const override { return items_shown_.size(); } + // ui::MenuModel: + std::u16string GetLabelAt(size_t index) const override { + std::u16string text = + decoration_strategy_->DecorateItemText(GetItemTextAt(index)); + base::i18n::AdjustStringForLocaleDirection(&text); + return text; + } + private: struct ShownItem { size_t index; @@ -209,8 +235,9 @@ }; bool HasIcons() const override { for (size_t i = 0; i < GetItemCount(); ++i) { - if (!GetIconAt(i).IsEmpty()) + if (!GetIconAt(i).IsEmpty()) { return true; + } } return false; } @@ -228,12 +255,6 @@ return static_cast<int>(index) + kFirstMenuItemId; } - std::u16string GetLabelAt(size_t index) const override { - std::u16string text = GetItemTextAt(index, owner_->showing_password_text_); - base::i18n::AdjustStringForLocaleDirection(&text); - return text; - } - bool IsItemDynamicAt(size_t index) const override { return false; } const gfx::FontList* GetLabelFontListAt(size_t index) const override { @@ -265,8 +286,11 @@ MenuModel* GetSubmenuModelAt(size_t index) const override { return nullptr; } + // The strategy used to customize the display of the dropdown menu. + std::unique_ptr<MenuDecorationStrategy> decoration_strategy_; + raw_ptr<EditableCombobox> owner_; // Weak. Owns |this|. - raw_ptr<ui::ComboboxModel> combobox_model_; // Weak. + std::unique_ptr<ui::ComboboxModel> combobox_model_; // Whether to adapt the items shown to the textfield content. const bool filter_on_edit_; @@ -306,26 +330,30 @@ // ui::EventHandler overrides. void OnMouseEvent(ui::MouseEvent* event) override { if (event->type() == ui::ET_MOUSE_PRESSED && - event->button_flags() == event->changed_button_flags()) + event->button_flags() == event->changed_button_flags()) { HandlePressEvent(event->root_location()); + } } void OnTouchEvent(ui::TouchEvent* event) override { - if (event->type() == ui::ET_TOUCH_PRESSED) + if (event->type() == ui::ET_TOUCH_PRESSED) { HandlePressEvent(event->root_location()); + } } private: void HandlePressEvent(const gfx::Point& root_location) { View* handler = root_view_->GetEventHandlerForPoint(root_location); - if (handler == owner_->textfield_ || handler == owner_->arrow_) + if (handler == owner_->textfield_ || handler == owner_->arrow_) { return; + } owner_->CloseMenu(); } void StopObserving() { - if (!root_view_) + if (!root_view_) { return; + } root_view_->RemovePreTargetHandler(this); root_view_ = nullptr; } @@ -341,36 +369,32 @@ std::unique_ptr<ui::ComboboxModel> combobox_model, const bool filter_on_edit, const bool show_on_empty, - const Type type, const int text_context, const int text_style, const bool display_arrow) : textfield_(new Textfield()), text_context_(text_context), text_style_(text_style), - type_(type), filter_on_edit_(filter_on_edit), - show_on_empty_(show_on_empty), - showing_password_text_(type != Type::kPassword) { + show_on_empty_(show_on_empty) { SetModel(std::move(combobox_model)); observation_.Observe(textfield_.get()); textfield_->set_controller(this); textfield_->SetFontList(GetFontList()); - textfield_->SetTextInputType((type == Type::kPassword) - ? ui::TEXT_INPUT_TYPE_PASSWORD - : ui::TEXT_INPUT_TYPE_TEXT); AddChildView(textfield_.get()); + + control_elements_container_ = AddChildView(std::make_unique<BoxLayoutView>()); + control_elements_container_->SetInsideBorderInsets( + gfx::Insets::TLBR(0, 0, 0, + GetComboboxArrowContainerWidthAndMargins() - + GetComboboxArrowContainerWidth())); + if (display_arrow) { - textfield_->SetExtraInsets( - gfx::Insets::TLBR(0, 0, 0, - GetComboboxArrowContainerWidthAndMargins() - - (features::IsChromeRefresh2023() - ? kComboboxArrowPaddingWidthChromeRefresh2023 - : kComboboxArrowPaddingWidth))); - arrow_ = AddChildView(std::make_unique<Arrow>(base::BindRepeating( + arrow_ = AddControlElement(std::make_unique<Arrow>(base::BindRepeating( &EditableCombobox::ArrowButtonPressed, base::Unretained(this)))); } - SetLayoutManager(std::make_unique<views::FillLayout>()); + + SetLayoutManager(std::make_unique<FillLayout>()); } EditableCombobox::~EditableCombobox() { @@ -380,9 +404,8 @@ void EditableCombobox::SetModel(std::unique_ptr<ui::ComboboxModel> model) { CloseMenu(); - combobox_model_.swap(model); menu_model_ = std::make_unique<EditableComboboxMenuModel>( - this, combobox_model_.get(), filter_on_edit_, show_on_empty_); + this, std::move(model), filter_on_edit_, show_on_empty_); } const std::u16string& EditableCombobox::GetText() const { @@ -406,32 +429,30 @@ void EditableCombobox::OnAccessibleNameChanged(const std::u16string& new_name) { textfield_->SetAccessibleName(new_name); - if (arrow_) + if (arrow_) { arrow_->SetAccessibleName(new_name); + } } void EditableCombobox::SetAssociatedLabel(View* labelling_view) { textfield_->SetAssociatedLabel(labelling_view); } -void EditableCombobox::RevealPasswords(bool revealed) { - DCHECK_EQ(Type::kPassword, type_); - if (revealed == showing_password_text_) - return; - showing_password_text_ = revealed; - textfield_->SetTextInputType(revealed ? ui::TEXT_INPUT_TYPE_TEXT - : ui::TEXT_INPUT_TYPE_PASSWORD); +void EditableCombobox::SetMenuDecorationStrategy( + std::unique_ptr<MenuDecorationStrategy> strategy) { + DCHECK(menu_model_); + menu_model_->SetDecorationStrategy(std::move(strategy)); +} + +void EditableCombobox::UpdateMenu() { menu_model_->UpdateItemsShown(); } void EditableCombobox::Layout() { View::Layout(); - if (arrow_) { - gfx::Rect arrow_bounds( - /*x=*/width() - GetComboboxArrowContainerWidthAndMargins(), - /*y=*/0, GetComboboxArrowContainerWidth(), height()); - arrow_->SetBoundsRect(arrow_bounds); - } + int preferred_width = control_elements_container_->GetPreferredSize().width(); + control_elements_container_->SetBounds(width() - preferred_width, 0, + preferred_width, height()); } void EditableCombobox::GetAccessibleNodeData(ui::AXNodeData* node_data) { @@ -478,8 +499,9 @@ views::AnimatingLayoutManager* source, bool is_animating) { dropdown_blocked_for_animation_ = is_animating; - if (dropdown_blocked_for_animation_) + if (dropdown_blocked_for_animation_) { CloseMenu(); + } } void EditableCombobox::CloseMenu() { @@ -488,10 +510,7 @@ } void EditableCombobox::OnItemSelected(size_t index) { - // |textfield_| can hide the characters on its own so we read the actual - // characters instead of gfx::RenderText::kPasswordReplacementChar characters. - std::u16string selected_item_text = - menu_model_->GetItemTextAt(index, /*showing_password_text=*/true); + std::u16string selected_item_text = menu_model_->GetItemTextAt(index); textfield_->SetText(selected_item_text); // SetText does not actually notify the TextfieldController, so we call the // handling code directly. @@ -513,31 +532,35 @@ content_changed_callback_.Run(); menu_model_->EnableUpdateItemsShown(); } - menu_model_->UpdateItemsShown(); + UpdateMenu(); } void EditableCombobox::ArrowButtonPressed(const ui::Event& event) { textfield_->RequestFocus(); - if (menu_runner_ && menu_runner_->IsRunning()) + if (menu_runner_ && menu_runner_->IsRunning()) { CloseMenu(); - else + } else { ShowDropDownMenu(ui::GetMenuSourceTypeForEvent(event)); + } } void EditableCombobox::ShowDropDownMenu(ui::MenuSourceType source_type) { constexpr int kMenuBorderWidthTop = 1; - if (dropdown_blocked_for_animation_) + if (dropdown_blocked_for_animation_) { return; + } if (!menu_model_->GetItemCount()) { CloseMenu(); return; } - if (menu_runner_ && menu_runner_->IsRunning()) + if (menu_runner_ && menu_runner_->IsRunning()) { return; - if (!GetWidget()) + } + if (!GetWidget()) { return; + } // Since we don't capture the mouse, we want to see the events that happen in // the EditableCombobox's RootView to get a chance to close the menu if they @@ -567,12 +590,27 @@ MenuAnchorPosition::kTopLeft, source_type); } +void EditableCombobox::UpdateTextfieldInsets() { + textfield_->SetExtraInsets(gfx::Insets::TLBR( + 0, 0, 0, + std::max(control_elements_container_->GetPreferredSize().width() - + (features::IsChromeRefresh2023() + ? kComboboxArrowPaddingWidthChromeRefresh2023 + : kComboboxArrowPaddingWidth), + 0))); +} + const ui::MenuModel* EditableCombobox::GetMenuModelForTesting() const { return menu_model_.get(); } std::u16string EditableCombobox::GetItemTextForTesting(size_t index) const { - return menu_model_->GetItemTextAt(index, showing_password_text_); + return menu_model_->GetLabelAt(index); +} + +const ui::ComboboxModel* EditableCombobox::GetComboboxModel() const { + DCHECK(menu_model_); + return menu_model_->GetComboboxModel(); } BEGIN_METADATA(EditableCombobox, View)
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h index 85c86a56..8eebbda2c 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.h +++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -18,6 +18,7 @@ #include "ui/base/ui_base_types.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/layout/animating_layout_manager.h" +#include "ui/views/layout/box_layout_view.h" #include "ui/views/style/typography.h" #include "ui/views/view.h" #include "ui/views/view_observer.h" @@ -40,6 +41,7 @@ class EditableComboboxPreTargetHandler; class MenuRunner; class Textfield; +class ToggleImageButton; namespace test { class InteractionTestUtilSimulatorViews; @@ -54,9 +56,13 @@ public: METADATA_HEADER(EditableCombobox); - enum class Type { - kRegular, - kPassword, + // A strategy that can be used to customize the display of the drop-down menu. + // It is only intended to be used by classes that extend `EditableCombobox`. + class MenuDecorationStrategy { + public: + virtual ~MenuDecorationStrategy() = default; + + virtual std::u16string DecorateItemText(std::u16string text) const; }; static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON; @@ -70,14 +76,12 @@ // completions of the current textfield content. // |show_on_empty|: Whether to show the drop-down list when there is no // textfield content. - // |type|: The EditableCombobox type. // |text_context| and |text_style|: Together these indicate the font to use. // |display_arrow|: Whether to display an arrow in the combobox to indicate // that there is a drop-down list. explicit EditableCombobox(std::unique_ptr<ui::ComboboxModel> combobox_model, bool filter_on_edit = false, bool show_on_empty = true, - Type type = Type::kRegular, int text_context = kDefaultTextContext, int text_style = kDefaultTextStyle, bool display_arrow = true); @@ -105,12 +109,30 @@ // is a label associated with this combobox. void SetAssociatedLabel(View* labelling_view); - // For Type::kPassword, sets whether the textfield and - // drop-down menu will reveal their current content. - void RevealPasswords(bool revealed); + protected: + // Sets the menu decoration strategy. Setting it triggers an update to the + // menu. + void SetMenuDecorationStrategy( + std::unique_ptr<MenuDecorationStrategy> strategy); + + // Forces an update of the drop-down menu. + void UpdateMenu(); + + // Adds `view` to the set of controls. The ordering is such that views are + // added to the front (i.e. to the left in LTR set-ups). + template <typename T> + T* AddControlElement(std::unique_ptr<T> view) { + T* raw_view = + control_elements_container_->AddChildViewAt(std::move(view), 0); + UpdateTextfieldInsets(); + return raw_view; + } + + Textfield& GetTextfield() { return *textfield_; } private: friend class EditableComboboxTest; + friend class EditablePasswordComboboxTest; friend class test::InteractionTestUtilSimulatorViews; class EditableComboboxMenuModel; class EditableComboboxPreTargetHandler; @@ -129,10 +151,18 @@ // Shows the drop-down menu. void ShowDropDownMenu(ui::MenuSourceType source_type = ui::MENU_SOURCE_NONE); + // Recalculates the extra insets of the textfield based on the size of the + // controls container. + void UpdateTextfieldInsets(); + // These are for unit tests to get data from private implementation classes. const ui::MenuModel* GetMenuModelForTesting() const; std::u16string GetItemTextForTesting(size_t index) const; + // Returns the underlying combobox model. Used only by + // `ui::test::InteractionTestUtil`. + const ui::ComboboxModel* GetComboboxModel() const; + // Overridden from View: void Layout() override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; @@ -155,8 +185,9 @@ bool is_animating) override; raw_ptr<Textfield> textfield_; + raw_ptr<BoxLayoutView> control_elements_container_ = nullptr; raw_ptr<Button> arrow_ = nullptr; - std::unique_ptr<ui::ComboboxModel> combobox_model_; + raw_ptr<ToggleImageButton> eye_ = nullptr; // The EditableComboboxMenuModel used by |menu_runner_|. std::unique_ptr<EditableComboboxMenuModel> menu_model_; @@ -174,23 +205,17 @@ // shown in the drop-down menu. const int text_style_; - const Type type_; - // Whether to adapt the items shown to the textfield content. - bool filter_on_edit_; + const bool filter_on_edit_; // Whether to show options when the textfield is empty. - bool show_on_empty_; + const bool show_on_empty_; // Set while the drop-down is showing. std::unique_ptr<MenuRunner> menu_runner_; base::RepeatingClosure content_changed_callback_; - // Whether we are currently showing the passwords for type - // Type::kPassword. - bool showing_password_text_; - bool dropdown_blocked_for_animation_ = false; base::ScopedObservation<View, ViewObserver> observation_{this};
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index 9a5db495..31cebb8c 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -28,8 +28,8 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image_unittest_util.h" -#include "ui/gfx/render_text.h" #include "ui/views/context_menu_controller.h" +#include "ui/views/controls/combobox/combobox_util.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/test/menu_test_utils.h" @@ -90,17 +90,14 @@ bool show_on_empty = true); // Initializes the combobox with the given items. - void InitEditableCombobox( - const std::vector<std::u16string>& items, - bool filter_on_edit, - bool show_on_empty = true, - EditableCombobox::Type type = EditableCombobox::Type::kRegular); + void InitEditableCombobox(const std::vector<std::u16string>& items, + bool filter_on_edit, + bool show_on_empty = true); void InitEditableCombobox( const std::vector<ui::SimpleComboboxModel::Item>& items, bool filter_on_edit, - bool show_on_empty = true, - EditableCombobox::Type type = EditableCombobox::Type::kRegular); + bool show_on_empty = true); // Initializes the widget where the combobox and the dummy control live. void InitWidget(); @@ -186,25 +183,23 @@ void EditableComboboxTest::InitEditableCombobox( const std::vector<std::u16string>& strings, bool filter_on_edit, - bool show_on_empty, - EditableCombobox::Type type) { + bool show_on_empty) { std::vector<ui::SimpleComboboxModel::Item> items; for (const auto& item_str : strings) items.emplace_back(item_str); - InitEditableCombobox(items, filter_on_edit, show_on_empty, type); + InitEditableCombobox(items, filter_on_edit, show_on_empty); } // Initializes the combobox with the given items. void EditableComboboxTest::InitEditableCombobox( const std::vector<ui::SimpleComboboxModel::Item>& items, const bool filter_on_edit, - const bool show_on_empty, - const EditableCombobox::Type type) { + const bool show_on_empty) { parent_of_combobox_ = new View(); parent_of_combobox_->SetID(1); combobox_ = new EditableCombobox(std::make_unique<ui::SimpleComboboxModel>(items), - filter_on_edit, show_on_empty, type); + filter_on_edit, show_on_empty); combobox_->SetCallback(base::BindRepeating( &EditableComboboxTest::OnContentChanged, base::Unretained(this))); combobox_->SetID(2); @@ -847,28 +842,6 @@ ASSERT_EQ(3, change_count()); } -TEST_F(EditableComboboxTest, PasswordCanBeHiddenAndRevealed) { - std::vector<std::u16string> items = {u"item0", u"item1"}; - InitEditableCombobox(items, /*filter_on_edit=*/false, /*show_on_empty=*/true, - EditableCombobox::Type::kPassword); - - ASSERT_EQ(2u, GetItemCount()); - ASSERT_EQ(std::u16string(5, gfx::RenderText::kPasswordReplacementChar), - GetItemAt(0)); - ASSERT_EQ(std::u16string(5, gfx::RenderText::kPasswordReplacementChar), - GetItemAt(1)); - - combobox_->RevealPasswords(/*revealed=*/true); - ASSERT_EQ(u"item0", GetItemAt(0)); - ASSERT_EQ(u"item1", GetItemAt(1)); - - combobox_->RevealPasswords(/*revealed=*/false); - ASSERT_EQ(std::u16string(5, gfx::RenderText::kPasswordReplacementChar), - GetItemAt(0)); - ASSERT_EQ(std::u16string(5, gfx::RenderText::kPasswordReplacementChar), - GetItemAt(1)); -} - TEST_F(EditableComboboxTest, ArrowButtonOpensAndClosesMenu) { InitEditableCombobox(); dummy_focusable_view_->RequestFocus(); @@ -933,18 +906,6 @@ EXPECT_FALSE(IsMenuOpen()); } -TEST_F(EditableComboboxTest, NoCrashWithoutWidget) { - std::vector<ui::SimpleComboboxModel::Item> items = { - ui::SimpleComboboxModel::Item(u"item0"), - ui::SimpleComboboxModel::Item(u"item1")}; - auto combobox = std::make_unique<EditableCombobox>( - std::make_unique<ui::SimpleComboboxModel>(items), - /*filter_on_edit=*/false, - /*show_on_empty=*/true, EditableCombobox::Type::kPassword); - // Showing the dropdown should silently fail. - combobox->RevealPasswords(true); -} - using EditableComboboxDefaultTest = ViewsTestBase; class ConfigurableComboboxModel final : public ui::ComboboxModel {
diff --git a/ui/views/controls/editable_combobox/editable_password_combobox.cc b/ui/views/controls/editable_combobox/editable_password_combobox.cc new file mode 100644 index 0000000..a1b5f48 --- /dev/null +++ b/ui/views/controls/editable_combobox/editable_password_combobox.cc
@@ -0,0 +1,143 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/controls/editable_combobox/editable_password_combobox.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/functional/bind.h" +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "ui/base/ime/text_input_type.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/base/models/combobox_model.h" +#include "ui/gfx/render_text.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/button/image_button_factory.h" +#include "ui/views/controls/editable_combobox/editable_combobox.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/vector_icons.h" + +namespace views { + +namespace { + +// The eye-styled icon that serves as a button to toggle the password +// visibility. +class Eye : public ToggleImageButton { + public: + METADATA_HEADER(Eye); + + constexpr static int kPaddingWidth = 4; + + explicit Eye(PressedCallback callback) + : ToggleImageButton(std::move(callback)) { + SetInstallFocusRingOnFocus(true); + SetRequestFocusOnPress(true); + SetBorder(CreateEmptyBorder(kPaddingWidth)); + + SetImageVerticalAlignment(ImageButton::ALIGN_MIDDLE); + SetImageHorizontalAlignment(ImageButton::ALIGN_CENTER); + + SetImageFromVectorIconWithColorId(this, kEyeIcon, ui::kColorIcon, + ui::kColorIconDisabled); + SetToggledImageFromVectorIconWithColorId( + this, kEyeCrossedIcon, ui::kColorIcon, ui::kColorIconDisabled); + } + + Eye(const Eye&) = delete; + Eye& operator=(const Eye&) = delete; + ~Eye() override = default; +}; + +BEGIN_METADATA(Eye, ToggleImageButton) +END_METADATA + +class PasswordMenuDecorationStrategy + : public EditableCombobox::MenuDecorationStrategy { + public: + explicit PasswordMenuDecorationStrategy( + const EditablePasswordCombobox* parent) + : parent_(parent) { + DCHECK(parent); + } + + std::u16string DecorateItemText(std::u16string text) const override { + return parent_->ArePasswordsRevealed() + ? text + : std::u16string(text.length(), + gfx::RenderText::kPasswordReplacementChar); + } + + private: + const raw_ptr<const EditablePasswordCombobox> parent_; +}; + +} // namespace + +EditablePasswordCombobox::EditablePasswordCombobox() = default; + +EditablePasswordCombobox::EditablePasswordCombobox( + std::unique_ptr<ui::ComboboxModel> combobox_model, + int text_context, + int text_style, + bool display_arrow) + : EditableCombobox(std::move(combobox_model), + /*filter_on_edit=*/false, + /*show_on_empty=*/true, + text_context, + text_style, + display_arrow) { + eye_ = AddControlElement(std::make_unique<Eye>(base::BindRepeating( + &EditablePasswordCombobox::RequestTogglePasswordVisibility, + base::Unretained(this)))); + GetTextfield().SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); + SetMenuDecorationStrategy( + std::make_unique<PasswordMenuDecorationStrategy>(this)); +} + +EditablePasswordCombobox::~EditablePasswordCombobox() = default; + +void EditablePasswordCombobox::SetPasswordIconTooltips( + const std::u16string& tooltip_text, + const std::u16string& toggled_tooltip_text) { + eye_->SetTooltipText(tooltip_text); + eye_->SetToggledTooltipText(toggled_tooltip_text); +} + +void EditablePasswordCombobox::RevealPasswords(bool revealed) { + if (revealed == are_passwords_revealed_) { + return; + } + are_passwords_revealed_ = revealed; + GetTextfield().SetTextInputType(revealed ? ui::TEXT_INPUT_TYPE_TEXT + : ui::TEXT_INPUT_TYPE_PASSWORD); + eye_->SetToggled(revealed); + UpdateMenu(); +} + +bool EditablePasswordCombobox::ArePasswordsRevealed() const { + return are_passwords_revealed_; +} + +void EditablePasswordCombobox::SetIsPasswordRevealPermittedCheck( + IsPasswordRevealPermittedCheck check) { + reveal_permitted_check_ = std::move(check); +} + +void EditablePasswordCombobox::RequestTogglePasswordVisibility() { + if (!are_passwords_revealed_ && reveal_permitted_check_ && + !reveal_permitted_check_.Run()) { + return; + } + RevealPasswords(!are_passwords_revealed_); +} + +BEGIN_METADATA(EditablePasswordCombobox, View) +END_METADATA + +} // namespace views
diff --git a/ui/views/controls/editable_combobox/editable_password_combobox.h b/ui/views/controls/editable_combobox/editable_password_combobox.h new file mode 100644 index 0000000..ccfdf87 --- /dev/null +++ b/ui/views/controls/editable_combobox/editable_password_combobox.h
@@ -0,0 +1,81 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_CONTROLS_EDITABLE_COMBOBOX_EDITABLE_PASSWORD_COMBOBOX_H_ +#define UI_VIEWS_CONTROLS_EDITABLE_COMBOBOX_EDITABLE_PASSWORD_COMBOBOX_H_ + +#include <memory> +#include <string> + +#include "base/functional/callback_forward.h" +#include "base/memory/raw_ptr.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/editable_combobox/editable_combobox.h" + +namespace views { +class ToggleImageButton; + +// Textfield that also shows a drop-down list with suggestions and can switch +// between visible and obfuscated text. +class VIEWS_EXPORT EditablePasswordCombobox : public EditableCombobox { + public: + METADATA_HEADER(EditablePasswordCombobox); + + using IsPasswordRevealPermittedCheck = base::RepeatingCallback<bool(void)>; + + static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON; + static constexpr int kDefaultTextStyle = style::STYLE_PRIMARY; + + EditablePasswordCombobox(); + + // `combobox_model`: The ComboboxModel that gives us the items to show in the + // menu. + // `text_context` and `text_style`: Together these indicate the font to use. + // `display_arrow`: Whether to display an arrow in the combobox to indicate + // that there is a drop-down list. + explicit EditablePasswordCombobox( + std::unique_ptr<ui::ComboboxModel> combobox_model, + int text_context = kDefaultTextContext, + int text_style = kDefaultTextStyle, + bool display_arrow = true); + + EditablePasswordCombobox(const EditablePasswordCombobox&) = delete; + EditablePasswordCombobox& operator=(const EditablePasswordCombobox&) = delete; + + ~EditablePasswordCombobox() override; + + // Sets the tooltips for the password eye icon. + void SetPasswordIconTooltips(const std::u16string& tooltip_text, + const std::u16string& toggled_tooltip_text); + + // Sets and gets whether the textfield and drop-down menu reveal their current + // content. + void RevealPasswords(bool revealed); + bool ArePasswordsRevealed() const; + + // Sets the callback to check whether revealing a password is permitted. + void SetIsPasswordRevealPermittedCheck(IsPasswordRevealPermittedCheck check); + + private: + friend class EditablePasswordComboboxTest; + + // Toggles the password visibility. If the password is currently unrevealed, + // a `PasswordRevealCheck` is set and returns false, then the password remains + // unrevealed. + void RequestTogglePasswordVisibility(); + + ToggleImageButton* GetEyeButtonForTesting() { return eye_.get(); } + + raw_ptr<ToggleImageButton> eye_ = nullptr; + + // Indicates whether the passwords are currently revealed. + bool are_passwords_revealed_ = false; + + // A callback to check whether the password is allowed to be revealed. + IsPasswordRevealPermittedCheck reveal_permitted_check_; +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_EDITABLE_COMBOBOX_EDITABLE_PASSWORD_COMBOBOX_H_
diff --git a/ui/views/controls/editable_combobox/editable_password_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_password_combobox_unittest.cc new file mode 100644 index 0000000..8154b0bc --- /dev/null +++ b/ui/views/controls/editable_combobox/editable_password_combobox_unittest.cc
@@ -0,0 +1,203 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/controls/editable_combobox/editable_password_combobox.h" + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/strings/string_piece.h" +#include "base/test/mock_callback.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/models/combobox_model.h" +#include "ui/base/models/menu_model.h" +#include "ui/base/models/simple_combobox_model.h" +#include "ui/events/test/event_generator.h" +#include "ui/events/types/event_type.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/render_text.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/editable_combobox/editable_combobox.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_utils.h" + +namespace views { + +using ::testing::Return; +using ::testing::StrictMock; + +class EditablePasswordComboboxTest : public ViewsTestBase { + public: + EditablePasswordComboboxTest() = default; + + EditablePasswordComboboxTest(const EditablePasswordComboboxTest&) = delete; + EditablePasswordComboboxTest& operator=(const EditablePasswordComboboxTest&) = + delete; + + // Initializes the combobox and the widget containing it. + void SetUp() override; + + void TearDown() override; + + protected: + size_t GetItemCount() const { + return combobox_->GetMenuModelForTesting()->GetItemCount(); + } + + std::u16string GetItemAt(size_t index) const { + return combobox_->GetItemTextForTesting(index); + } + + // Clicks the eye button to reveal or obscure the password. + void ClickEye() { + ToggleImageButton* eye = combobox_->GetEyeButtonForTesting(); + generator_->MoveMouseTo(eye->GetBoundsInScreen().CenterPoint()); + generator_->ClickLeftButton(); + } + + EditablePasswordCombobox* combobox() { return combobox_.get(); } + + private: + raw_ptr<Widget> widget_ = nullptr; + raw_ptr<EditablePasswordCombobox> combobox_ = nullptr; + + // Used for simulating eye button clicks. + std::unique_ptr<ui::test::EventGenerator> generator_; +}; + +// Initializes the combobox with the given items. +void EditablePasswordComboboxTest::SetUp() { + ViewsTestBase::SetUp(); + + auto combobox = std::make_unique<EditablePasswordCombobox>( + std::make_unique<ui::SimpleComboboxModel>( + std::vector<ui::SimpleComboboxModel::Item>{ + ui::SimpleComboboxModel::Item(u"item0"), + ui::SimpleComboboxModel::Item(u"item1")})); + // Set dummy tooltips and name to avoid running into a11y-related DCHECKs. + combobox->SetPasswordIconTooltips(u"Show password", u"Hide password"); + combobox->SetAccessibleName(u"Password field"); + + widget_ = new Widget(); + Widget::InitParams params = + CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.bounds = gfx::Rect(0, 0, 1000, 1000); + combobox->SetBoundsRect(gfx::Rect(0, 0, 500, 40)); + + widget_->Init(std::move(params)); + View* container = widget_->SetContentsView(std::make_unique<View>()); + combobox_ = container->AddChildView(std::move(combobox)); + + generator_ = + std::make_unique<ui::test::EventGenerator>(GetRootWindow(widget_)); + + widget_->Show(); + +#if BUILDFLAG(IS_MAC) + // The event loop needs to be flushed here, otherwise in various tests: + // 1. The actual showing of the native window backing the widget gets delayed + // until a spin of the event loop. + // 2. The combobox menu object is triggered, and it starts listening for the + // "window did become key" notification as a sign that it lost focus and + // should close. + // 3. The event loop is spun, and the actual showing of the native window + // triggers the close of the menu opened from within the window. + base::RunLoop().RunUntilIdle(); +#endif +} + +void EditablePasswordComboboxTest::TearDown() { + generator_.reset(); + if (widget_) { + widget_->Close(); + } + ViewsTestBase::TearDown(); +} + +TEST_F(EditablePasswordComboboxTest, PasswordCanBeHiddenAndRevealed) { + const std::u16string kObscuredPassword( + 5, gfx::RenderText::kPasswordReplacementChar); + + ASSERT_EQ(2u, GetItemCount()); + EXPECT_FALSE(combobox()->ArePasswordsRevealed()); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); + + combobox()->RevealPasswords(/*revealed=*/true); + EXPECT_TRUE(combobox()->ArePasswordsRevealed()); + EXPECT_EQ(u"item0", GetItemAt(0)); + EXPECT_EQ(u"item1", GetItemAt(1)); + + combobox()->RevealPasswords(/*revealed=*/false); + EXPECT_FALSE(combobox()->ArePasswordsRevealed()); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); +} + +TEST_F(EditablePasswordComboboxTest, EyeButtonClickRevealsAndHidesPassword) { + const std::u16string kObscuredPassword( + 5, gfx::RenderText::kPasswordReplacementChar); + + ASSERT_EQ(2u, GetItemCount()); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); + + ClickEye(); + EXPECT_EQ(u"item0", GetItemAt(0)); + EXPECT_EQ(u"item1", GetItemAt(1)); + + ClickEye(); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); +} + +TEST_F(EditablePasswordComboboxTest, EyeButtonClickRequestsPermission) { + const std::u16string kObscuredPassword( + 5, gfx::RenderText::kPasswordReplacementChar); + + StrictMock<base::MockCallback< + EditablePasswordCombobox::IsPasswordRevealPermittedCheck>> + reveal_check; + combobox()->SetIsPasswordRevealPermittedCheck(reveal_check.Get()); + + ASSERT_EQ(2u, GetItemCount()); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); + + // If the reveal check returns `false`, the passwords remain obscured. + EXPECT_CALL(reveal_check, Run).WillOnce(Return(false)); + ClickEye(); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); + + // If the reveal check returns `true`, the passwords are revealed. + EXPECT_CALL(reveal_check, Run).WillOnce(Return(true)); + ClickEye(); + EXPECT_EQ(u"item0", GetItemAt(0)); + EXPECT_EQ(u"item1", GetItemAt(1)); + + // Unrevealing the passwords does not trigger a check. + ClickEye(); + EXPECT_EQ(kObscuredPassword, GetItemAt(0)); + EXPECT_EQ(kObscuredPassword, GetItemAt(1)); +} + +TEST_F(EditablePasswordComboboxTest, NoCrashWithoutWidget) { + auto combobox = std::make_unique<EditablePasswordCombobox>( + std::make_unique<ui::SimpleComboboxModel>( + std::vector<ui::SimpleComboboxModel::Item>{ + ui::SimpleComboboxModel::Item(u"item0"), + ui::SimpleComboboxModel::Item(u"item1")})); + // Showing the dropdown should silently fail. + combobox->RevealPasswords(true); +} + +} // namespace views
diff --git a/ui/views/interaction/interaction_test_util_views.cc b/ui/views/interaction/interaction_test_util_views.cc index a2288b8..6edffea1 100644 --- a/ui/views/interaction/interaction_test_util_views.cc +++ b/ui/views/interaction/interaction_test_util_views.cc
@@ -480,8 +480,8 @@ auto* const editable_combobox = views::AsViewClass<EditableCombobox>(view); if (!combobox && !editable_combobox) return ui::test::ActionResult::kNotAttempted; - auto* const model = combobox ? combobox->GetModel() - : editable_combobox->combobox_model_.get(); + auto* const model = + combobox ? combobox->GetModel() : editable_combobox->GetComboboxModel(); if (index >= model->GetItemCount()) { LOG(ERROR) << "Item index " << index << " is out of range, there are " << model->GetItemCount() << " items.";
diff --git a/ui/views/interaction/interaction_test_util_views_unittest.cc b/ui/views/interaction/interaction_test_util_views_unittest.cc index 3469c4d..1c9b0ed 100644 --- a/ui/views/interaction/interaction_test_util_views_unittest.cc +++ b/ui/views/interaction/interaction_test_util_views_unittest.cc
@@ -385,8 +385,7 @@ } // Pass the default values for every parameter except for `display_arrow`. auto* const box = contents_->AddChildView(std::make_unique<EditableCombobox>( - CreateComboboxModel(), false, true, EditableCombobox::Type::kRegular, - EditableCombobox::kDefaultTextContext, + CreateComboboxModel(), false, true, EditableCombobox::kDefaultTextContext, EditableCombobox::kDefaultTextStyle, /* display_arrow =*/false)); box->SetAccessibleName(u"Editable Combobox"); auto* const box_el =
diff --git a/chrome/app/vector_icons/eye.icon b/ui/views/vector_icons/eye.icon similarity index 100% rename from chrome/app/vector_icons/eye.icon rename to ui/views/vector_icons/eye.icon
diff --git a/chrome/app/vector_icons/eye_crossed.icon b/ui/views/vector_icons/eye_crossed.icon similarity index 100% rename from chrome/app/vector_icons/eye_crossed.icon rename to ui/views/vector_icons/eye_crossed.icon
diff --git a/ui/webui/resources/cr_components/history_clusters/BUILD.gn b/ui/webui/resources/cr_components/history_clusters/BUILD.gn index 5ac1dc4..93ec5c6 100644 --- a/ui/webui/resources/cr_components/history_clusters/BUILD.gn +++ b/ui/webui/resources/cr_components/history_clusters/BUILD.gn
@@ -43,6 +43,8 @@ "shared_vars.css", ] + static_files = [ "thumb_down_filled_gm_grey.svg" ] + mojo_files_deps = [ ":mojo_bindings_ts__generator" ] mojo_files = [ "$target_gen_dir/history_clusters.mojom-webui.ts" ]
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.html b/ui/webui/resources/cr_components/history_clusters/cluster.html index 1e43e22..a9dc5a0 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.html +++ b/ui/webui/resources/cr_components/history_clusters/cluster.html
@@ -136,6 +136,7 @@ <div id="container" on-visit-clicked="onVisitClicked_" on-open-all-visits="onOpenAllVisits_" on-remove-all-visits="onRemoveAllVisits_" + on-hide-visit="onHideVisit_" on-remove-visit="onRemoveVisit_"> <div class="label-row"> <span id="label" class="truncate"></span> @@ -147,13 +148,15 @@ </div> </div> <template is="dom-repeat" items="[[visibleVisits_]]"> - <url-visit visit="[[item]]" query="[[query]]"></url-visit> + <url-visit visit="[[item]]" query="[[query]]" from-persistence="[[cluster.fromPersistence]]"> + </url-visit> </template> <!-- Disable animation on iron-collapse, as the parent iron-list can't easily handle it. --> <iron-collapse opened="[[expanded_]]" no-animation> <template is="dom-repeat" items="[[hiddenVisits_]]"> - <url-visit visit="[[item]]" query="[[query]]"></url-visit> + <url-visit visit="[[item]]" query="[[query]]" from-persistence="[[cluster.fromPersistence]]"> + </url-visit> </template> </iron-collapse> <div id="related-searches" hidden="[[!cluster.relatedSearches.length]]"
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.ts b/ui/webui/resources/cr_components/history_clusters/cluster.ts index cbc20bd..eb4746a7 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.ts +++ b/ui/webui/resources/cr_components/history_clusters/cluster.ts
@@ -144,6 +144,7 @@ private expanded_: boolean; private hiddenVisits_: URLVisit[]; private inSidePanel_: boolean; + private onVisitsHiddenListenerId_: number|null = null; private onVisitsRemovedListenerId_: number|null = null; private unusedLabel_: string; private visibleVisits_: URLVisit[]; @@ -165,13 +166,21 @@ override connectedCallback() { super.connectedCallback(); + this.onVisitsHiddenListenerId_ = + this.callbackRouter_.onVisitsHidden.addListener( + this.onVisitsRemovedOrHidden_.bind(this)); this.onVisitsRemovedListenerId_ = this.callbackRouter_.onVisitsRemoved.addListener( - this.onVisitsRemoved_.bind(this)); + this.onVisitsRemovedOrHidden_.bind(this)); } override disconnectedCallback() { super.disconnectedCallback(); + + assert(this.onVisitsHiddenListenerId_); + this.callbackRouter_.removeListener(this.onVisitsHiddenListenerId_); + this.onVisitsHiddenListenerId_ = null; + assert(this.onVisitsRemovedListenerId_); this.callbackRouter_.removeListener(this.onVisitsRemovedListenerId_); this.onVisitsRemovedListenerId_ = null; @@ -230,9 +239,18 @@ })); } + private onHideVisit_(event: CustomEvent<URLVisit>) { + // The actual hiding is handled in clusters.ts. This is just a good place to + // record the metric. + const visit = event.detail; + MetricsProxyImpl.getInstance().recordVisitAction( + VisitAction.kHidden, this.getVisitIndex_(visit), + MetricsProxyImpl.getVisitType(visit)); + } + private onRemoveVisit_(event: CustomEvent<URLVisit>) { - // The actual removal is handled at in clusters.ts. This is just a good - // place to record the metric. + // The actual removal is handled in clusters.ts. This is just a good place + // to record the metric. const visit = event.detail; MetricsProxyImpl.getInstance().recordVisitAction( VisitAction.kDeleted, this.getVisitIndex_(visit), @@ -287,12 +305,12 @@ } /** - * Called with the original remove params when the last accepted request to - * browser to remove visits succeeds. Since the same visit may appear in - * multiple Clusters, all Clusters receive this callback in order to get a - * chance to remove their matching visits. + * Called with the original remove or hide params when the last accepted + * request to browser to remove or hide visits succeeds. Since the same visit + * may appear in multiple Clusters, all Clusters receive this callback in + * order to get a chance to remove their matching visits. */ - private onVisitsRemoved_(removedVisits: URLVisit[]) { + private onVisitsRemovedOrHidden_(removedVisits: URLVisit[]) { const visitHasBeenRemoved = (visit: URLVisit) => { return removedVisits.findIndex((removedVisit) => { if (visit.normalizedUrl.url !== removedVisit.normalizedUrl.url) {
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.html b/ui/webui/resources/cr_components/history_clusters/clusters.html index 2302ad0..f46d3a5c 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.html +++ b/ui/webui/resources/cr_components/history_clusters/clusters.html
@@ -57,7 +57,8 @@ [[placeholderText_]] </div> <iron-list id="clusters" items="[[result_.clusters]]" - on-remove-visits="onRemoveVisits_" hidden="[[!result_.clusters.length]]"> + on-hide-visit="onHideVisit_" on-remove-visits="onRemoveVisits_" + hidden="[[!result_.clusters.length]]"> <!-- We must have a tabindex on these history-cluster elements, because iron-list gets very confused handling arrow keys without them. Moreover, we can't allow Tab to traverse all list elements because:
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.ts b/ui/webui/resources/cr_components/history_clusters/clusters.ts index 704f9303..8f0993a 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.ts +++ b/ui/webui/resources/cr_components/history_clusters/clusters.ts
@@ -228,6 +228,13 @@ } /** + * Called with `event` received from a visit requesting to be hidden. + */ + private onHideVisit_(event: CustomEvent<URLVisit>) { + this.pageHandler_.hideVisits([event.detail]); + } + + /** * Called with `event` received from a cluster requesting to be removed from * the list when all its visits have been removed. Contains the cluster index. */
diff --git a/ui/webui/resources/cr_components/history_clusters/history_clusters.mojom b/ui/webui/resources/cr_components/history_clusters/history_clusters.mojom index f1a458a..fa463c3f 100644 --- a/ui/webui/resources/cr_components/history_clusters/history_clusters.mojom +++ b/ui/webui/resources/cr_components/history_clusters/history_clusters.mojom
@@ -60,6 +60,7 @@ // Actions that can be performed on visits. enum VisitAction { kClicked, + kHidden, kDeleted, }; @@ -81,6 +82,9 @@ // However, the time of the least recent visit as well as the raw URLs of those // duplicative visits are preserved for deletion purposes. struct URLVisit { + // ID for this visit in the history DB. + int64 visit_id; + // Normalized URL of the visited webpage. Only Search Results Page urls will // be normalized for now; This is because SRP visits for the same search terms // have slightly different URLs due to various query params such as the AQS. @@ -152,6 +156,10 @@ // The image URL associated with this cluster. url.mojom.Url? image_url; + // Set to true if this cluster was loaded from SQL rather than dynamically + // generated. + bool from_persistence; + // Additional debug string to show. This is not visible in production, and // used for development only. Disabled by default, but can be enabled by the // 'JourneysUserVisibleDebug' flag. @@ -167,7 +175,7 @@ // The Clusters in the result set in reverse chronological order. This is // always non-zero length, unless `continuation_end_time` is also null, // indicating that we have exhausted History. - array<history_clusters.mojom.Cluster> clusters; + array<Cluster> clusters; // True if there is another page of clusters that the UI can request. bool can_load_more; @@ -207,6 +215,10 @@ // to the bottom of the page. `query` is passed through for sanity checking. LoadMoreClusters(string query); + // Requests to hide the visits by visit IDs. The returned Promise resolves + // with whether the request succeeded in the History backend layer. + HideVisits(array<URLVisit> visits) => (bool success); + // Requests to remove all visits to the specified URLs in the specified // timespan in `visits`. This includes the less recent visits to the same set // of URLs whose information is preserved in `visits`. The returned Promise @@ -242,6 +254,10 @@ // Called when the browser has found a suitable image for `cluster_index`. OnClusterImageUpdated(int32 cluster_index, url.mojom.Url image_url); + // Called with the set of hidden visits when the last accepted call to + // `HideVisits()` succeeds. `hidden_visits` will be used to update the UI. + OnVisitsHidden(array<URLVisit> hidden_visits); + // Called with the set of removed visits when the last accepted call to // `RemoveVisits()` succeeds. `removed_visits` will be used to update the UI. OnVisitsRemoved(array<URLVisit> removed_visits);
diff --git a/ui/webui/resources/cr_components/history_clusters/thumb_down_filled_gm_grey.svg b/ui/webui/resources/cr_components/history_clusters/thumb_down_filled_gm_grey.svg new file mode 100644 index 0000000..3ca8ea31 --- /dev/null +++ b/ui/webui/resources/cr_components/history_clusters/thumb_down_filled_gm_grey.svg
@@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="#455A64"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M0 0h24v24H0V0z" fill="none"/><path d="M3 17h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 24s7.09-6.85 7.17-7V4H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2zM19 17h4V4h-4v13z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.html b/ui/webui/resources/cr_components/history_clusters/url_visit.html index 432d573..f86cb525 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.html +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.html
@@ -1,4 +1,4 @@ -<style include="history-clusters-shared-style"> +<style include="history-clusters-shared-style cr-icons"> :host { align-items: center; cursor: pointer; @@ -10,18 +10,23 @@ background-color: var(--cr-hover-background-color); } - #actionMenuButton { + .suffix-icons { + display: flex; opacity: 0; /* Hides the element while keeping it in tab order. */ position: absolute; /* Surrender its layout space to other elements. */ --cr-icon-button-margin-end: 8px; } - :host(:hover) #actionMenuButton, - #actionMenuButton:focus-within { + :host(:hover) .suffix-icons, + .suffix-icons:focus-within { opacity: 1; position: static; } + .thumb-down-filled-gm-grey { + --cr-icon-image: url(chrome://resources/cr_components/history_clusters/thumb_down_filled_gm_grey.svg); + } + #header { align-items: center; display: flex; @@ -127,17 +132,27 @@ <span id="debug-info" hidden="[[!debugInfo_]]">[[debugInfo_]]</span> </div> </a> - <cr-icon-button id="actionMenuButton" class="icon-more-vert" - title$="[[i18n('actionMenuDescription')]]" aria-haspopup="menu" - on-click="onActionMenuButtonClick_" - hidden="[[!allowDeletingHistory_]]"> - </cr-icon-button> + <div class="suffix-icons"> + <cr-icon-button class="thumb-down-filled-gm-grey" + title$="[[i18n('hideFromCluster')]]" + on-click="onHideSelfButtonClick_" + hidden="[[!showHideVisitIcon_]]"></cr-icon-button> + <cr-icon-button id="actionMenuButton" class="icon-more-vert" + title$="[[i18n('actionMenuDescription')]]" aria-haspopup="menu" + on-click="onActionMenuButtonClick_" + hidden="[[!showActionMenuButton_]]"> + </cr-icon-button> + </div> </div> <cr-lazy-render id="actionMenu"> <template> <cr-action-menu role-description="[[i18n('actionMenuDescription')]]"> - <button id="removeSelfButton" class="dropdown-item" + <button id="hideSelfButton" class="dropdown-item" hidden="[[!showHideVisitMenu_]]" + on-click="onHideSelfButtonClick_"> + [[i18n('hideFromCluster')]] + </button> + <button id="removeSelfButton" class="dropdown-item" hidden="[[!allowDeletingHistory_]]" on-click="onRemoveSelfButtonClick_"> [[i18n('removeFromHistory')]] </button>
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.ts b/ui/webui/resources/cr_components/history_clusters/url_visit.ts index 9b4f377..4d713fe 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.ts +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.ts
@@ -72,6 +72,11 @@ visit: Object, /** + * Whether this visit is within a persisted cluster. + */ + fromPersistence: Boolean, + + /** * Annotations to show for the visit (e.g., whether page was bookmarked). */ annotations_: { @@ -80,6 +85,25 @@ }, /** + * True when the hide-visits feature is enabled, not showing the hide + * visits icon, and the visit is hide-able (i.e. belongs to a persisted + * cluster). + */ + showHideVisitMenu_: { + type: Boolean, + computed: 'computeShowHideVisitMenu_(fromPersistence)', + }, + + /** + * Similar to `showHideVisitMenu_`, but showing the icon instead of the + * menu button. + */ + showHideVisitIcon_: { + type: Boolean, + computed: 'computeShowHideVisitIcon_(fromPersistence)', + }, + + /** * Usually this is true, but this can be false if deleting history is * prohibited by Enterprise policy. */ @@ -89,6 +113,15 @@ }, /** + * The action menu is hidden when the menu would be empty; i.e., both the + * hide visits and delete visits buttons are disabled. + */ + showActionMenuButton_: { + type: Boolean, + computed: 'computeShowActionMenuButton_(showHideVisitMenu_)', + }, + + /** * Debug info for the visit. */ debugInfo_: { @@ -133,8 +166,12 @@ query: string; visit: URLVisit; + fromPersistence: boolean; private annotations_: string[]; + private showHideVisitMenu_: boolean; + private showHideVisitIcon_: boolean; private allowDeletingHistory_: boolean; + private showActionMenuButton_: boolean; private debugInfo_: string; private inSidePanel_: boolean; private unusedTitle_: string; @@ -195,10 +232,18 @@ event.preventDefault(); // Prevent default browser action (navigation). } + private onHideSelfButtonClick_(event: Event) { + this.emitMenuButtonClick_(event, 'hide-visit'); + } + private onRemoveSelfButtonClick_(event: Event) { + this.emitMenuButtonClick_(event, 'remove-visit'); + } + + private emitMenuButtonClick_(event: Event, emitEventName: string) { event.preventDefault(); // Prevent default browser action (navigation). - this.dispatchEvent(new CustomEvent('remove-visit', { + this.dispatchEvent(new CustomEvent(emitEventName, { bubbles: true, composed: true, detail: this.visit, @@ -211,7 +256,7 @@ // Helper methods //============================================================================ - private computeAnnotations_(): string[] { + private computeAnnotations_(_visit: URLVisit): string[] { // Disabling annotations until more appropriate design for annotations in // the side panel is complete. if (this.inSidePanel_) { @@ -227,7 +272,25 @@ .map((id: string) => loadTimeData.getString(id)); } - private computeDebugInfo_(): string { + private computeShowHideVisitMenu_(_fromPersistence: boolean): boolean { + // Show the hide menu item if the visit is hide-able and the hide icon is + // hidden. + return this.fromPersistence && + loadTimeData.getBoolean('isHideVisitsEnabled') && + !loadTimeData.getBoolean('isHideVisitsIconEnabled'); + } + + private computeShowHideVisitIcon_(_fromPersistence: boolean): boolean { + return this.fromPersistence && + loadTimeData.getBoolean('isHideVisitsIconEnabled'); + } + + private computeShowActionMenuButton_(_showHideVisitMenu: boolean): boolean { + // Show the menu if either the hide or delete button is visible. + return this.showHideVisitMenu_ || this.allowDeletingHistory_; + } + + private computeDebugInfo_(_visit: URLVisit): string { if (!loadTimeData.getBoolean('isHistoryClustersDebug')) { return ''; }
diff --git a/ui/wm/core/cursor_util.cc b/ui/wm/core/cursor_util.cc index c8963ff4..9aeadca 100644 --- a/ui/wm/core/cursor_util.cc +++ b/ui/wm/core/cursor_util.cc
@@ -7,6 +7,7 @@ #include "base/check_op.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor_size.h" @@ -101,253 +102,259 @@ } } -struct HotPoint { - int x; - int y; +struct CursorResourceData { + CursorType type; + int id; + gfx::Point hotspot_1x; + gfx::Point hotspot_2x; }; -struct CursorData { - CursorType id; - int resource_id; - HotPoint hot_1x; - HotPoint hot_2x; +// Cursor resource data indexed by CursorType. Make sure to respect the order +// defined at ui/base/cursor/mojom/cursor_type.mojom. +constexpr absl::optional<CursorResourceData> kNormalCursorResourceData[] = { + {{CursorType::kPointer, IDR_AURA_CURSOR_PTR, {4, 4}, {7, 7}}}, + {{CursorType::kCross, IDR_AURA_CURSOR_CROSSHAIR, {12, 12}, {24, 24}}}, + {{CursorType::kHand, IDR_AURA_CURSOR_HAND, {9, 4}, {19, 8}}}, + {{CursorType::kIBeam, IDR_AURA_CURSOR_IBEAM, {12, 12}, {24, 25}}}, + {{CursorType::kWait, IDR_AURA_CURSOR_THROBBER, {7, 7}, {14, 14}}}, + {{CursorType::kHelp, IDR_AURA_CURSOR_HELP, {4, 4}, {8, 9}}}, + {{CursorType::kEastResize, + IDR_AURA_CURSOR_EAST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthResize, + IDR_AURA_CURSOR_NORTH_RESIZE, + {11, 12}, + {23, 23}}}, + {{CursorType::kNorthEastResize, + IDR_AURA_CURSOR_NORTH_EAST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthWestResize, + IDR_AURA_CURSOR_NORTH_WEST_RESIZE, + {11, 11}, + {24, 23}}}, + {{CursorType::kSouthResize, + IDR_AURA_CURSOR_SOUTH_RESIZE, + {11, 12}, + {23, 23}}}, + {{CursorType::kSouthEastResize, + IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, + {11, 11}, + {24, 23}}}, + {{CursorType::kSouthWestResize, + IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kWestResize, + IDR_AURA_CURSOR_WEST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthSouthResize, + IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, + {11, 12}, + {23, 23}}}, + {{CursorType::kEastWestResize, + IDR_AURA_CURSOR_EAST_WEST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthEastSouthWestResize, + IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthWestSouthEastResize, + IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, + {11, 11}, + {24, 23}}}, + {{CursorType::kColumnResize, + IDR_AURA_CURSOR_COL_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kRowResize, IDR_AURA_CURSOR_ROW_RESIZE, {11, 12}, {23, 23}}}, + /*CursorType::kMiddlePanning*/ {}, + /*CursorType::kEastPanning*/ {}, + /*CursorType::kNorthPanning*/ {}, + /*CursorType::kNorthEastPanning*/ {}, + /*CursorType::kNorthWestPanning*/ {}, + /*CursorType::kSouthPanning*/ {}, + /*CursorType::kSouthEastPanning*/ {}, + /*CursorType::kSouthWestPanning*/ {}, + /*CursorType::kWestPanning*/ {}, + {{CursorType::kMove, IDR_AURA_CURSOR_MOVE, {11, 11}, {23, 23}}}, + {{CursorType::kVerticalText, + IDR_AURA_CURSOR_XTERM_HORIZ, + {12, 11}, + {26, 23}}}, + {{CursorType::kCell, IDR_AURA_CURSOR_CELL, {11, 11}, {24, 23}}}, + {{CursorType::kContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, {4, 4}, {8, 9}}}, + {{CursorType::kAlias, IDR_AURA_CURSOR_ALIAS, {8, 6}, {15, 11}}}, + {{CursorType::kProgress, IDR_AURA_CURSOR_THROBBER, {7, 7}, {14, 14}}}, + {{CursorType::kNoDrop, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}}, + {{CursorType::kCopy, IDR_AURA_CURSOR_COPY, {9, 9}, {18, 18}}}, + /*CursorType::kNone*/ {}, + {{CursorType::kNotAllowed, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}}, + {{CursorType::kZoomIn, IDR_AURA_CURSOR_ZOOM_IN, {10, 10}, {20, 20}}}, + {{CursorType::kZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, {10, 10}, {20, 20}}}, + {{CursorType::kGrab, IDR_AURA_CURSOR_GRAB, {8, 5}, {16, 10}}}, + {{CursorType::kGrabbing, IDR_AURA_CURSOR_GRABBING, {9, 9}, {18, 18}}}, + /*CursorType::kMiddlePanningVertical*/ {}, + /*CursorType::kMiddlePanningHorizontal*/ {}, + /*CursorType::kCustom*/ {}, + /*CursorType::kDndNone*/ {}, + /*CursorType::kDndMove*/ {}, + /*CursorType::kDndCopy*/ {}, + /*CursorType::kDndLink*/ {}, + {{CursorType::kEastWestNoResize, + IDR_AURA_CURSOR_EAST_WEST_NO_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthSouthNoResize, + IDR_AURA_CURSOR_NORTH_SOUTH_NO_RESIZE, + {11, 12}, + {23, 23}}}, + {{CursorType::kNorthEastSouthWestNoResize, + IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_NO_RESIZE, + {12, 11}, + {25, 23}}}, + {{CursorType::kNorthWestSouthEastNoResize, + IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_NO_RESIZE, + {11, 11}, + {24, 23}}}, }; -struct CursorSizeData { - const ui::CursorSize id; - const CursorData* cursors; - const int length; +static_assert(std::size(kNormalCursorResourceData) == + static_cast<int>(CursorType::kMaxValue) + 1); + +constexpr absl::optional<CursorResourceData> kLargeCursorResourceData[] = { + {{CursorType::kPointer, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {20, 20}}}, + {{CursorType::kCross, IDR_AURA_CURSOR_BIG_CROSSHAIR, {30, 32}, {60, 64}}}, + {{CursorType::kHand, IDR_AURA_CURSOR_BIG_HAND, {25, 7}, {50, 14}}}, + {{CursorType::kIBeam, IDR_AURA_CURSOR_BIG_IBEAM, {30, 32}, {60, 64}}}, + {{CursorType::kWait, + // TODO(https://crbug.com/336867): create IDR_AURA_CURSOR_BIG_THROBBER. + IDR_AURA_CURSOR_THROBBER, + {7, 7}, + {14, 14}}}, + {{CursorType::kHelp, IDR_AURA_CURSOR_BIG_HELP, {10, 11}, {20, 22}}}, + {{CursorType::kEastResize, + IDR_AURA_CURSOR_BIG_EAST_RESIZE, + {35, 29}, + {70, 58}}}, + {{CursorType::kNorthResize, + IDR_AURA_CURSOR_BIG_NORTH_RESIZE, + {29, 32}, + {58, 64}}}, + {{CursorType::kNorthEastResize, + IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE, + {31, 28}, + {62, 56}}}, + {{CursorType::kNorthWestResize, + IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE, + {28, 28}, + {56, 56}}}, + {{CursorType::kSouthResize, + IDR_AURA_CURSOR_BIG_SOUTH_RESIZE, + {29, 32}, + {58, 64}}}, + {{CursorType::kSouthEastResize, + IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE, + {28, 28}, + {56, 56}}}, + {{CursorType::kSouthWestResize, + IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE, + {31, 28}, + {62, 56}}}, + {{CursorType::kWestResize, + IDR_AURA_CURSOR_BIG_WEST_RESIZE, + {35, 29}, + {70, 58}}}, + {{CursorType::kNorthSouthResize, + IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE, + {29, 32}, + {58, 64}}}, + {{CursorType::kEastWestResize, + IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE, + {35, 29}, + {70, 58}}}, + {{CursorType::kNorthEastSouthWestResize, + IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE, + {32, 30}, + {64, 60}}}, + {{CursorType::kNorthWestSouthEastResize, + IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE, + {32, 31}, + {64, 62}}}, + {{CursorType::kColumnResize, + IDR_AURA_CURSOR_BIG_COL_RESIZE, + {35, 29}, + {70, 58}}}, + {{CursorType::kRowResize, + IDR_AURA_CURSOR_BIG_ROW_RESIZE, + {29, 32}, + {58, 64}}}, + /*CursorType::kMiddlePanning*/ {}, + /*CursorType::kEastPanning*/ {}, + /*CursorType::kNorthPanning*/ {}, + /*CursorType::kNorthEastPanning*/ {}, + /*CursorType::kNorthWestPanning*/ {}, + /*CursorType::kSouthPanning*/ {}, + /*CursorType::kSouthEastPanning*/ {}, + /*CursorType::kSouthWestPanning*/ {}, + /*CursorType::kWestPanning*/ {}, + {{CursorType::kMove, IDR_AURA_CURSOR_BIG_MOVE, {32, 31}, {64, 62}}}, + {{CursorType::kVerticalText, + IDR_AURA_CURSOR_BIG_XTERM_HORIZ, + {32, 30}, + {64, 60}}}, + {{CursorType::kCell, IDR_AURA_CURSOR_BIG_CELL, {30, 30}, {60, 60}}}, + {{CursorType::kContextMenu, + IDR_AURA_CURSOR_BIG_CONTEXT_MENU, + {11, 11}, + {22, 22}}}, + {{CursorType::kAlias, IDR_AURA_CURSOR_BIG_ALIAS, {19, 11}, {38, 22}}}, + {{CursorType::kProgress, + // TODO(https://crbug.com/336867): create IDR_AURA_CURSOR_BIG_THROBBER. + IDR_AURA_CURSOR_THROBBER, + {7, 7}, + {14, 14}}}, + {{CursorType::kNoDrop, IDR_AURA_CURSOR_BIG_NO_DROP, {10, 10}, {20, 20}}}, + {{CursorType::kCopy, IDR_AURA_CURSOR_BIG_COPY, {21, 11}, {42, 22}}}, + /*CursorType::kNone*/ {}, + {{CursorType::kNotAllowed, + IDR_AURA_CURSOR_BIG_NO_DROP, + {10, 10}, + {20, 20}}}, + {{CursorType::kZoomIn, IDR_AURA_CURSOR_BIG_ZOOM_IN, {25, 26}, {50, 52}}}, + {{CursorType::kZoomOut, IDR_AURA_CURSOR_BIG_ZOOM_OUT, {26, 26}, {52, 52}}}, + {{CursorType::kGrab, IDR_AURA_CURSOR_BIG_GRAB, {21, 11}, {42, 22}}}, + {{CursorType::kGrabbing, IDR_AURA_CURSOR_BIG_GRABBING, {20, 12}, {40, 24}}}, + /*CursorType::kMiddlePanningVertical*/ {}, + /*CursorType::kMiddlePanningHorizontal*/ {}, + /*CursorType::kCustom*/ {}, + /*CursorType::kDndNone*/ {}, + /*CursorType::kDndMove*/ {}, + /*CursorType::kDndCopy*/ {}, + /*CursorType::kDndLink*/ {}, + {{CursorType::kEastWestNoResize, + IDR_AURA_CURSOR_BIG_EAST_WEST_NO_RESIZE, + {35, 29}, + {70, 58}}}, + {{CursorType::kNorthSouthNoResize, + IDR_AURA_CURSOR_BIG_NORTH_SOUTH_NO_RESIZE, + {29, 32}, + {58, 64}}}, + {{CursorType::kNorthEastSouthWestNoResize, + IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_NO_RESIZE, + {32, 30}, + {64, 60}}}, + {{CursorType::kNorthWestSouthEastNoResize, + IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_NO_RESIZE, + {32, 31}, + {64, 62}}}, }; -const CursorData kNormalCursors[] = { - {CursorType::kNull, IDR_AURA_CURSOR_PTR, {4, 4}, {7, 7}}, - {CursorType::kPointer, IDR_AURA_CURSOR_PTR, {4, 4}, {7, 7}}, - {CursorType::kNoDrop, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}, - {CursorType::kNotAllowed, IDR_AURA_CURSOR_NO_DROP, {9, 9}, {18, 18}}, - {CursorType::kCopy, IDR_AURA_CURSOR_COPY, {9, 9}, {18, 18}}, - {CursorType::kHand, IDR_AURA_CURSOR_HAND, {9, 4}, {19, 8}}, - {CursorType::kMove, IDR_AURA_CURSOR_MOVE, {11, 11}, {23, 23}}, - {CursorType::kNorthEastResize, - IDR_AURA_CURSOR_NORTH_EAST_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kSouthWestResize, - IDR_AURA_CURSOR_SOUTH_WEST_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kSouthEastResize, - IDR_AURA_CURSOR_SOUTH_EAST_RESIZE, - {11, 11}, - {24, 23}}, - {CursorType::kNorthWestResize, - IDR_AURA_CURSOR_NORTH_WEST_RESIZE, - {11, 11}, - {24, 23}}, - {CursorType::kNorthResize, - IDR_AURA_CURSOR_NORTH_RESIZE, - {11, 12}, - {23, 23}}, - {CursorType::kSouthResize, - IDR_AURA_CURSOR_SOUTH_RESIZE, - {11, 12}, - {23, 23}}, - {CursorType::kEastResize, IDR_AURA_CURSOR_EAST_RESIZE, {12, 11}, {25, 23}}, - {CursorType::kWestResize, IDR_AURA_CURSOR_WEST_RESIZE, {12, 11}, {25, 23}}, - {CursorType::kIBeam, IDR_AURA_CURSOR_IBEAM, {12, 12}, {24, 25}}, - {CursorType::kAlias, IDR_AURA_CURSOR_ALIAS, {8, 6}, {15, 11}}, - {CursorType::kCell, IDR_AURA_CURSOR_CELL, {11, 11}, {24, 23}}, - {CursorType::kContextMenu, IDR_AURA_CURSOR_CONTEXT_MENU, {4, 4}, {8, 9}}, - {CursorType::kCross, IDR_AURA_CURSOR_CROSSHAIR, {12, 12}, {24, 24}}, - {CursorType::kHelp, IDR_AURA_CURSOR_HELP, {4, 4}, {8, 9}}, - {CursorType::kVerticalText, - IDR_AURA_CURSOR_XTERM_HORIZ, - {12, 11}, - {26, 23}}, - {CursorType::kZoomIn, IDR_AURA_CURSOR_ZOOM_IN, {10, 10}, {20, 20}}, - {CursorType::kZoomOut, IDR_AURA_CURSOR_ZOOM_OUT, {10, 10}, {20, 20}}, - {CursorType::kRowResize, IDR_AURA_CURSOR_ROW_RESIZE, {11, 12}, {23, 23}}, - {CursorType::kColumnResize, IDR_AURA_CURSOR_COL_RESIZE, {12, 11}, {25, 23}}, - {CursorType::kEastWestNoResize, - IDR_AURA_CURSOR_EAST_WEST_NO_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kEastWestResize, - IDR_AURA_CURSOR_EAST_WEST_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kNorthSouthNoResize, - IDR_AURA_CURSOR_NORTH_SOUTH_NO_RESIZE, - {11, 12}, - {23, 23}}, - {CursorType::kNorthSouthResize, - IDR_AURA_CURSOR_NORTH_SOUTH_RESIZE, - {11, 12}, - {23, 23}}, - {CursorType::kNorthEastSouthWestNoResize, - IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_NO_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kNorthEastSouthWestResize, - IDR_AURA_CURSOR_NORTH_EAST_SOUTH_WEST_RESIZE, - {12, 11}, - {25, 23}}, - {CursorType::kNorthWestSouthEastNoResize, - IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_NO_RESIZE, - {11, 11}, - {24, 23}}, - {CursorType::kNorthWestSouthEastResize, - IDR_AURA_CURSOR_NORTH_WEST_SOUTH_EAST_RESIZE, - {11, 11}, - {24, 23}}, - {CursorType::kGrab, IDR_AURA_CURSOR_GRAB, {8, 5}, {16, 10}}, - {CursorType::kGrabbing, IDR_AURA_CURSOR_GRABBING, {9, 9}, {18, 18}}, - {CursorType::kWait, IDR_AURA_CURSOR_THROBBER, {7, 7}, {14, 14}}, - {CursorType::kProgress, IDR_AURA_CURSOR_THROBBER, {7, 7}, {14, 14}}, -}; - -const CursorData kLargeCursors[] = { - // The 2x hotspots should be double of the 1x, even though the cursors are - // shown as same size as 1x (64x64), because in 2x dpi screen, the 1x large - // cursor assets (64x64) are internally enlarged to the double size - // (128x128) - // by ResourceBundleImageSource. - {CursorType::kNull, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {20, 20}}, - {CursorType::kPointer, IDR_AURA_CURSOR_BIG_PTR, {10, 10}, {20, 20}}, - {CursorType::kNoDrop, IDR_AURA_CURSOR_BIG_NO_DROP, {10, 10}, {20, 20}}, - {CursorType::kNotAllowed, IDR_AURA_CURSOR_BIG_NO_DROP, {10, 10}, {20, 20}}, - {CursorType::kCopy, IDR_AURA_CURSOR_BIG_COPY, {21, 11}, {42, 22}}, - {CursorType::kHand, IDR_AURA_CURSOR_BIG_HAND, {25, 7}, {50, 14}}, - {CursorType::kMove, IDR_AURA_CURSOR_BIG_MOVE, {32, 31}, {64, 62}}, - {CursorType::kNorthEastResize, - IDR_AURA_CURSOR_BIG_NORTH_EAST_RESIZE, - {31, 28}, - {62, 56}}, - {CursorType::kSouthWestResize, - IDR_AURA_CURSOR_BIG_SOUTH_WEST_RESIZE, - {31, 28}, - {62, 56}}, - {CursorType::kSouthEastResize, - IDR_AURA_CURSOR_BIG_SOUTH_EAST_RESIZE, - {28, 28}, - {56, 56}}, - {CursorType::kNorthWestResize, - IDR_AURA_CURSOR_BIG_NORTH_WEST_RESIZE, - {28, 28}, - {56, 56}}, - {CursorType::kNorthResize, - IDR_AURA_CURSOR_BIG_NORTH_RESIZE, - {29, 32}, - {58, 64}}, - {CursorType::kSouthResize, - IDR_AURA_CURSOR_BIG_SOUTH_RESIZE, - {29, 32}, - {58, 64}}, - {CursorType::kEastResize, - IDR_AURA_CURSOR_BIG_EAST_RESIZE, - {35, 29}, - {70, 58}}, - {CursorType::kWestResize, - IDR_AURA_CURSOR_BIG_WEST_RESIZE, - {35, 29}, - {70, 58}}, - {CursorType::kIBeam, IDR_AURA_CURSOR_BIG_IBEAM, {30, 32}, {60, 64}}, - {CursorType::kAlias, IDR_AURA_CURSOR_BIG_ALIAS, {19, 11}, {38, 22}}, - {CursorType::kCell, IDR_AURA_CURSOR_BIG_CELL, {30, 30}, {60, 60}}, - {CursorType::kContextMenu, - IDR_AURA_CURSOR_BIG_CONTEXT_MENU, - {11, 11}, - {22, 22}}, - {CursorType::kCross, IDR_AURA_CURSOR_BIG_CROSSHAIR, {30, 32}, {60, 64}}, - {CursorType::kHelp, IDR_AURA_CURSOR_BIG_HELP, {10, 11}, {20, 22}}, - {CursorType::kVerticalText, - IDR_AURA_CURSOR_BIG_XTERM_HORIZ, - {32, 30}, - {64, 60}}, - {CursorType::kZoomIn, IDR_AURA_CURSOR_BIG_ZOOM_IN, {25, 26}, {50, 52}}, - {CursorType::kZoomOut, IDR_AURA_CURSOR_BIG_ZOOM_OUT, {26, 26}, {52, 52}}, - {CursorType::kRowResize, - IDR_AURA_CURSOR_BIG_ROW_RESIZE, - {29, 32}, - {58, 64}}, - {CursorType::kColumnResize, - IDR_AURA_CURSOR_BIG_COL_RESIZE, - {35, 29}, - {70, 58}}, - {CursorType::kEastWestNoResize, - IDR_AURA_CURSOR_BIG_EAST_WEST_NO_RESIZE, - {35, 29}, - {70, 58}}, - {CursorType::kEastWestResize, - IDR_AURA_CURSOR_BIG_EAST_WEST_RESIZE, - {35, 29}, - {70, 58}}, - {CursorType::kNorthSouthNoResize, - IDR_AURA_CURSOR_BIG_NORTH_SOUTH_NO_RESIZE, - {29, 32}, - {58, 64}}, - {CursorType::kNorthSouthResize, - IDR_AURA_CURSOR_BIG_NORTH_SOUTH_RESIZE, - {29, 32}, - {58, 64}}, - {CursorType::kNorthEastSouthWestNoResize, - IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_NO_RESIZE, - {32, 30}, - {64, 60}}, - {CursorType::kNorthEastSouthWestResize, - IDR_AURA_CURSOR_BIG_NORTH_EAST_SOUTH_WEST_RESIZE, - {32, 30}, - {64, 60}}, - {CursorType::kNorthWestSouthEastNoResize, - IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_NO_RESIZE, - {32, 31}, - {64, 62}}, - {CursorType::kNorthWestSouthEastResize, - IDR_AURA_CURSOR_BIG_NORTH_WEST_SOUTH_EAST_RESIZE, - {32, 31}, - {64, 62}}, - {CursorType::kGrab, IDR_AURA_CURSOR_BIG_GRAB, {21, 11}, {42, 22}}, - {CursorType::kGrabbing, IDR_AURA_CURSOR_BIG_GRABBING, {20, 12}, {40, 24}}, - // TODO(https://crbug.com/336867): create IDR_AURA_CURSOR_BIG_THROBBER. -}; - -const CursorSizeData kCursorSizes[] = { - {ui::CursorSize::kNormal, kNormalCursors, std::size(kNormalCursors)}, - {ui::CursorSize::kLarge, kLargeCursors, std::size(kLargeCursors)}, -}; - -const CursorSizeData* GetCursorSizeByType(ui::CursorSize cursor_size) { - for (size_t i = 0; i < std::size(kCursorSizes); ++i) { - if (kCursorSizes[i].id == cursor_size) { - return &kCursorSizes[i]; - } - } - - return nullptr; -} - -bool SearchTable(const CursorData* table, - size_t table_length, - CursorType id, - float scale_factor, - int* resource_id, - gfx::Point* point) { - DCHECK_NE(scale_factor, 0); - - bool resource_2x_available = - ui::ResourceBundle::GetSharedInstance().GetMaxResourceScaleFactor() == - ui::k200Percent; - for (size_t i = 0; i < table_length; ++i) { - if (table[i].id == id) { - *resource_id = table[i].resource_id; - *point = scale_factor == 1.0f || !resource_2x_available - ? gfx::Point(table[i].hot_1x.x, table[i].hot_1x.y) - : gfx::Point(table[i].hot_2x.x, table[i].hot_2x.y); - return true; - } - } - - return false; -} +static_assert(std::size(kLargeCursorResourceData) == + static_cast<int>(CursorType::kMaxValue) + 1); } // namespace @@ -441,21 +448,38 @@ } bool GetCursorDataFor(ui::CursorSize cursor_size, - CursorType id, + CursorType type, float scale_factor, int* resource_id, gfx::Point* point) { - const CursorSizeData* cursor_set = GetCursorSizeByType(cursor_size); - if (cursor_set && SearchTable(cursor_set->cursors, cursor_set->length, id, - scale_factor, resource_id, point)) { - return true; + DCHECK_NE(type, CursorType::kCustom); + + // TODO(https://crbug.com/1270302: temporary check until GetCursorDataFor is + // replaced by GetCursorData, which is only used internally by CursorLoader. + if (type == CursorType::kNone) { + return false; } - // Falls back to the default cursor set. - cursor_set = GetCursorSizeByType(ui::CursorSize::kNormal); - DCHECK(cursor_set); - return SearchTable(cursor_set->cursors, cursor_set->length, id, scale_factor, - resource_id, point); + // TODO(htts://crbug.com/1190818): currently, kNull is treated as kPointer. + CursorType t = type == CursorType::kNull ? CursorType::kPointer : type; + absl::optional<CursorResourceData> resource = + cursor_size == ui::CursorSize::kNormal + ? kNormalCursorResourceData[static_cast<int>(t)] + : kLargeCursorResourceData[static_cast<int>(t)]; + if (!resource) { + return false; + } + + DCHECK_EQ(resource->type, t); + *resource_id = resource->id; + *point = resource->hotspot_1x; + bool resource_2x_available = + ui::ResourceBundle::GetSharedInstance().GetMaxResourceScaleFactor() == + ui::k200Percent; + if (scale_factor != 1.0f && resource_2x_available) { + *point = resource->hotspot_2x; + } + return true; } } // namespace wm
diff --git a/ui/wm/core/cursor_util.h b/ui/wm/core/cursor_util.h index 9a2c1c0..e142c70a 100644 --- a/ui/wm/core/cursor_util.h +++ b/ui/wm/core/cursor_util.h
@@ -25,7 +25,7 @@ COMPONENT_EXPORT(UI_WM) absl::optional<ui::CursorData> GetCursorData( - ui::mojom::CursorType id, + ui::mojom::CursorType type, ui::CursorSize size, float scale, display::Display::Rotation rotation); @@ -39,13 +39,12 @@ SkBitmap* bitmap_in_out, gfx::Point* hotpoint_in_out); -// Returns data about |id|, where id is a cursor constant like -// ui::mojom::CursorType::kHelp. The IDR will be placed in |resource_id| and -// the hotspots for the different DPIs will be placed in |hot_1x| and -// |hot_2x|. Returns false if |id| is invalid. +// Returns data about the cursor `type`. The IDR will be placed in `resource_id` +// and the hotspot in `point`. Returns false if resource data for `type` isn't +// available. COMPONENT_EXPORT(UI_WM) bool GetCursorDataFor(ui::CursorSize cursor_size, - ui::mojom::CursorType id, + ui::mojom::CursorType type, float scale_factor, int* resource_id, gfx::Point* point);
diff --git a/url/android/origin_android.cc b/url/android/origin_android.cc index 02f17e80..a0dd271b 100644 --- a/url/android/origin_android.cc +++ b/url/android/origin_android.cc
@@ -46,7 +46,7 @@ const std::string& host = ConvertJavaStringToUTF8(env, java_host); absl::optional<base::UnguessableToken> nonce_token = - base::UnguessableToken::Deserialize2(token_high_bits, token_low_bits); + base::UnguessableToken::Deserialize(token_high_bits, token_low_bits); bool has_nonce = nonce_token.has_value(); CHECK(has_nonce == is_opaque); Origin::Nonce nonce;
diff --git a/url/origin.cc b/url/origin.cc index 7a14cde..fdc1cd09 100644 --- a/url/origin.cc +++ b/url/origin.cc
@@ -376,7 +376,7 @@ return absl::nullopt; absl::optional<base::UnguessableToken> nonce_token = - base::UnguessableToken::Deserialize2(nonce_high, nonce_low); + base::UnguessableToken::Deserialize(nonce_high, nonce_low); Origin::Nonce nonce; if (nonce_token.has_value()) {
diff --git a/weblayer/browser/js_communication/web_message_browsertest.cc b/weblayer/browser/js_communication/web_message_browsertest.cc index daf3c62..93c70a4 100644 --- a/weblayer/browser/js_communication/web_message_browsertest.cc +++ b/weblayer/browser/js_communication/web_message_browsertest.cc
@@ -167,11 +167,12 @@ // WebLayerBrowserTest: void SetUp() override { scoped_feature_list_.InitWithFeaturesAndParameters( - {{features::kBackForwardCache, + {{features::kBackForwardCache, {{}}}, + {features::kBackForwardCacheTimeToLiveControl, {// Set a very long TTL before expiration (longer than the test // timeout) so tests that are expecting deletion don't pass when // they shouldn't. - {"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}}, + {"time_to_live_seconds", "3600"}}}}, // Allow BackForwardCache for all devices regardless of their memory. {features::kBackForwardCacheMemoryControls}); WebLayerBrowserTest::SetUp();
diff --git a/weblayer/browser/password_manager_driver_factory.h b/weblayer/browser/password_manager_driver_factory.h index 27fcfb6e..cfc4494e 100644 --- a/weblayer/browser/password_manager_driver_factory.h +++ b/weblayer/browser/password_manager_driver_factory.h
@@ -7,7 +7,6 @@ #include <map> -#include "base/supports_user_data.h" #include "components/autofill/content/common/mojom/autofill_driver.mojom.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h"
diff --git a/weblayer/browser/safe_browsing/safe_browsing_service.cc b/weblayer/browser/safe_browsing/safe_browsing_service.cc index cc9c93d..9c5a4c2 100644 --- a/weblayer/browser/safe_browsing/safe_browsing_service.cc +++ b/weblayer/browser/safe_browsing/safe_browsing_service.cc
@@ -62,16 +62,18 @@ content::RenderProcessHost* render_process_host = content::RenderProcessHost::FromID(rph_id); - if (!render_process_host) + if (!render_process_host) { return; + } bool is_safe_browsing_enabled = safe_browsing::IsSafeBrowsingEnabled( *static_cast<BrowserContextImpl*>( render_process_host->GetBrowserContext()) ->pref_service()); - if (!is_safe_browsing_enabled) + if (!is_safe_browsing_enabled) { return; + } content::GetIOThreadTaskRunner({})->PostTask( FROM_HERE, @@ -128,7 +130,8 @@ }, base::Unretained(this)), wc_getter, frame_tree_node_id, - url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr); + url_lookup_service ? url_lookup_service->GetWeakPtr() : nullptr, + /*hash_realtime_service=*/nullptr); } std::unique_ptr<content::NavigationThrottle> @@ -210,8 +213,9 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(safe_browsing_db_manager_); - if (started_db_manager_) + if (started_db_manager_) { return; + } started_db_manager_ = true; @@ -279,15 +283,17 @@ } network::mojom::NetworkContext* SafeBrowsingService::GetNetworkContext() { - if (!network_context_) + if (!network_context_) { return nullptr; + } return network_context_->GetNetworkContext(); } scoped_refptr<network::SharedURLLoaderFactory> SafeBrowsingService::GetURLLoaderFactory() { - if (!network_context_) + if (!network_context_) { return nullptr; + } return network_context_->GetURLLoaderFactory(); }